<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Hacker News Personal Blogs 2017 | All Blog Posts</title><link>https://hn-blogs.kronis.dev/feed.xml</link><description>A collection of blog posts from users of Hacker News, based on RSS feeds.</description><language>en-US</language><lastBuildDate>Fri, 10 Jul 2026 04:03:21 GMT</lastBuildDate><generator>rfeed v1.1.1</generator><docs>https://github.com/svpino/rfeed/blob/master/README.md</docs><item><title>Fees are a metric worth looking into but I would say that the story they tell is more of how…</title><link>https://olshansky.info/posts/2017-12-31-fees-are-a-metric-worth-looking-into-but-i-would-say-that-the-story-they-tell-is-more-of-how/</link><description>They’re actually growing at a much higher rate than I had expected! I think this is healthy given how BTC will probably be a settlement…</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 31 Dec 2017 12:38:45 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-12-31-fees-are-a-metric-worth-looking-into-but-i-would-say-that-the-story-they-tell-is-more-of-how/</guid></item><item><title>Forget Net Neutrality. Think personal clouds instead</title><link>https://stop.zona-m.net/2017/12/forget-net-neutrality.-think-personal-clouds-instead/</link><description>&lt;p&gt;The &lt;a href="https://www.theguardian.com/technology/2017/dec/14/net-neutrality-fcc-rules-open-internet"&gt;FCC Net Neutrality decision on Dec. 14th, 2017&lt;/a&gt; (*) has rightly caused a lot of outrage, and concrete reactions, both political (e.g. petitions) and technical ones&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 31 Dec 2017 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/12/forget-net-neutrality.-think-personal-clouds-instead/</guid></item><item><title>December Begins</title><link>https://faingezicht.com/photos/2017/12/31/december-begins-17/</link><description>December was a busy month. A lot of our friends hosted events, and it went by super fast.

Posting _December begins_ on the 31st has its own kind of irony, I guess.</description><author>Avy Faingezicht</author><pubDate>Sun, 31 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/12/31/december-begins-17/</guid></item><item><title>📸 Seoul</title><link>https://bpev.me/notes/seoul</link><author>bpev.me</author><pubDate>Sun, 31 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/seoul</guid></item><item><title>Migrating from Google (and more)</title><link>https://captnemo.in/blog/2017/12/31/migrating-from-google/</link><description>&lt;div class="toc"&gt;
  &lt;h4 id="contents"&gt;Contents&lt;/h4&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;a href="#email"&gt;Email&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#google-play-music"&gt;Google Play Music&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#google-keep"&gt;Google Keep&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#phone"&gt;Phone&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href="#microg-core"&gt;microG Core&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="#unifiedlp"&gt;UnifiedLP&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="#maps"&gt;Maps&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="#uber"&gt;Uber&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="#calendar-contacts"&gt;Calendar/Contacts&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="#google-play-store"&gt;Google Play Store&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href="#lastpass"&gt;LastPass&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="#github"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;As part of working on my home-server setup, I wanted to move off few online services to ones that I manage. This is a list of what all services I used and what I’ve migrated to .&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: I got frustrated with &lt;a href="https://music.google.com" title="Google Play Music"&gt;Google Play Music&lt;/a&gt; a few times. Synced songs would not show up across all clients immediately (I had to refresh,uninstall,reinstall), and I hated the client limits it would impose. Decided to try &lt;a href="https://microg.org/" title="MicroG is a free-as-in-freedom re-implementation of Google’s proprietary Android user space apps and libraries."&gt;microG&lt;/a&gt; on my phone at the same time, and it slowly came together.&lt;/p&gt;

&lt;h1 id="email"&gt;Email&lt;/h1&gt;

&lt;p&gt;I’ve been using email on my own domain for quite some time (&lt;code class="language-plaintext highlighter-rouge"&gt;captnemo.in&lt;/code&gt;), but it was managed by a Outlook+Google combination that I didn’t like very much.&lt;/p&gt;

&lt;p&gt;I switched to &lt;a href="http://www.migadu.com/" title="Migadu is email hosting built and operated by humans"&gt;Migadu&lt;/a&gt; sometime last year, and have been quite happy with the service. Their &lt;a href="https://www.migadu.com/privacy/"&gt;Privacy Policy&lt;/a&gt;, and &lt;a href="https://www.migadu.com/procon/"&gt;pro/cons&lt;/a&gt; section on the website is a pleasure to read.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: Email is the central-point of your online digital identity. Use your own-domain, at the very least. That way, you’re atleast protected if Google decides to suspend your account. Self-hosting email is a big responsibility that requires critical uptime, and I didn’t want to manage that, so went with migadu.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why Migadu&lt;/em&gt;: You should read their &lt;a href="https://news.ycombinator.com/item?id=13048334"&gt;HN thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Caviats&lt;/em&gt;: They don’t yet offer 2FA, but hopefully that should be fixed soon. Their spam filters aren’t the best either. Migadu even has a &lt;a href="https://www.migadu.com/procon/#the-drawbacks-list"&gt;Drawbacks&lt;/a&gt; section on their website that you &lt;em&gt;must read&lt;/em&gt; before signing up.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Alternatives&lt;/em&gt;: RiseUp, FastMail.&lt;/p&gt;

&lt;h1 id="google-play-music"&gt;Google Play Music&lt;/h1&gt;

&lt;p&gt;I quite liked &lt;a href="https://music.google.com" title="Google Play Music"&gt;Google Play Music&lt;/a&gt;. While their subscription offering is horrible in India, I was a happy user of their “bring-your-own-music” plan. In fact, the most used Google service on my phone happened to be Google Play Music! I switched to a nice subsonic fork called [AirSonic][airsonic], which gives me the ability to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Listen on as many devices as I want (Google has some limits)&lt;/li&gt;
  &lt;li&gt;Listen using multiple clients at the same time&lt;/li&gt;
  &lt;li&gt;Stream at whatever bandwidth I pick (I stream at 64kbps over 2G networks!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m currently using &lt;a href="https://www.clementine-player.org/"&gt;Clementine&lt;/a&gt; on the Desktop (which unfortunately, doesn’t cache music), and &lt;a href="https://github.com/ultrasonic/ultrasonic/"&gt;UltraSonic&lt;/a&gt; on the phone. Airsonic even supports bookmarks, so listening to audiobooks becomes much more simpler.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: I didn’t like Google Play Music limits, plus I wanted to try the “phone-without-google” experiment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why AirSonic&lt;/em&gt;: &lt;a href="https://github.com/sindremehus/subsonic"&gt;Subsonic&lt;/a&gt; is now closed source, and the &lt;a href="https://www.reddit.com/r/selfhosted/comments/6saiac/airsonic_is_out/dlbea94/"&gt;Libresonic developers forked off to AirSonic&lt;/a&gt;, which is under active development. It is supports across all devices that I use, while &lt;a href="http://ampache.org/"&gt;Ampache&lt;/a&gt; has spotty Android support.&lt;/p&gt;

&lt;h1 id="google-keep"&gt;Google Keep&lt;/h1&gt;

&lt;p&gt;I switched across to &lt;a href="https://workflowy.com"&gt;WorkFlowy&lt;/a&gt;, which has both a Android and a Linux app (both based on webviews). I’ve used it for years, and it is a great tool. Moreover, I’m also using DAVDroid sync for Open Tasks app on my phone. Both of these work well enough offline.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: I didn’t use Keep much, and WorkFlowy is a far better tool anyway.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why WorkFlowy&lt;/em&gt;: It is &lt;em&gt;the best&lt;/em&gt; note-taking/list tool I’ve used.&lt;/p&gt;

&lt;h1 id="phone"&gt;Phone&lt;/h1&gt;

&lt;p&gt;I switched over to the &lt;a href="https://lineage.microg.org/"&gt;microG fork of lineageOS&lt;/a&gt; which offers a reverse-engineered implementation of the Google Play Services modules. It includes:&lt;/p&gt;

&lt;h2 id="microg-core"&gt;microG Core&lt;/h2&gt;

&lt;p&gt;Which talks to Google for Sync, Account purposes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: Saves me a lot of battery. I can uninstall this, unlike Google Play Services.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cons&lt;/em&gt;: Not all google services are supported very well. Push notifications have some issues on my phone. See the &lt;a href="https://github.com/microg/android_packages_apps_GmsCore/wiki/Implementation-Status"&gt;Wiki&lt;/a&gt; for Implementation Status.&lt;/p&gt;

&lt;h2 id="unifiedlp"&gt;UnifiedLP&lt;/h2&gt;

&lt;p&gt;Instead of the Google Location Provider. I use the Mozilla Location Services, along with Mozilla Stumbler to help improve their data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: Google doesn’t need to know where I am.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Caviats&lt;/em&gt;: GALP (Google Assisted Location Provider) does GPS locks much faster in comparision. However, I’ve found the Mozilla Location Services coverage in Bangalore to be pretty good.&lt;/p&gt;

&lt;h2 id="maps"&gt;Maps&lt;/h2&gt;

&lt;p&gt;Stil looking for decent alternatives.&lt;/p&gt;

&lt;h2 id="uber"&gt;Uber&lt;/h2&gt;

&lt;p&gt;microG comes with a Google Maps shim that talks to Open Street Maps. The maps feature on Uber worked fine with that shim, however booking cabs was not always possible. I switched over to &lt;code class="language-plaintext highlighter-rouge"&gt;m.uber.com&lt;/code&gt; which worked quite well for some time.&lt;/p&gt;

&lt;p&gt;Uber doesn’t really spend resources on their mobile site though, and it would ocassionaly stop working. Especially with regards to payments. I’ve switched over to the Ola mobile website, which works pretty well. I keep the OlaMoney app for recharging the OlaMoney wallet alongside.&lt;/p&gt;

&lt;p&gt;Uber-&amp;gt;Ola switch was also partially motivated by &lt;a href="https://www.theguardian.com/technology/2017/jun/18/uber-travis-kalanick-scandal-pr-disaster-timeline"&gt;how-badly-run Uber is&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="calendarcontacts"&gt;Calendar/Contacts&lt;/h2&gt;

&lt;p&gt;Most implementations support caldav/carddav for calendar/contacts sync. I’m using DAVDroid for syncing to a self-hosted &lt;a href="https://radicale.org" title="A Free and Open-Source CalDAV and CardDAV Server, runs on Python"&gt;Radicale Server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: I’ve always had contacts synced to Google, so it was always my-single-source-of-truth for contacts. But since I’m on a different email provider now, it makes sense to move off those contacts as well. Radicale also lets me manage multiple addressbooks very easily.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why Radicale&lt;/em&gt;: I looked &lt;a href="https://github.com/Kickball/awesome-selfhosted#calendaring-and-contacts-management"&gt;around at alternatives&lt;/a&gt;, and 2 looked promising: Sabre.io, and Radicale. Sabre is no longer under development, so I picked Radicale, which also happened to have a &lt;a href="https://hub.docker.com/r/tomsquest/docker-radicale/"&gt;regularly updated docker image&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="google-play-store"&gt;Google Play Store&lt;/h2&gt;

&lt;p&gt;Switch to &lt;a href="https://f-droid.org/"&gt;FDroid&lt;/a&gt; - It has some apps that &lt;a href="https://adaway.org/"&gt;Google doesn’t&lt;/a&gt; &lt;a href="https://newpipe.schabi.org/"&gt;like&lt;/a&gt;, and some more. Moreover, you can use YALP Store to download any applications from the Play Store. You can even run a FDroid repository for the apps you use from Play Store, as an alternative. See &lt;a href="https://shadow53.com/android/no-gapps/faq/can-i-use-the-official-play-store-with-microg/"&gt;this excellent&lt;/a&gt; guide on the various options.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: Play Store is tightly linked to Google Play Services, and doesn’t play nice with &lt;a href="https://microg.org/" title="MicroG is a free-as-in-freedom re-implementation of Google’s proprietary Android user space apps and libraries."&gt;microG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why FDroid&lt;/em&gt;: FDroid has &lt;a href="https://f-droid.org/docs/Reproducible_Builds/?title=Deterministic,_Reproducible_Builds"&gt;publicly verifiable builds&lt;/a&gt;, and tons of open-source applications.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why Yalp&lt;/em&gt;: Was easy enough to setup.&lt;/p&gt;

&lt;p&gt;If you’re looking to migrate to MicroG, I’d recommend going through the entire &lt;a href="https://shadow53.com/android/no-gapps/setup-guide/microg/"&gt;NO Gapps Setup Guide&lt;/a&gt; by shadow53 before proceeding.&lt;/p&gt;

&lt;h1 id="lastpass"&gt;LastPass&lt;/h1&gt;

&lt;p&gt;I’ve switched to &lt;code class="language-plaintext highlighter-rouge"&gt;pass&lt;/code&gt; along with a sync to keybase.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt;: &lt;a href="https://en.wikipedia.org/wiki/LastPass#Security_issues"&gt;LastPass has had multiple breaches&lt;/a&gt;, and a plethora of security issues (including 2 RCE vulnerabilities). Their fingerprint authentication on Android could be bypassed til recently. &lt;em&gt;I just can’t trust them any more&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why pass&lt;/em&gt;: It is built on strong crypto primitives, is open-source, and has good integration with both &lt;a href="https://github.com/cdown/passmenu"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;i3&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/browserpass/browserpass-extension"&gt;firefox&lt;/a&gt;. There is also a &lt;a href="https://git.zx2c4.com/password-store/tree/contrib/importers/lastpass2pass.rb"&gt;LastPass migration script&lt;/a&gt; that I used.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Caviats&lt;/em&gt;: Website names are used as filenames in pass, so even though passwords are encrypted, you don’t want to push it to a public Git server (since that would expose the list of services you are using). I’m using my &lt;a href="https://git.captnemo.in" title="Hosted by gitea, uptime not guaranteed"&gt;own git server&lt;/a&gt;, along with keybase git(which keeps it end-to-end encrypted, even branch names). You also need to be careful about your GPG keys, instead of a single master password.&lt;/p&gt;

&lt;h1 id="github"&gt;GitHub&lt;/h1&gt;

&lt;p&gt;For bonus, I setup a Gitea server hosted at &lt;a href="https://git.captnemo.in" title="Hosted by gitea, uptime not guaranteed"&gt;git.captnemo.in&lt;/a&gt;. &lt;a href="https://gitea.io/en-US/"&gt;Gitea&lt;/a&gt; is a fork of &lt;a href="https://gogs.io/"&gt;gogs&lt;/a&gt;, and is a single-binary go application that you can run easiy.&lt;/p&gt;

&lt;p&gt;Just running it for fun, since I’m pretty happy with my GitHub setup. However, I might move some of my sensitive repos (such as &lt;a href="https://github.com/captn3m0/dir-600l" title="Reverse engineered firmware for my D-Link 600L router"&gt;this&lt;/a&gt;) to my own host.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why Gitea&lt;/em&gt;: The other alternatives were &lt;code class="language-plaintext highlighter-rouge"&gt;gogs&lt;/code&gt;, and GitLab. There have been concerns about gogs development model, and GitLab was just too overpowered/heavy for my use case. (I’m using the home server for gaming as well, so it matters)&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" title="If this is down, wait"&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;</description><author>Nemo's Home</author><pubDate>Sun, 31 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/12/31/migrating-from-google/</guid></item><item><title>Writing first ray tracer</title><link>https://whackylabs.com/pbr/graphics/2017/12/30/writing-first-ray-tracer/</link><description>&lt;p&gt;One of the many goals I had for 2017 were:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Writing a ray tracer.&lt;/li&gt;
  &lt;li&gt;Restarting the blog.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id="writing-a-ray-tracer"&gt;Writing a ray tracer&lt;/h1&gt;

&lt;p&gt;Sometime when the trees were starting to shed their leaves for the winters, I was worried that I was falling  behind my goals for the year. I finally decided to order the book I wanted to read for many years now. The following day I placed an order for &lt;a href="http://www.pbrt.org"&gt;Physically Based Rendering&lt;/a&gt;, which arrived within a long and sleepless month.&lt;/p&gt;

&lt;p&gt;As I was close to finishing the first chapter, I realized I had never written a ray tracer. Although, many people tend to claim that writing a ray tracer is the most natural and natural first step in the beautiful world of computer graphics, or like how easy it is to write a ray tracing algorithm, as it requires no prior knowledge of any graphics API or how the graphics pipeline functions, for that matter. Still, I had never written it.&lt;/p&gt;

&lt;p&gt;The closest I had ever been to understanding a ray tracer was when following the &lt;a href="http://fabiensanglard.net/rayTracing_back_of_business_card/"&gt;dissection&lt;/a&gt; of the mysterious and amusing &lt;a href="http://eastfarthing.com/blog/2016-01-12-card/"&gt;ray tracer on a business card&lt;/a&gt;. As a follow up, I started following the articles on &lt;a href="https://www.scratchapixel.com"&gt;https://www.scratchapixel.com&lt;/a&gt; about ray tracing, to get a more in depth understanding of how would one go in order to write a ray tracer from scratch.&lt;/p&gt;

&lt;p&gt;Although, these blogs were tempting enough for me to start diving into writing my first ray tracer, but still I was too busy (read lazy) to actually do it. Then, one day I ran across the minibook &lt;a href="https://www.amazon.com/Ray-Tracing-Weekend-Minibooks-Book-ebook/dp/B01B5AODD8"&gt;Ray tracing in one weekend&lt;/a&gt;. Although the book was probably designed to be finished within a weekend, and rightfully so, still I took it really slow and maybe finished in about a month.&lt;/p&gt;

&lt;p&gt;For every chapter, I used to do my own side research as well. For example, when working on the camera, I would often go side track and read about the innards of a real life camera. How do things like appertures, depth of field are supposed to work? What is the role of a lens in camera, and so on. Also, while coding, I tried to write a bit modern-ish C++ and explore the Apple &lt;code class="language-plaintext highlighter-rouge"&gt;simd.h&lt;/code&gt; library for all my math needs, which interestingly has no or very less online presence. For example, there is no proper documentation except for the header files, and searching any thing with keywords &lt;em&gt;simd&lt;/em&gt; would return results from anything related to the SSE instruction sets to the architecture itself.&lt;/p&gt;

&lt;p&gt;Eventually, today, just when the year is about to end, I was able to render the final target image from the book!&lt;/p&gt;

&lt;p&gt;&lt;img alt="ray traced spheres" src="https://i.imgur.com/s5W3SrK.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/chunkyguy/SimpleRayTracer"&gt;https://github.com/chunkyguy/SimpleRayTracer&lt;/a&gt;&lt;/p&gt;

&lt;h1 id="restarting-the-blog"&gt;Restarting the blog&lt;/h1&gt;

&lt;p&gt;Another thing I had planned to do for a very long time was restarting this blog. The death of this blog started with some miscommunication between me and my hosting service &lt;a href="https://india.yahoosmallbusiness.com"&gt;Yahoo Small business India&lt;/a&gt;. Unfortunately my service renew date coincided with their transition to Aabaco. So every time I tried to renew my service I received a generic and unhelpful try again later error. At the same time, I was also moving continents, literally speaking. Later when I was finally settled and tried to renew the service again to my horror I received the message from them that due my failure to renew they had wiped my data from the server.&lt;/p&gt;

&lt;p&gt;Eventually, I transferred the domain name and built the blog up from whatever scrap I could find. This entire process had left me a bit wretched to say the least. Also, at the same time I was having hard time finding something interesting to focus on that I could write about.&lt;/p&gt;

&lt;p&gt;Finally, it was the goal of 2017 to restart the blog again, and if this post is published before the dawn of 2018 I believe 2017 was a great year after all for me!&lt;/p&gt;

&lt;p&gt;I hope you had a great year too! Let’s carry the positive spirit to 2018!&lt;/p&gt;</description><author>Whacky Labs</author><pubDate>Sat, 30 Dec 2017 13:02:00 GMT</pubDate><guid isPermaLink="true">https://whackylabs.com/pbr/graphics/2017/12/30/writing-first-ray-tracer/</guid></item><item><title>Transportation as a service needs better cities, not smarter cars</title><link>https://stop.zona-m.net/2017/12/transportation-as-a-service-needs-better-cities-not-smarter-cars/</link><description>&lt;p&gt;I just discovered some declarations from a former vice chairman of General Motors and a Bay Area think thank that confirm what I recently proposed about driverless cars.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 30 Dec 2017 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/12/transportation-as-a-service-needs-better-cities-not-smarter-cars/</guid></item><item><title>Favorite Books Read in 2017</title><link>http://dominik.net/favorite-books-read-in-2017.html</link><description>&lt;p&gt;My favorite books out of the 102 books (~38,000 pages) that I read in 2017:&lt;/p&gt;
&lt;h2 id="sci-fi-fantasy-and-speculative-fiction"&gt;Sci-Fi, Fantasy, and Speculative Fiction&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Revelation_Space_universe"&gt;Revelation Space series&lt;/a&gt; (&lt;a href="https://www.amazon.com/Revelation-Space-Alastair-Reynolds-ebook/dp/B001QL5MAA/ref=as_li_ss_tl?ie=UTF8&amp;amp;qid=1514657217&amp;amp;sr=8-2&amp;amp;keywords=redemption+ark&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=f41055664a42a18cf3fece1caf6581e8"&gt;Revelation Space&lt;/a&gt;, &lt;a href="https://www.amazon.com/Redemption-Ark-Revelation-Space-Book-ebook/dp/B001LFDABO/ref=as_li_ss_tl?ie=UTF8&amp;amp;qid=1514657217&amp;amp;sr=8-1&amp;amp;keywords=redemption+ark&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=e25488e31aa9deb8477a65bb20c6707d"&gt;Redemption Ark&lt;/a&gt;, &lt;a href="https://www.amazon.com/Absolution-Gap-Revelation-Space-Book-ebook/dp/B001ODO61G/ref=as_li_ss_tl?ie=UTF8&amp;amp;qid=1514657217&amp;amp;sr=8-3&amp;amp;keywords=redemption+ark&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=08e1045719744d6b7d25870efd05de7b"&gt;Absolution Gap&lt;/a&gt;) — Hard scifi space opera. Greatly enjoyable, with memorable characters, backstory, science, history, and of course the requisite galactic-scale threats.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/House-Suns-Alastair-Reynolds-ebook/dp/B002AKPECW/ref=la_B000APTREU_1_7?s=books&amp;amp;ie=UTF8&amp;amp;qid=1514657330&amp;amp;sr=1-7"&gt;House of Suns&lt;/a&gt; — Set outside the Revelation Space universe, Alastair Reynolds manages to craft a compelling tale that spans galaxies and offers new mysteries of its own.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Stories-Your-Life-Others-Chiang-ebook/dp/B0048EKOP0/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514657599&amp;amp;sr=1-1&amp;amp;keywords=stories+of+your+life+and+others&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=4e20a2c40dac4ed55e018dd2215134f1"&gt;Stories of Your Life and Others&lt;/a&gt; — Succinct almost to the point of austerity, Ted Chiang’s hauntingly written tales waste not a word to weave a web of wonder, delight, and, at times, echoing mystery.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Invisible-Planets-Contemporary-Chinese-Translation-ebook/dp/B01E3PFTXK/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658315&amp;amp;sr=1-1&amp;amp;keywords=invisible+planets&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=b205000c5d9e1a4df9fa0e6a76f01f3f"&gt;Invisible Planets&lt;/a&gt; — Translated from Chinese by &lt;a href="https://kenliu.name/"&gt;Ken Liu&lt;/a&gt; (who translated &lt;em&gt;The Three Body Problem&lt;/em&gt;), this collection of science fiction short stories offers new and intriguing perspectives on both classic and novel themes. Hao Jingfang’s &lt;a href="https://uncannymagazine.com/article/folding-beijing-2/"&gt;Folding Beijing&lt;/a&gt; struck me as particularly moving and poignant; an imaginative meditation on inequality, class, and power.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Reamde-Novel-Neal-Stephenson-ebook/dp/B004XVN0WW/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658335&amp;amp;sr=1-1&amp;amp;keywords=reamde&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=1d2b484c1e9ae007dfc1d69f20b32979"&gt;Reamde &lt;/a&gt;— A fun, rollicking romp across worlds both virtual and real, told with Stephenson’s usual brilliant flair for detailed history and similarly detailed prognostication.&lt;/p&gt;
&lt;h2 id="modern-fiction"&gt;Modern Fiction&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Neapolitan_Novels"&gt;The Neapolitan Novels&lt;/a&gt;/&lt;em&gt;L’amica geniale&lt;/em&gt; (&lt;a href="https://www.amazon.com/My-Brilliant-Friend-Neapolitan-Novels-ebook/dp/B008H7KGFC/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658443&amp;amp;sr=1-1&amp;amp;keywords=my+brilliant+friend&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=00c1a81dbd73cdd05da2b7bcdd22a550"&gt;My Brilliant Friend&lt;/a&gt;, &lt;a href="https://www.amazon.com/Story-New-Name-Neapolitan-Novels-ebook/dp/B00ETSEZDC/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658546&amp;amp;sr=1-1&amp;amp;keywords=the+story+of+a+new+name&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=cae79422a0cb57eb9c06bf90c971a9e2"&gt;The Story of a New Name&lt;/a&gt;, &lt;a href="https://www.amazon.com/Those-Who-Leave-Stay-Neapolitan-ebook/dp/B00IOE4JQK/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658443&amp;amp;sr=1-4&amp;amp;keywords=my+brilliant+friend&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=0f9465d5e36f5f17c9660c89f153d5ad"&gt;Those Who Leave and Those Who Stay&lt;/a&gt;, &lt;a href="https://www.amazon.com/Story-Lost-Child-Neapolitan-Novels-ebook/dp/B00XIYG8WE/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658443&amp;amp;sr=1-5&amp;amp;keywords=my+brilliant+friend&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=55bf48a3da8d9e26c87fa2b5440cc74e"&gt;The Story of the Lost Child&lt;/a&gt;) — Told in an evocative, warm, almost conversational style, this quadrilogy compellingly tells the story of the life of two girls who grew up in Naples, and all that life brought them to bear, and all they brought to bear to life. Moving and meaningful.&lt;/p&gt;
&lt;h2 id="classics"&gt;Classics&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Old-Man-Sea-Ernest-Hemingway-ebook/dp/B07785LD3B/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658614&amp;amp;sr=1-1&amp;amp;keywords=old+man+and+the+sea&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=83a3843ed5b674c4a30f98c13d099f72"&gt;The Old Man and the Sea&lt;/a&gt; — Somehow I hadn’t read this classic until this year. Hemingway at his finest: a simple tale, beautifully told.&lt;/p&gt;
&lt;h2 id="history"&gt;History&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Dreamland-True-Americas-Opiate-Epidemic-ebook/dp/B00U19DTS0/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658638&amp;amp;sr=1-1&amp;amp;keywords=dreamland&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=8916d579768eb4119112b431eca9bbe2"&gt;Dreamland&lt;/a&gt; — Powerful exposition on the modern history of the opiate drug trade in the United States: how it came about, how it prospered, how its tale interweaves with that of prescription painkillers, and how it rages on today, with more Americans dying each year to drug overdoses than die in car crashes.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Way-Strangers-Encounters-Islamic-State-ebook/dp/B018PD2HIG/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658659&amp;amp;sr=1-1&amp;amp;keywords=way+of+strangers&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=307dd8554186490c59453f3720642319"&gt;The Way of Strangers&lt;/a&gt; — Why would someone join the Islamic State? This book examines that question both at the personal and global level.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Dynasty-Rise-Fall-House-Caesar-ebook/dp/B00SPVPXXA/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658683&amp;amp;sr=1-2&amp;amp;keywords=dynasty&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=587ca479987a53806c38b8b0750cdaba"&gt;Dynasty&lt;/a&gt; — Caesar is dead. Long live Caesar. This book explores the immediate history of Rome after the murder of Julius Caesar, narrating the machinations and consolidations of power that led to the reign of the emperors for the next several hundred years.&lt;/p&gt;
&lt;h2 id="economics"&gt;Economics&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Seeing-Like-State-Condition-Institution-ebook/dp/B00D8JJYWA/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658704&amp;amp;sr=1-1&amp;amp;keywords=seeing+like+a+state&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=a4b4d12e9ed7c282383243605ab0ed3c"&gt;Seeing Like a State &lt;/a&gt;— An amazing book. Introduces the powerful lenses of &lt;em&gt;legibility&lt;/em&gt; and &lt;em&gt;metis&lt;/em&gt;; illustrates, with examples from scientific forestry to communist Russia, the dangers of hubris and model-blindness. Thought provoking, particularly considering the increasing legibility and inherent reductionism of a future mediated by ever-more-prevalent technology.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Rise-Fall-American-Growth-Princeton-ebook/dp/B071W7JCKW/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514658732&amp;amp;sr=1-1&amp;amp;keywords=rise+and+fall+of+american+growth&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=9b929f83fbb2cc794b670f501afb82d4"&gt;The Rise and Fall of American Growth&lt;/a&gt; — Argues that 1870 to 1970 comprised the most productive hundred years of history and that future growth will not reach those heights of productivity any time soon. Strongest in its economic history, offering insights into the everyday and illustrating the impact of now-commonplace inventions such as the car, lightbulb, indoor plumbing, television, and flight.&lt;/p&gt;
&lt;h2 id="leadership-and-self-development"&gt;Leadership and Self-Development&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Radical-Candor-Kim-Scott/dp/B01KTIEFEE/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659194&amp;amp;sr=1-1&amp;amp;keywords=radical+candor&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=e7eb5c6b45da0260407d81c891a3128e"&gt;Radical Candor &lt;/a&gt;— Preaches the importance of radical candor: a combination of caring personally and directly challenging. Contrasted, in sometimes humorous tales from the field, with the failure modes of ruinous empathy and obnoxious aggression. Clearly and concisely written, with lessons applicable to all, whether manager or individual contributor.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Principles-Life-Work-Ray-Dalio-ebook/dp/B071CTK28D/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659238&amp;amp;sr=1-1&amp;amp;keywords=priniciples&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=72c3101728d24d493541cedd431c8459"&gt;Principles&lt;/a&gt; — How to live and work effectively? This book explores, in great detail, &lt;a href="https://en.wikipedia.org/wiki/Ray_Dalio"&gt;Ray Dalio&lt;/a&gt;’s own approach, how he arrived at it, how he put it in practice, and why he believes it works. Not all lessons are every where applicable, but there’s something to learn from here.&lt;/p&gt;
&lt;h2 id="business"&gt;Business&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Attention-Merchants-Scramble-Inside-Heads-ebook/dp/B01AEPSWB4/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659348&amp;amp;sr=1-1&amp;amp;keywords=attention+merchants&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=50c70d9d12a726dbc688d141f685d2b3"&gt;The Attention Merchants&lt;/a&gt; — A comprehensive history of advertising, thoughtfully told, from the penny press to the native ad.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Upstarts-Airbnb-Companies-Silicon-Changing-ebook/dp/B01HZFB3X0/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659384&amp;amp;sr=1-1&amp;amp;keywords=upstarts&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=2cf0697e6c99a1cc92807c66ecd39ebd"&gt;The Upstarts &lt;/a&gt;— Much like Brad Stone’s earlier work &lt;a href="https://www.amazon.com/dp/B00BWQW73E/ref=as_li_ss_tl?_encoding=UTF8&amp;amp;btkr=1&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=a205dbf38c5490019031b7266b90aec4"&gt;The Everything Store&lt;/a&gt; explored the history and rise of Amazon, this book examines the rise of Uber and Airbnb, along with a few other companies that didn’t quite rise so far. Published in early 2017, so it doesn’t take into account the most recent upheavals at Uber.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/WTF-Whats-Future-Why-Its-ebook/dp/B01N34IDU6/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659442&amp;amp;sr=1-1&amp;amp;keywords=wtf+tim+oreilly&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=9989fe5cd0d8c2ad36536e7c23dba795"&gt;WTF?: What’s the Future &lt;/a&gt;—&lt;a href="https://en.wikipedia.org/wiki/Tim_O%27Reilly"&gt; Tim O’Reilly&lt;/a&gt; counters the zeitgeist’s prevailing pessimism about the future of tech and offers an inspiring vision of how things could/should be. Written with learning, humility, and love.&lt;/p&gt;
&lt;h2 id="design"&gt;Design&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Visual-Explanations-Quantities-Evidence-Narrative/dp/0961392126/ref=as_li_ss_tl?s=books&amp;amp;ie=UTF8&amp;amp;qid=1514659478&amp;amp;sr=1-1&amp;amp;keywords=visual+explanations&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=72b5ae3718cdd7f75e6e3cc8b9ba9a47"&gt;Visual Explanations&lt;/a&gt; — A classic that long rested on my bookshelves but that I hadn’t properly read, cover to cover. Dated in parts, stunningly farsighted in others, the book is treat to enter into and read.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shapeofdesignbook.com/"&gt;The Shape of Design&lt;/a&gt; — Delightful meditations upon the nature of design, and indeed, of this wonderful world we find ourselves in.&lt;/p&gt;
&lt;h2 id="politics"&gt;Politics&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Righteous-Mind-Divided-Politics-Religion-ebook/dp/B0052FF7YM/ref=as_li_ss_tl?ie=UTF8&amp;amp;qid=1514659529&amp;amp;sr=8-1&amp;amp;keywords=righteous+mind&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=1e8721afb4a90ac7c86f672a3cdca6a8"&gt;The Righteous Mind&lt;/a&gt; — Each of us arrives at our most deeply held convictions through rigorous application of reason, right? Wrong. This book illustrates how and why.&lt;/p&gt;
&lt;h2 id="philosophy"&gt;Philosophy&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/When-Breath-Becomes-Paul-Kalanithi-ebook/dp/B00XSSYR50/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659559&amp;amp;sr=1-1&amp;amp;keywords=when+breath+becomes+air&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=8836b0a601246d1f209c309e86f1838e"&gt;When Breath Becomes Air&lt;/a&gt; — Moving, meaningful, lyrically written. A powerful reflection on what it means to be human.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Subtle-Art-Not-Giving-Counterintuitive-ebook/dp/B019MMUA8S/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659611&amp;amp;sr=1-1&amp;amp;keywords=subtle+art+of+not+giving&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=4d5990f526ed3fb10a94b185b03a27f9"&gt;The Subtle Art of Not Giving a F*ck &lt;/a&gt;— Stoicism for the digital age. Entertainingly written, with profound lessons hidden beneath seemingly casual prose.&lt;/p&gt;
&lt;h2 id="science"&gt;Science&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Seven-Brief-Lessons-Physics-Rovelli-ebook/dp/B00Z8VTMYG/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659659&amp;amp;sr=1-1&amp;amp;keywords=seven+brief+lessons&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=7a6706531ccd9c055ef035eeb86cec85"&gt;Seven Brief Lessons on Physics&lt;/a&gt; — Short (86 pages!) and sweet. Evocatively explores seven aspects of modern physics and communicates the author’s passion for his field.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Machine-Platform-Crowd-Harnessing-Digital-ebook/dp/B01MAWT25I/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659706&amp;amp;sr=1-1&amp;amp;keywords=machine+platform+crowd&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=00b8c447b12985fb1bbca84f5f5567c3"&gt;Machine, Platform, Crowd&lt;/a&gt; — A splendid book, replete with riches. Vital for understanding where we, as a society and an economy, are and where we’ll be heading in the decades ahead.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Soonish-Emerging-Technologies-Improve-Everything-ebook/dp/B06XBQ443G/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1514659725&amp;amp;sr=1-1&amp;amp;keywords=soonish&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=d0bbdaae0e7cbd46e4223bcb58893635"&gt;Soonish&lt;/a&gt; — You know that sparkle in your eye when you learn something new? This book is full of those sparkles.&lt;/p&gt;</description><author>dominik.net</author><pubDate>Sat, 30 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dominik.net/favorite-books-read-in-2017.html</guid></item><item><title>Links - December 30, 2017</title><link>https://faingezicht.com/links/2017/12/30/links/</link><description>Hello, and welcome to my last set of links of 2017. Let's get right into it:</description><author>Avy Faingezicht</author><pubDate>Sat, 30 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/12/30/links/</guid></item><item><title>Earthed by UA Fanthorpe</title><link>https://ho.dges.online/words/commonplace/earthed-by-ua-fanthorpe/</link><description>&lt;p&gt;Not precisely, like a pylon or&lt;br /&gt;
A pop-up toaster, but in a general&lt;br /&gt;
Way, stuck in the mud.&lt;/p&gt;
&lt;p&gt;Not budding out of it like gipsies,&lt;br /&gt;
Laundry lashed to a signpost, dieting on&lt;br /&gt;
Nettles and hedgehogs,&lt;/p&gt;
&lt;p&gt;Not lodged in its layers like badgers,&lt;br /&gt;
Tuned to the runes of its home-made walls, wearing&lt;br /&gt;
Its shape like a skin,&lt;/p&gt;
&lt;p&gt;Not even securely rooted, like&lt;br /&gt;
Tribesmen tied to the same allotment, sure of&lt;br /&gt;
The local buses,&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Sat, 30 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/earthed-by-ua-fanthorpe/</guid></item><item><title>2017 in review</title><link>https://jasoneckert.github.io/myblog/2017-in-review/</link><description>&lt;p&gt;&lt;img alt="2017a" src="2017a.png#center" title="2017a" /&gt;&lt;/p&gt;
&lt;p&gt;So what happened in 2017?&lt;/p&gt;
&lt;p&gt;Last year I thought I completed my basement arcade by getting Donkey Kong (see my blog post entitled &amp;ldquo;2016 in review&amp;rdquo;), but I was wrong!  I actually got two new arcade games this year. The first one was an arcade machine I never thought I’d find in good working condition. It’s also the absolute coolest arcade game of the 1980s with its amazing vector graphics (as well as my all-time favourite arcade game)&amp;hellip;&amp;hellip;.Atari’s Tempest!&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Sat, 30 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/2017-in-review/</guid></item><item><title>Write Your Leadership Philosophy</title><link>https://allan.reyes.sh/leadership/</link><description>&lt;p&gt;At best, it represents who you are and what you can deliver as a leader, and at
worst, it’s a contract for what you aspire to be.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I first wrote down my &lt;strong&gt;leadership philosophy&lt;/strong&gt; about a decade ago by writing
down all the values and practices I embraced. At the time, every great leader
and commander I served with had a written philosophy—so, I thought I should
craft one myself. It changed a lot since then, and &lt;em&gt;I’ve&lt;/em&gt; changed a lot.&lt;/p&gt;</description><author>allan.reyes.sh</author><pubDate>Fri, 29 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://allan.reyes.sh/leadership/</guid></item><item><title>Exit strategy for the new year resolution</title><link>http://dimitarsimeonov.com/2017/12/29/exit-strategy-for-the-new-year-resolution</link><description>&lt;p&gt;As the year is almost over, more and more people start reflecting on
everything that happened through the year, and start making plans for
the new year.&lt;/p&gt;

&lt;p&gt;But the last day of the calendar year is just an arbitrary day. There
is nothing special about it. It’s all in our heads. We assign that day
importance, but it’s arbitrary. The earth rotates around the sun, and
there is nothing special about its position on this date. It just
happens to be somewhere within the winter season in Europe. The
Chinese New Year is in mid February. What gives.&lt;/p&gt;

&lt;p&gt;The calendar is a convenience. It makes it possible to refer to a
point in time in a clear, unambiguous way.&lt;/p&gt;

&lt;p&gt;But nature doesn’t give a fuck about new years eve. Animals are
minding their own hunting and hiding. Rains, storms and earthquakes
don’t check the calendar to see if it is a good day to wreak
havoc. Our bodies’ growth, health and aging don’t change in discrete
steps, once per year. They keep coming at us all the time!&lt;/p&gt;

&lt;p&gt;So, what’s the point of end of year summaries and new year
resolutions?  It’s as if at the end of the year someone comes and
shakes us “Wake up, wake up!”. “Huh. What’s happening. What
happened”… “Ah, OK, this year I learned how to cook pot roast, next
year I should loose my belly fat.” By end of January, its sweet dreams
again. We’ve forgotten all about new years resolutions. We keep
dreaming, and December comes, and we are again surprised, and not
ready for it. We didn’t lose the belly fat.&lt;/p&gt;

&lt;p&gt;It’s because new years resolutions are bullshit. They are lousy and
lazy. If you want to make something happen, you make a resolution. Not
a new years resolution, but emotional fortitude and commitment. Not
just setting the label on the 365 days as “belly-fat-be-gone”, but
actually deciding to go for it, as long as it takes, until you
accomplish it, or consciously resolve not to do it.&lt;/p&gt;

&lt;p&gt;And, in my opinion, that emotional attachment makes the
difference. Not everything needs a whole year. It might take three
months, or two years. It might take ten years or even a lifetime.&lt;/p&gt;

&lt;p&gt;The end of the calendar year is really dumb exit strategy for a
goal.&lt;/p&gt;

&lt;p&gt;Instead, emotional attachment to our resolution is an effective exit
strategy. That is, we are emotionally committed to our resolution,
which means that we don’t abandon it, unless another, stronger emotion
comes against it, or we achieve it, or we re-assess our emotion and
decide it is not that strong.&lt;/p&gt;

&lt;p&gt;Emotions work because they’re more real, than the calendar year’s
beginning and end. Our emotions affect our hormones, and biochemistry,
and even if it is placebo, placebo sometimes works.&lt;/p&gt;

&lt;p&gt;My current resolutions are to write a lot and to figure out a long
term career path. Deciding on vocation whether it’s a software
engineer, or running my own business, or something else. These
resolutions are not new years resolutions. They took a long time of
deliberation and thinking to arrive at. It took a bunch of effort to
commit to them. My emotional resolve built up over that time, and are
what drives me to make sustainable progress towards these goals.&lt;/p&gt;

&lt;p&gt;These goals are active. I have to do something to achieve them. They
are not avoidance goals. An avoidance goal is “Stop drinking” or “Stop
smoking” or “Don’t be distracted by the Internet”. Those are lousy
goals. They are just as much bullshit as the new years resolution. The
underlying objectives are good and commendable, and something to
strive towards, but the way of measuring success is lousy. They can never be achieved in the abstract.&lt;/p&gt;

&lt;p&gt;I’ve had a little bit of a success with the drinking aspect so let me
elaborate. If your goal is the absolute “Never drink again” then
that’s destined to fail. It is just easy to slip up sometimes and
forget about the resolution not to drink, and out of habit have a sip
whiskey sour at a birthday party, until you realize “Oh shit!”.&lt;/p&gt;

&lt;p&gt;In that case, it’s an immediate failure. The statement “Never drink
again” is false. You can reset the timer on it, but that’s a slippery
slope. Every time it happens, it chips away from the emotional
resolve. It’s almost impossible to muster so much emotional resolve to
last forever. But I think it is possible to muster enough resolve to
last for some period of time.&lt;/p&gt;

&lt;p&gt;I think a better resolution in this case is to set a period such as
thirty or ninety days and resolve to accomplish one or multiple such
“dry” periods. With no end date for completing them. If you’re not
done by the end of the year, why, keep going. You’ve presumably made
some progress, so you haven’t failed. Personally, I’ve done a 30 day
no drinking every year for ten years in a row and over time it really
decreased my overall alcohol consumption to a point where I rarely
drink.&lt;/p&gt;

&lt;p&gt;I have a much more healthy relationship with alcohol now. I don’t
think I’ll ever fully eliminate it from my life, but I have very
little thirst for it now.&lt;/p&gt;

&lt;p&gt;My first such period happened when I was hungover. It started in May,
and not as a new year resolution. I was disgusted with myself for
drinking too much the night before, and decided to avoid drinking for
month and a half, until my birthday. I only made it twenty six days
then, but I still regarded it as a success. My personal record. If I
had the lousy goal of never drinking, I would’ve relapsed much sooner
and the goal would have felt much more like a failure. My emotion
would’ve been :(, instead of the :) that I got from accomplishing
twenty six days without drinking!&lt;/p&gt;

&lt;p&gt;Taking a defensive goal of “never drink again” and turning it into the
offensive “accomplish 30 days of no drinking” made the difference
emotion-wise. It embedded the exit strategy within the goal. I had
enough emotional fortitude for achieving that goal, at creation
time. I didn’t, and still don’t have enough emotional fortitude to
give up alcohol completely.&lt;/p&gt;

&lt;p&gt;Goals and resolutions without exit strategy are lousy goals.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 29 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/12/29/exit-strategy-for-the-new-year-resolution</guid></item><item><title>How to set up rsnapshot instead of Time Machine</title><link>https://bastibe.de/2017-12-29-rsnapshot-on-macos.html</link><description>&lt;p&gt;(This blog post was changed since my initial strategy of disabling the lockfile didn't work. Turns out, the lockfile is required, and backups have to be stacked.)&lt;/p&gt;
&lt;p&gt;Yesterday, I wrote about how Time Machine has failed me. Time Machine keeps regular backups, going back as far as your hard drive space permits. In theory. In practice, every year or so it messes up somehow and has to start over, thereby deleting all your older backups. A backup that is not reliable is not a backup.&lt;/p&gt;
&lt;p&gt;Luckily, there are alternatives. Probably the easiest is &lt;a href="https://rsync.samba.org/"&gt;rsync&lt;/a&gt;&lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;, a very cool tool that copies files and directories from one place to another. You could simply run this once a day, and have a new backup every day. You can even configure rsync so it doesn't need to copy unchanged files, and instead hard-links them from an older backup. &lt;a href="http://rsnapshot.org/"&gt;rsnapshot&lt;/a&gt; automates this process to keep a number of tiered copies, for example ten hourly backups, seven daily backups, four weekly backups, and a hundred monthly backups. Each backup is then simply a directory that contains your files. No fancy starfield-GUI, but utterly reliable and trivial to understand &lt;sup class="footnote-ref" id="fnref-2"&gt;&lt;a href="#fn-2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Setting up rsnapshot on macOS is not quite as straight-forward as I'd like, and I couldn't find a great guide online. So, without further ado, here's how to configure rsnapshot on macOS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Install rsnapshot&lt;/p&gt;
&lt;p&gt;&lt;code&gt;brew install rsnapshot&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write the config file&lt;/p&gt;
&lt;p&gt;You can copy a template from homebrew:
&lt;code&gt;cp /usr/local/Cellar/rsnapshot/1.4.2/etc/rsnapshot.conf.default /usr/local/etc/rsnapshot.conf&lt;/code&gt;
And then configure the new configuration file to your liking (preserve the tabs!):&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;  config_version	1.2 # default
  verbose		2   # default
  loglevel	3   # default

  # this is where your backups are stored:
  snapshot_root	/Volumes/BBackup/Backups.rsnapshot/ # make sure this is writeable
  # prevent accidental backup corruption:
  lockfile	/Users/bb/.rsnapshot.pid
  # use this if you back up to an external drive:
  no_create_root	1   # don't back up if the external drive is not connected

  # configure how many tiers of backups are created:
  retain	hourly	10
  retain	daily	7   # dailies will only be created once 10 hourlies exist
  retain	weekly	4   # weeklies will only be created once 7 dailies exist
  retain	monthly	100 # monthlies will only be created once 4 weeklies exist

  # the list of directories you want to back up:
  backup	/Users/bb/Documents		localhost/
  backup	/Users/bb/eBooks		localhost/
  backup	/Users/bb/Movies		localhost/
  backup	/Users/bb/Music		localhost/
  backup	/Users/bb/Pictures		localhost/
  backup	/Users/bb/Projects		localhost/
  backup	/Users/bb/Projects-Archive		localhost/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Instead of &lt;code&gt;localhost&lt;/code&gt;, you can use remote machines as well. Check  &lt;a href="https://download.samba.org/pub/rsync/rsync.html"&gt;&lt;code&gt;man rsync&lt;/code&gt;&lt;/a&gt; for details&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make sure it works and create initial backup&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rsnapshot -c /usr/local/etc/rsnapshot.conf hourly&lt;/code&gt;
The first backup will take a while, but subsequent backups will be fast. A normal backup on my machine takes about two minutes and runs unnoticeably in the background.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write launchd Agent&lt;/p&gt;
&lt;p&gt;Next, we have to tell macOS to run the backups in regular intervals. Conceptually, you do this by writing a launchd agent script&lt;sup class="footnote-ref" id="fnref-3"&gt;&lt;a href="#fn-3"&gt;3&lt;/a&gt;&lt;/sup&gt;, which tells launchd when and how to run your backups. In my case, I create four files in &lt;code&gt;/Users/bb/Library/LaunchAgents/&lt;/code&gt;, called &lt;code&gt;rsnapshot.{hourly,daily,weekly,monthly}.plist&lt;/code&gt;. Apple's &lt;a href="https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html"&gt;documentation&lt;/a&gt; for these files is only mildly useful (as usual), but &lt;a href="https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html"&gt;&lt;code&gt;man launchd.plist&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man5/plist.5.html#//apple_ref/doc/man/5/plist"&gt;&lt;code&gt;man plist&lt;/code&gt;&lt;/a&gt; should give you an idea how this works.&lt;/p&gt;
&lt;p&gt;Here is my hourly launchd agent (I'll explain the bash/sleep thing later):&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;rsnapshot.hourly&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/bin/bash&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;-c&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/rsnapshot&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;/usr/local/etc/rsnapshot.conf&lt;span class="w"&gt; &lt;/span&gt;hourly&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StartCalendarInterval&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For the other four scripts, change the two occurrences of &lt;code&gt;hourly&lt;/code&gt; to &lt;code&gt;{daily,weekly,monthly}&lt;/code&gt; and change the &lt;code&gt;&amp;lt;dict&amp;gt;&lt;/code&gt; portion at the end to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;daily:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;weekly:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Weekday&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;monthly:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Day&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, &lt;code&gt;rsnapshot&lt;/code&gt; can only ever run one backup at a time without stepping on its own toes. This is a problem when the computer wakes up, and more than one backup was scheduled during its sleep, since launchd will then happily launch all missed backups at the same time. But only one of them will succeed.&lt;/p&gt;
&lt;p&gt;To fix this, I delay the later backup tiers using the &lt;code&gt;sleep 0&lt;/code&gt; directive. I use &lt;code&gt;sleep 900&lt;/code&gt; (15 minutes later) for daily, &lt;code&gt;sleep 1800&lt;/code&gt; (30 minutes), and &lt;code&gt;sleep 2700&lt;/code&gt; (45 minutes) for the lower tiers&lt;sup class="footnote-ref" id="fnref-4"&gt;&lt;a href="#fn-4"&gt;4&lt;/a&gt;&lt;/sup&gt;. It seems that there should be a more elegant solution than this, but I haven't found one.&lt;/p&gt;
&lt;p&gt;From the documentation, you might think that &lt;code&gt;&amp;lt;key&amp;gt;Program&amp;lt;/key&amp;gt;&lt;/code&gt; would be more succinct than supplying the binary as the first argument of &lt;code&gt;&amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;&lt;/code&gt;, but this apparently uses a different syntax and does not in fact work as expected.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Load launchd agents&lt;/p&gt;
&lt;p&gt;&lt;code&gt;launchctl load ~/Library/LaunchAgents/rsnapshot.*&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test launchd agent&lt;/p&gt;
&lt;p&gt;&lt;code&gt;launchctl start rsnapshot.hourly&lt;/code&gt;
If it doesn't work, Console.app might show a relevant error message.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove backup directory from Spotlight&lt;/p&gt;
&lt;p&gt;Go to System Preferences → Spotlight → Privacy → Add your &lt;code&gt;snapshot_root&lt;/code&gt; directory from earlier&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disable TimeMachine and delete your existing backup (if you want)&lt;/p&gt;
&lt;p&gt;Start Time Machine, right-click any directory you want to delete, and select &amp;quot;delete all backups of $dir&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Caveats&lt;/h3&gt;
&lt;p&gt;The configuration file of rsnapshot says that you might experience data corruption if you run several copies of rsnapshot at the same time (and you can use the lockfile to prevent this). This is a problem if your computer is asleep while rsnapshot is scheduled to run, since launchd will then re-schedule all missed tasks at once when the computer wakes up. If you enable the lockfile, only one of them will run.&lt;/p&gt;
&lt;p&gt;On the other hand, only the hourly task will actually create a new backup. All higher-level backup tiers merely copy existing backups around, so &lt;em&gt;in theory&lt;/em&gt;, they shouldn't step on each other's toes when run concurrently. I have opened &lt;a href="https://github.com/rsnapshot/rsnapshot/issues/200"&gt;an issue&lt;/a&gt; asking about this.&lt;/p&gt;
&lt;p&gt;There are other possible solutions: ① You could modify the launchd entry such that backups only trigger after a few minutes or, better yet, only once all other instances of rsnapshot have finished. I am not sure if launchd supports this, though. ② You could schedule the hourly task using cron instead of launchd, since cron will &lt;em&gt;not&lt;/em&gt; reschedule missed tasks. This would only work for two tiers of backups, though. ③ You could just ignore the issue and hope for the best. After all, if a daily or hourly backup gets corrupted every now and then, you still have enough working backups...&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;rsync is one of those reliable tools &lt;a href="http://bastibe.de/2017-12-28-dropbox-timemachine-is-useless.html"&gt;I talked about&lt;/a&gt;. It is rock solid, incredibly versatile, and unapologetically single-minded. A true gem!&lt;a class="footnote" href="#fnref-1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn-2"&gt;&lt;p&gt;This works great for local backups. If you need encrypted backups or compressed backups (maybe on an untrusted remote machine), &lt;a href="https://www.reddit.com/r/linux/comments/42feqz/i_asked_here_for_the_optimal_backup_solution_and/czbeuby/"&gt;this post&lt;/a&gt; recommends &lt;a href="https://www.borgbackup.org/"&gt;Borg&lt;/a&gt; instead of rsnapshot, but you will lose the simplicity of simple directories.&lt;a class="footnote" href="#fnref-2"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn-3"&gt;&lt;p&gt;I use launchd instead of cron since launchd will re-schedule missed backups if the computer was asleep.&lt;a class="footnote" href="#fnref-3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn-4"&gt;&lt;p&gt;This will fail if the hourly backup takes longer than 15 minutes. This is rather unlikely, though, or at least should not happen often enough to be of concern.&lt;a class="footnote" href="#fnref-4"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>bastibe.de</author><pubDate>Fri, 29 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-12-29-rsnapshot-on-macos.html</guid></item><item><title>Sourcing developer marketing content</title><link>/2017/12/28/Sourcing-developer-marketing-content/</link><description>&lt;p&gt;I spend a lot of time with dev tool and data companies. I think I&amp;rsquo;ve more or less banished myself to a life of working in the space, no consumer products for me. In that world a common topic that comes up amongst marketing teams is how do I get my team to contribute to content? Sometimes the person already has an idea of how they want the team to jump onto the bandwagon of their plan, sometimes they&amp;rsquo;re entirely open minded. I won&amp;rsquo;t get into pros and cons of various approaches here, rather after sharing some of my approaches in one on one settings I thought it could be useful to share more broadly here.&lt;/p&gt;
&lt;h3 id="turn-emails-into-blogs"&gt;
&lt;div&gt;
Turn emails into blogs
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m a big fan of high quality content when it comes to developer focused products. Yes, you can publish x vs. y with FUD and get some traction with it. You can publish high level customer stories that don&amp;rsquo;t get down into the details. But publishing high quality deep technical content that other engineers appreciate gives you a huge head start in getting buy in from your customers. The best thing about much of this type of content is you likely already have it sitting within your organization.&lt;/p&gt;
&lt;p&gt;Engineers spend a lot of time being thorough and articulate in their emails to their peers. If you see a well written email from one engineer to the engineers@ list and then others chime in either with questions, follow-up, or praise then it&amp;rsquo;s likely a great candidate for a blog post. We recently had one of these at Citus where another engineer replied with &amp;ldquo;Nice blog post :)&amp;rdquo;, a few weeks later we had &lt;a href="https://www.citusdata.com/blog/2017/12/22/distributed-count-vs-hyperloglog/"&gt;a post&lt;/a&gt; for the rest of the world to read.&lt;/p&gt;
&lt;p&gt;The thing about emails though is the engineers won&amp;rsquo;t usually take and turn them into a blog post. Get a technically minded person that likes to write and put some framing around it, pull out relevant details, and collaborate with the engineer. I&amp;rsquo;ve often found going from one of these emails to a fully published blog post can be anywhere from 2-8 hrs (including reviews and edits).&lt;/p&gt;
&lt;h3 id="beginner-mindset-with-tickets"&gt;
&lt;div&gt;
Beginner mindset with tickets
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;As your product people and engineers spend more and more time with the product they become numb to the cool feature from 2 years ago. That initial awe is just expected. Yes there are new advanced features and tech that is being built&amp;hellip; but most of your users aren&amp;rsquo;t the advanced power users. You still need to speak to the people just now onboarding and discovering you.&lt;/p&gt;
&lt;p&gt;The best way to maintain this beginner mindset is to capture the interactions with those that are newer to your product. Over the years I&amp;rsquo;ve made the practice of cataloging support tickets and the type of issue encountered. Any time the same issue is seen several times it becomes a candidate for a blog post or at the very least being clearly documented.&lt;/p&gt;
&lt;h3 id="make-sales-engineering-obsolete"&gt;
&lt;div&gt;
Make sales engineering obsolete
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Your sales engineers spend weeks with customers helping them implement complex solutions with your product. In a lot of cases they get really good at helping re-implement a similar solution over and over. Similar to your process with support tickets they&amp;rsquo;re a great source to take what they&amp;rsquo;ve done a few times over and turn it into a blog post.&lt;/p&gt;
&lt;p&gt;Usually after the first time implementing they have some ideas but there are rough edges. The second or third time they&amp;rsquo;ve helped a customer implement a particular approach it becomes a candidate for a post.&lt;/p&gt;
&lt;h3 id="training-and-documentation-dont-have-to-be-siloed"&gt;
&lt;div&gt;
Training and Documentation don&amp;rsquo;t have to be siloed
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m a big fan of not doing anything for one reason. You should absolutely document your product, and if you need to do training to support customers go for it. But that doesn&amp;rsquo;t mean those bits of content can&amp;rsquo;t be re-used. Documentation is a great place to take the factual how something works and then give it some narration of the end to end experience in a blog post.&lt;/p&gt;
&lt;h2 id="the-process"&gt;
&lt;div&gt;
The process
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re asking the question how do I get more good content out there, then you&amp;rsquo;re not leveraging the content you&amp;rsquo;re already sitting on top of. Though perhaps equal is getting a process in place. A few tips for that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t blanket ask to a list for volunteers, ask individuals and about specific posts. &lt;em&gt;If you see a great email, respond and ask if you can work with them to get it turned into a blog post&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;You&amp;rsquo;ll need to navigate the process, and make sure to have a process&lt;/li&gt;
&lt;li&gt;Separate messaging/flow from grammar&lt;/li&gt;
&lt;li&gt;My typical process is: outline -&amp;gt; draft -&amp;gt; feedback from 2-3 on draft -&amp;gt; finalize draft -&amp;gt; feedback from 4-5 (often some external parties) -&amp;gt; publish&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="whatd-i-miss"&gt;
&lt;div&gt;
What&amp;rsquo;d I miss?
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Have other tips that are key to the process? Know of other places where content may already exist but isn&amp;rsquo;t being leveraged? Would love to &lt;a href="https://www.twitter.com/craigkerstiens"&gt;hear your thoughts&lt;/a&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 28 Dec 2017 22:55:56 GMT</pubDate><guid isPermaLink="true">/2017/12/28/Sourcing-developer-marketing-content/</guid></item><item><title>Dropbox deleted my pictures and Time Machine didn't backup</title><link>https://bastibe.de/2017-12-28-dropbox-timemachine-is-useless.html</link><description>&lt;p&gt;Dropbox deleted some of my favorite photos. Have you looked at all your old pictures lately and checked if they are still there? I have, and they were not. Of course Dropbox denies it is their fault, but no other program routinely accessed my pictures. &lt;a href="https://www.dropboxforum.com/t5/Missing-files-and-folders/Randomly-deleted-files-and-folders/td-p/203952"&gt;I am not alone with this problem&lt;/a&gt;. It must have happened some time between the summer of 2015, when I put my pictures on Dropbox, and the summer of 2016, when Time Machine last corrupted its backups and had to start over, thereby deleting my last chance of recovering my pictures. The pictures are gone for good.&lt;/p&gt;
&lt;p&gt;So, what have I learned? Dropbox loses your data, and Time Machine can't restore it. These programs are obviously no good for backups. Let me repeat this: &lt;strong&gt;Dropbox and Time Machine are not a backup!&lt;/strong&gt; A true backup needs to be reliable, keep an infinite history, and &lt;em&gt;never&lt;/em&gt;, &lt;em&gt;never&lt;/em&gt;, &lt;em&gt;never&lt;/em&gt; accidentally delete files.&lt;/p&gt;
&lt;p&gt;From now on, I will use &lt;a href="http://rsnapshot.org/"&gt;rsnapshot&lt;/a&gt; for backups. &lt;a href="https://rayed.com/wordpress/?p=1693"&gt;Here&lt;/a&gt;'s a tutorial on how to set it up on a Mac. I have used rsnapshot for years at work, and it has never let me down. For syncronizing things between computers, I now use &lt;a href="https://syncthing.net/"&gt;syncthing&lt;/a&gt;. Both of these programs are not as user-friendly as Dropbox or Time Machine, but that is a small price to pay for a working backup.&lt;/p&gt;
&lt;p&gt;A few years ago, I had high hopes that &lt;a href="http://bastibe.de/2009-03-14-get-a-mac.html"&gt;Apple&lt;/a&gt; and &lt;a href="http://bastibe.de/2009-03-28-synchronisieren-von-google.html"&gt;Dropbox&lt;/a&gt; and Google and Amazon would lead us to a bright future of computers that &amp;quot;just work&amp;quot;, and could solve our daily chores ever more conveniently and reliably. But I was proven wrong. &lt;a href="http://bastibe.de/2012-07-09-apple-is-failing-me.html"&gt;So&lt;/a&gt;. &lt;a href="http://bastibe.de/2012-11-01-apple-tv.html"&gt;Many&lt;/a&gt;. &lt;a href="http://bastibe.de/2015-10-16-finder-woes.html"&gt;Times&lt;/a&gt;. It seems that for-profit software inevitably becomes less dependable as it adds ever more features to attract ever more users. In contrast, free software can focus on &lt;a href="http://bastibe.de/2017-10-24-the-long-game.html"&gt;incremental improvements and steadily increasing reliability&lt;/a&gt;.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Thu, 28 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-12-28-dropbox-timemachine-is-useless.html</guid></item><item><title>Top album picks for 2017</title><link>https://smcleod.net/2017/12/top-album-picks-for-2017/</link><description>&lt;p&gt;Here are my top album pics for 2017 (in no particular order)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This is by no means an exhaustive list, it&amp;rsquo;s just the top albums that really stood out to me and in all fairness, I&amp;rsquo;ve thought of several others since so there may be a follow up post (or two).&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="father-john-misty---pure-comedy"&gt;Father John Misty - &lt;a href="https://en.wikipedia.org/wiki/Pure_Comedy"&gt;Pure Comedy&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://github.com/sammcj/smcleod_files/blob/master/images/albums_2017/FJM_PureComedy_Covers.gif?raw=true" /&gt;&lt;/p&gt;
&lt;p&gt;As a bonus, a short film was released with the album:&lt;/p&gt;
&lt;div style="padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
      
    &lt;/div&gt;

&lt;p&gt;From &lt;a href="https://en.wikipedia.org/wiki/Pure_Comedy"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Thu, 28 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/12/top-album-picks-for-2017/</guid></item><item><title>Bitcoin's price isn't a bubble, it's an adoption curve</title><link>https://olshansky.info/posts/2017-12-27-bitcoin-adoption-curve-not-bubble/</link><description>It's difficult to objectively quantify Bitcoin's adoption rate since there are too many factors to consider. Should it be the number of…</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 27 Dec 2017 21:35:51 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-12-27-bitcoin-adoption-curve-not-bubble/</guid></item><item><title>HP 4951C Protocol Analyser</title><link>https://smcleod.net/2017/12/hp-4951c-protocol-analyser/</link><description>&lt;p&gt;My good friend Joel Shea received a most unlikely gift this Christmas - A vintage HP 4951 Protocol Analyser.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href="http://www.hpmuseum.net/display_item.php?hw=1123"&gt;HP Computer Museum&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Original Price: $3595
The 4951B was replaced by the 4951C and 4952A in 1986. Both new models handled Async, BSC, SDLC, HDLC, X.25 and SNA protocols. The 4951C also handled DDCMP, while the 4952A did not. The 4952A handled X.21 while the 4951C did not. Both new analysers used a floppy dive (618 KB) for removable media.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Wed, 27 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/12/hp-4951c-protocol-analyser/</guid></item><item><title>2017-12-27/01</title><link>https://ho.dges.online/pictures/2017-12-27-01/</link><description/><author>ho.dges.online</author><pubDate>Wed, 27 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-12-27-01/</guid></item><item><title>2017-12-27/02</title><link>https://ho.dges.online/pictures/2017-12-27-02/</link><description/><author>ho.dges.online</author><pubDate>Wed, 27 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-12-27-02/</guid></item><item><title>2017-12-27/03</title><link>https://ho.dges.online/pictures/2017-12-27-03/</link><description/><author>ho.dges.online</author><pubDate>Wed, 27 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-12-27-03/</guid></item><item><title>Guidance on performing retrospectives</title><link>/2017/12/26/Guidance-on-performing-retrospectives/</link><description>&lt;p&gt;In my career I&amp;rsquo;ve had to conduct a number of retrospectives. Ahead of them it already sucked, there was an outage at some point, customers were impacted, and it was our fault. Never was it solely on our underlying infrastructure provider (AWS or Heroku), nope the blame was on us and we&amp;rsquo;d failed in some way. And as soon as the incident was resolved, it wasn&amp;rsquo;t time to go home and decompress with a beer, it was time start the process of a retrospective.&lt;/p&gt;
&lt;p&gt;Finding the motivation to get right back to work is tough, but not losing time is important. There is probably a lot out there on retrospectives, and in general I was well rehearsed at them. But since I&amp;rsquo;d not performed a large scale one in a few years I found myself rusty and thought it&amp;rsquo;d be good to share some of our process.&lt;/p&gt;
&lt;h3 id="capture-details-immediately"&gt;
&lt;div&gt;
Capture details immediately
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;It may not be clear if you&amp;rsquo;ve not been involved in many, but a retrospective is more than just a meeting to discuss what happened and how to fix it. It&amp;rsquo;s an overall process, it begins with capturing thorough details of what happened. The start is a timeline. The best thing to do is capture the details while they&amp;rsquo;re fresh. Start with a google doc and simply document the timeline of everything. Capture chat logs that are relevant while they&amp;rsquo;re fresh in history and easy to find.&lt;/p&gt;
&lt;p&gt;The start of an outage likely wasn&amp;rsquo;t the start of the timeline, there may have been something that happened days, weeks, or even years ago. Don&amp;rsquo;t just start from the time things went offline, go back to the causes as much as possible. If code was committed a year ago that was the offender make sure to note that.&lt;/p&gt;
&lt;h3 id="running-the-retrospective-the-meeting-part"&gt;
&lt;div&gt;
Running the retrospective (the meeting part)
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;There are a number of various good practices for running the retrospective itself. There are also a lot of different formats, all valid each with their own pros and cons. You can do with a basic timeline, what went well/didn&amp;rsquo;t, do a &lt;a href="https://en.wikipedia.org/wiki/5_Whys"&gt;five whys&lt;/a&gt; analysis. I tend to prefer a clean and dry analysis of timeline, what went well and what didn&amp;rsquo;t and what we&amp;rsquo;re doing about it.&lt;/p&gt;
&lt;p&gt;Some key tips to help a retrospective meeting be productive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Explicitly set time bounds for each activity ahead of time, more so than maybe any other meeting it&amp;rsquo;s important to get through all your agenda. Hard time limits on the planned items is how you accomplish this.&lt;/li&gt;
&lt;li&gt;Spend at least some time on what went well, retrospectives aren&amp;rsquo;t fun. Spending some time on the good parts of your process and response isn&amp;rsquo;t wasted, just don&amp;rsquo;t be overly self-back-patting (that&amp;rsquo;s not a word but you get it).&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t discuss people, or rather don&amp;rsquo;t point fingers. Yes, people will come up, but it&amp;rsquo;s about the technical and process errors not the person that performed them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="the-important-part"&gt;
&lt;div&gt;
The important part
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Every step in the retrospective is important, but the goal of them all is to get to how you can improve. With any retrospective there are likely two categories of improvements that will surface. The first is bugs that caused the issue or engineering that could go in place to help with the specific issue. The second are process improvements. If you don&amp;rsquo;t have improvements in both areas then spend more time thinking on the one you&amp;rsquo;re missing.&lt;/p&gt;
&lt;p&gt;Improvements shouldn&amp;rsquo;t be isolated to the exact issue you saw. Yes you may see the exact same issue again, but there is also a lot more you can draw out that helps improve overall quality. It&amp;rsquo;s inevitable you&amp;rsquo;ll see different issues in the future, thinking of how you can improve your systems and processes to catch those future issues is time well spent.&lt;/p&gt;
&lt;h3 id="sharing-the-details"&gt;
&lt;div&gt;
Sharing the details
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ve done the hard work in the above, but it&amp;rsquo;s still good to share publicly and transparently. Within your public retrospective I tend to follow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Apologize, &lt;strong&gt;and mean it&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Show a firm understanding of your systems, and communicate the problem. Don&amp;rsquo;t try to be fancy technically, but don&amp;rsquo;t be too highlevel. Think goldilocks.&lt;/li&gt;
&lt;li&gt;Share what you&amp;rsquo;re doing to improve&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Credit to Mark for being the first person I&amp;rsquo;m aware of to lay it out like the above&lt;/em&gt;&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://www.twitter.com/markimbriaco"&gt;Mark Imbriaco&lt;/a&gt;, &lt;a href="https://www.twitter.com/blakegentry"&gt;Blake Gentry&lt;/a&gt;, &lt;a href="https://www.twitter.com/danfarina"&gt;Daniel Farina&lt;/a&gt;, &lt;a href="https://www.twitter.com/lukasfittl"&gt;Lukas Fittl&lt;/a&gt;, &lt;a href="https://www.twitter.com/leinweber"&gt;Will Leinweber&lt;/a&gt; for input and feedback along the way.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Looking for more resources on the topic? Make sure to check out these two talks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.heavybit.com/library/video/every-minute-counts-coordinating-herokus-incident-response/"&gt;Every Minute Counts: Coordinating Heroku&amp;rsquo;s Incident Response&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vimeo.com/67178303"&gt;Monitorama 2013 - Mark Imbriaco&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 26 Dec 2017 22:55:56 GMT</pubDate><guid isPermaLink="true">/2017/12/26/Guidance-on-performing-retrospectives/</guid></item><item><title>Editing Gameplay Videos without Re-encoding using FFmpeg</title><link>https://blog.varunramesh.net/posts/editing-gameplay-videos-without-re-encoding-using-ffmpeg/</link><description>Editing gameplay videos in Premiere requires that you re-encode, thus losing quality. Instead, you can use FFmpeg to edit losslessly.</description><author>Varun Ramesh's Blog</author><pubDate>Tue, 26 Dec 2017 20:04:26 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/editing-gameplay-videos-without-re-encoding-using-ffmpeg/</guid></item><item><title>My terminal setup</title><link>https://josh.works/terminal-setup</link><description>&lt;p&gt;&lt;em&gt;note: this is a draft. Please ping me in slack/email with questions, spots where this is unclear. I’ll answer your question, and update this post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s some quick notes on how I have my terminal setup.&lt;/p&gt;

&lt;p&gt;First, I use Zsh. If you’re on a new Macbook Pro, you also are using Zsh.&lt;/p&gt;

&lt;h2 id="install-iterm"&gt;Install iTerm&lt;/h2&gt;

&lt;p&gt;If you’re using &lt;code class="language-plaintext highlighter-rouge"&gt;Terminal.app&lt;/code&gt;, head to &lt;a href="https://iterm2.com/index.html"&gt;https://iterm2.com/index.html&lt;/a&gt; and click the “download” button. Install the app.&lt;/p&gt;

&lt;h2 id="install-oh-my-zsh"&gt;Install &lt;code class="language-plaintext highlighter-rouge"&gt;oh my zsh&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Install &lt;code class="language-plaintext highlighter-rouge"&gt;oh my zsh&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Head to &lt;a href="https://ohmyz.sh/"&gt;https://ohmyz.sh/&lt;/a&gt; and follow their installation instructions, which is&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Run the following command in your terminal:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="edit-zshrc"&gt;Edit ~/.zshrc`&lt;/h2&gt;

&lt;p&gt;Open up &lt;code class="language-plaintext highlighter-rouge"&gt;~/.zshrc&lt;/code&gt; in Atom. We’ll use it a few times.&lt;/p&gt;

&lt;p&gt;Line 10 or 11, change the &lt;code class="language-plaintext highlighter-rouge"&gt;theme&lt;/code&gt; value to &lt;code class="language-plaintext highlighter-rouge"&gt;agnoster&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="github.com/agnoster/agnoster-zsh-theme"&gt;github.com/agnoster/agnoster-zsh-theme&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Head to the repo and follow the installation instructions, which touch on:&lt;/p&gt;

&lt;h3 id="install-the-patched-solarized-fonts"&gt;Install the Patched Solarized Fonts:&lt;/h3&gt;

&lt;p&gt;&lt;a href="github.com/powerline/fonts"&gt;github.com/powerline/fonts&lt;/a&gt;&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;# clone
git clone https://github.com/powerline/fonts.git --depth=1
# install
cd fonts
./install.sh
# clean-up a bit
cd ..
rm -rf fonts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="update-iterm-to-use-one-of-the-new-fonts"&gt;Update iTerm to use one of the new fonts&lt;/h3&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Profiles &amp;gt; Text &amp;gt; Font (Meslo LG M DZ for Powerline)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="iterm settings" src="/images_2020/2020-08-12 at 1.56 PM.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;open up this file: &lt;code class="language-plaintext highlighter-rouge"&gt;~/.oh-my-zsh/themes/agnoster.zsh-theme&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or do &lt;code class="language-plaintext highlighter-rouge"&gt;atom ~/.oh-my-zsh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Atom open up the themes directory, and open up &lt;code class="language-plaintext highlighter-rouge"&gt;agnoster.zsh-theme&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;comment out the existing line that says &lt;code class="language-plaintext highlighter-rouge"&gt;PROMPT&lt;/code&gt; on line 230, and paste in:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;PROMPT='$(build_prompt) 
&amp;gt; '
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Should look like this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="prompt" src="/images_2020/2020-08-12 at 1.50 PM.jpg" /&gt;&lt;/p&gt;

&lt;h3 id="resources"&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://gist.github.com/josh-works/22b3cd2f4cc4abc9458f50c4b47565e2"&gt;Josh’s Zsh Setup instructions from ages ago&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/jazz-up-your-zsh-terminal-in-seven-steps-a-visual-guide-e81a8fd59a38/"&gt;Jazz Up Your “ZSH” Terminal In Seven Steps — A Visual Guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://duskcloudxu.github.io/2020/03/04/How-to-install-and-use-iterm-and-oh-my-zsh/"&gt;How to install and use iterm and oh-my-zsh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Tue, 26 Dec 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/terminal-setup</guid></item><item><title>A (mostly) automated release process</title><link>https://www.mootoday.com/blog/a-mostly-automated-release-process</link><description>Automate whatever you can automate and share the responsibility for the remaining tasks.</description><author>www.mootoday.com - RSS Feed</author><pubDate>Tue, 26 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mootoday.com/blog/a-mostly-automated-release-process</guid></item><item><title>Cultivate Curiosity, or 'Reasons to be More Childlike'</title><link>https://josh.works/cultivate-curiosity-reasons-to-be-more-childlike</link><description>&lt;p&gt;I’ve had an idea rolling around my head.&lt;/p&gt;

&lt;p&gt;I suspect that “being curious” will correlate well with positive outcomes in my life, on pretty much any time horizon, be it days, weeks, or decades. Curiosity feels like a tolerable antidote to boredom, though boredom in and of itself is something to celebrate and embrace.&lt;/p&gt;

&lt;p&gt;The goal isn’t to &lt;em&gt;not be bored&lt;/em&gt;, it is to &lt;em&gt;not be jaded and closed&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What is “jaded and closed”? I cannot quite define it, but &lt;a href="https://en.wikipedia.org/wiki/I_know_it_when_I_see_it"&gt;I know it when I see it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I enjoy spending time with people who are both older than me, and people who are just plain old. When they display traits or attitudes that I either want to emulate or want to avoid, I try to reverse engineer what led to that thing I do or don’t want.&lt;/p&gt;

&lt;p&gt;The presence/absence of curiosity has correlated well the presence/absence of other traits I want to emulate.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;This habit seems amenable to practice. I.E. the more you look for (and expect to find) objects, remarks, incidents, thoughts, comments that spark curiosity, the more you find these exact curiosity-sparking… things.&lt;/p&gt;

&lt;p&gt;I’ve encountered objects and phenomena recently that sparked my curiosity. For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;an old bridge: How was it constructed? What was it’s general strategy for staying up? (Was it held up by tension or compression? I couldn’t tell)&lt;/li&gt;
  &lt;li&gt;Metal tags nailed to a sidewalk: Were they marking property lines? Underground pipes?&lt;/li&gt;
  &lt;li&gt;a pipe in a basement: it was warm. Obviously it had warm water inside, but I couldn’t tell why. It &lt;em&gt;might&lt;/em&gt; have been a return for a radiant heater, but I wasn’t sure.&lt;/li&gt;
  &lt;li&gt;A phrase someone said. Of all the ways they could have expressed a similar thought, why’d they use that particular phrase?&lt;/li&gt;
  &lt;li&gt;many many more things. (The topic of programming alone could fill books with just questions. Everything from “how the heck do wifi signals not interfere with each other” to “what’s the physics of the millions and billions of calculations a computer does every second to render my favorite cat video?”)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the thing. It would be very, very easy to not find them curious.&lt;/p&gt;

&lt;p&gt;I mean, come on. This is 21st century America! We’ve got real things to worry about, plus smart phones, plus plenty of outrage to marinate in all day. Why be curious about a stupid bridge?&lt;/p&gt;

&lt;p&gt;In a small way, curiosity is a potent antidote to all the mind-numbing attention-stealing crap shoved at us from every corner of the average environment.&lt;/p&gt;

&lt;p&gt;Once I started looking for things to find curious, I found them &lt;em&gt;everywhere&lt;/em&gt;. I’m glad I started looking.&lt;/p&gt;

&lt;p&gt;This extends to people, too. I’ve been apologizing &lt;em&gt;regularly&lt;/em&gt; to people for what will feel like an interrogation, as I start grilling them. My go-to questions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What’s a good book you’ve read recently? Why? (If not a good book, a good piece of media. Movie, TV show, documentary, comic book, cartoon, magazine, blog)&lt;/li&gt;
  &lt;li&gt;If you could go back to {current_age - (age * .25)} and give yourself any piece of advice, knowing it was coming from current you, what would it be? Before you tell me the advice, tell me the context. What was going on in your life at the time, etc.&lt;/li&gt;
  &lt;li&gt;What’s something the world has too much of?&lt;/li&gt;
  &lt;li&gt;What’s something you look forward to about aging? What’s something you fear about aging?&lt;/li&gt;
  &lt;li&gt;Are you spiritual, or religious? Why/why not?&lt;/li&gt;
  &lt;li&gt;What’s the hardest thing you’ve faced in the last year?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve asked one or more of these questions of probably more than 100 people. I’ve learned so much from these questions, and follow-up questions. I’ll probably be asking some variation of these questions until the day I die, and that doesn’t trouble me one bit.&lt;/p&gt;

&lt;h2 id="related-resources"&gt;Related resources&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://blog.robertsj.com/work-and-intellectual-curiosity/"&gt;Naval Ravikant on work and intellectual curiosity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://arxiv.org/pdf/0812.4360.pdf"&gt;Driven by Compression Progress: A Simple Principle Explains Essential Aspects of Subjective Beauty, Novelty, Surprise, Interestingness, Attention, Curiosity, Creativity, Art, Science, Music, Jokes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.farnamstreetblog.com/2017/09/open-closed-minded/"&gt;The Difference Between Open-Minded and Closed-Minded People&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.farnamstreetblog.com/2013/11/richard-feynman-curiosity/"&gt;It has to do with curiosity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Mon, 25 Dec 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/cultivate-curiosity-reasons-to-be-more-childlike</guid></item><item><title>My programming history (part 2)</title><link>http://negfeedback.blogspot.com/2017/12/my-programming-history-part-2.html</link><description>This post overlaps a little bit with the &lt;a href="http://negfeedback.blogspot.com/2014/05/my-programming-history-part-1.html"&gt;the previous one&lt;/a&gt;, recapping my programming history.&lt;br /&gt;
&lt;br /&gt;
We ended the previous part in 2002 when I finished my Masters and started teaching, but I want to go into a little more detail on my history with scripting languages.&lt;br /&gt;
&lt;br /&gt;
I encountered Matlab for the first time in my second year (in 1998) in a course called CRV220. I still have the study guide so I can say with confidence that we were taught a combination of Turbo Pascal and Matlab. At the time, the Turbo Pascal environment was much nicer than the Matlab one. Even though the Borland IDE was text-based, it had syntax highlighting and step-by-step debugging. It looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://i.ytimg.com/vi/fjBPf32oC1c/maxresdefault.jpg" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="225" src="https://i.ytimg.com/vi/fjBPf32oC1c/maxresdefault.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
By contrast, in 1998 Matlab was in version 5.2 and looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogs.mathworks.com/images/steve/2009/logical-indexing-matlab-5.1.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogs.mathworks.com/images/steve/2009/logical-indexing-matlab-5.1.png" width="307" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
We typed Matlab code into Notepad and executed it from this command window. The most impressive part of Matlab was that it could produce graphical output very easily. But the development environment was non-existent. It was, however, very clear that you could solve engineering problems using much less Matlab code than Turbo Pascal. Matlab was also the first language I encountered which had a REPL - you could type commands into the command window one at a time and see the result. I really liked this concept.&lt;br /&gt;
&lt;br /&gt;
In 1998 also bought an &lt;a href="https://en.wikipedia.org/wiki/HP_48_series"&gt;HP 48 GL calculator&lt;/a&gt;&amp;nbsp;and spent a lot of time programming it do solve problems like balancing chemical equations and so on. We were often allowed to use our calculators in tests, but they were often cleared before we wrote. The HP introduced me to the idea of &lt;a href="https://en.wikipedia.org/wiki/Stack-oriented_programming_language"&gt;stack-based languages&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
In my final year (in 2000), we did our final year project calculations using a spreadsheet called &lt;a href="https://en.wikipedia.org/wiki/Quattro_Pro"&gt;Quattro Pro&lt;/a&gt;, since Excel had not yet achieved the dominant position it currently enjoys. We did not do much programming in our final year.&lt;br /&gt;
&lt;br /&gt;
By the time I started my Masters in 2001, Matlab had just undergone a major rework in the release of version 6, moving to a Java-based workspace and for the first time Matlab was an IDE with an integrated code editor, debugging, and all the features from the Turbo Pascal IDE that I had missed when I first encountered Matlab. I found this new environment quite comfortable and used it happily throughout my Masters work. I used it to do the actual simulation and to produce all the graphs in my dissertation. But I had also bumped up against one of the things that Matlab was not very good at when I was writing the code to make the call graph I posted in the previous part: Matlab was really terrible at text processing.&lt;br /&gt;
&lt;br /&gt;
By 2002 I was completely immersing myself in the Unix way. I had started to see the power of the "small tools doing one thing well" philosophy and spend a great deal of time reading the GNU Info pages for all the various unix tools while also learning about Richard Stalman and the Free Software movement. I was using Matlab on my Linux machine and learning bash. This is when I started learning Emacs, after reading &lt;a href="http://cristal.inria.fr/~weis/info/commandline.html"&gt;In the beginning was the commandline&lt;/a&gt;&amp;nbsp;where Neal Stephenson says the following about it:&lt;br /&gt;
&lt;br /&gt;
"I use emacs, which might be thought of as a thermonuclear word processor. It was created by Richard Stallman; enough said. It is written in Lisp, which is the only computer language that is beautiful. It is colossal, and yet it only edits straight ASCII text files, which is to say, no fonts, no boldface, no underlining. In other words, the engineer-hours that, in the case of Microsoft Word, were devoted to features like mail merge, and the ability to embed feature-length motion pictures in corporate memoranda, were, in the case of emacs, focused with maniacal intensity on the deceptively simple-seeming problem of editing text."&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Teaching&lt;/h2&gt;
In the first semester of 2002 I was the teaching assistant for CRV210 (the same subject where I had learned Matlab, now moved to the first semester). In the second semester I took over CMO320 (Mass transfer) from a lecturer who had moved to New Zealand. At this point I was done with my Masters and thinking of but had not yet enrolled for my PhD. I barely kept my head above water in that first semester, having to revise the material even as I taught it. In the second go around I started using more computer methods in my teaching, using Excel and Matlab to solve mass transfer problems.&lt;br /&gt;
&lt;br /&gt;
As I did this, I started realising that our students were not well prepared to deal with computer solutions of these problems. I eventually moved over to teaching our computer course.&lt;br /&gt;
&lt;h2&gt;
Other languages&lt;/h2&gt;
I started evaluating different scripting languages which would be better at the kinds of string processing I had done for the call graph program and came across Perl and Python around this time. The earliest proper Python program I could find in my records was from 2004 and was for creating the same kind of file I used to do the call graph (the &lt;a href="https://www.graphviz.org/"&gt;GraphViz&lt;/a&gt; package). I also learned the classic grep, sed and awk combination for text processing in Linux, motivated largely by reading "&lt;a href="http://www.oreilly.com/openbook/utp/"&gt;Unix Text Processing&lt;/a&gt;"&lt;br /&gt;
&lt;br /&gt;
I picked up Fortran around 2005 as I started looking for ways to speed up my simulations. In the process I learned that modern Fortran was not at all like the FORTRAN 77 that people love to mock. It is a pretty decent language for numerical work. I learned R in 2007 while I was looking for better ways to handle statistical graphics. At that time R was the best language to learn for statistical work. Some might say it still is, even though Python has the big momentum for data science as of 2017.&lt;br /&gt;
&lt;h2&gt;
Teaching programming&lt;/h2&gt;
&lt;div&gt;
I started teaching CRV210 in 2006. Before I did, I went on a deep dive to understand the best ways to teach programming. I found out about the MIT programming course and read &lt;a href="https://mitpress.mit.edu/sicp/full-text/book/book.html"&gt;The Structure and Interpretation of Computer Programs&lt;/a&gt;, picking up a deep and abiding love for Lisp in the process. I read up on SmallTalk, various graphical languages for teaching programming and all the different models which can be used to understand programming.&lt;br /&gt;
&lt;br /&gt;
I settled on teaching Matlab with a strong focus on functional programming. I taught students to avoid scripts and write everything as functions, building functionality up slowly. I taught recursion and scoping before I even handled basic iteration (for loops). I think this made students understand functions a lot better, but it was an unpopular choice. My students tend to view programming more as a necessary evil than the transformative experience I found it to be. They want to solve problems and learn as little programming on the way to those solutions. This made my course feel hopelessly obtuse as I went over problems like computability and logic before simple things like solving a set of equations using the tools.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Moving from Matlab to open source and Python&lt;/h2&gt;
Not long after I started teaching programming, it became clear to me that students were pirating Matlab at an alarming rate. Part of the problem was that the cheap student version could only handle small matrices. The problem actually became more pronounced after the Mathworks moved over to a more capable student version which required you to send in your proof of registration to get the student discount. Most students found it easier to crack a downloaded version than to deal with the paperwork of getting the student version. The university was also paying a large sum of money to retain Matlab licenses for the lab computers, and we calculated large costs for he research license which we would need to do actual research with Matlab instead of only using it for teaching.&lt;br /&gt;
&lt;br /&gt;
I started gathering support for a move to Python. The first phase of this was to stop renewing our license for Matlab and move to Octave, an open-source reimplementation of &amp;nbsp;Matlab. This allowed lecturers to retain their Matlab code and get used to a less featureful environment (we were back to a single window interface). CRV was taught for the last time in 2008. Our students started attending the MPR212 classes in 2009, which are now still taught to all the engineering students at UP. They moved to Python in 2013 and from Python scripts to Jupyter Notebooks in 2016.&lt;br /&gt;
&lt;h2&gt;
The notebook revolution&lt;/h2&gt;
&lt;div&gt;
I started hearing about IPython notebooks around 2011, but I only started using them at the end of 2012. It took a while for me to warm to them, but I now feel they are excellent as an exploration tool as well as a teaching tool. I have committed deeply to producing &lt;a href="https://github.com/alchemyst/Dynamics-and-Control/blob/master/README.md"&gt;notebooks&lt;/a&gt; for the subjects that I teach. There is a great deal of momentum behind the Jupyter project right now and I think they will continue to be one of the best ways to interact with your code for a couple of years yet. My one big issue with notebooks is that bundling the results of calculations together with the code makes it quite hard to handle them in source code management tools. But I am also sure that a future incarnation will fix this issue. It's not a big enough problem to cancel the benefit.&lt;/div&gt;
&lt;h2&gt;
Final word&lt;/h2&gt;
Right now I feel like we made the right bet when we moved away from Matlab. Python is a much more general purpose language and has a large installed base. I think it is a better first language than Matlab and is something that you can see yourself using even when you go to industry. Of course Matlab hasn't stood still, and is still one of the fastest ways to solve a problem if a toolbox exists for the field you're in, but I haven't felt the need to open much else than Python for a very long time.&lt;br /&gt;
&lt;br /&gt;
I'm keeping an eye on Julia as a competitor to Python in the computational space, but so far it seems to lack critical mass. I'm also testing the waters on Rust as a replacement for Fortran for my high speed code, but it also has too little support for the well-established numerical libraries.&lt;br /&gt;
&lt;br /&gt;
I think the last bit of my recap on history will be about simulation environments, moving from Simulink to Modelica, but this post is probably already too long.&lt;/div&gt;</description><author>Negative Feedback</author><pubDate>Mon, 25 Dec 2017 10:40:48 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2017/12/my-programming-history-part-2.html</guid></item><item><title>Books I read in 2017</title><link>https://nindalf.com/posts/books-i-read-in-2017/</link><description>I share my top book recommendations for 2017, including Trevor Noah's Born a Crime and The Dictator's Handbook by Bruce Bueno de Mesquita and Alastair Smith.</description><author>Krishna's blog</author><pubDate>Mon, 25 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/books-i-read-in-2017/</guid></item><item><title>Smoking in fashion as a promise of bodily experience</title><link>https://rybakov.com/blog/smoking_as_promise/</link><description>&lt;p&gt;&lt;figure class=""&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/fakenose.jpg" /&gt;




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Diseases have always been fashionable. Tuberculosis &lt;a href="https://www.smithsonianmag.com/science-nature/how-tuberculosis-shaped-victorian-fashion-180959029/"&gt;brought us&lt;/a&gt; the fad of looking pale and skinny. Syphilis and it&amp;rsquo;s symptomatic light sensitivity and rotten noses brought us &lt;a href="https://www.racked.com/2015/4/6/8349545/sunglasses-history"&gt;sunglasses and fake noses&lt;/a&gt; that were worn even by those not afflicted by the illness.&lt;br /&gt;
I won&amp;rsquo;t go into detail as to why disease becomes fashionable - first, I don&amp;rsquo;t really know, and then there&amp;rsquo;s a &lt;a href="http://fashionablediseases.info/podcasts.php"&gt;whole conference&lt;/a&gt; on it.&lt;/p&gt;
&lt;p&gt;One point of interest for me is how a fashionable disease is a &lt;em&gt;promise of a physical experience&lt;/em&gt;. Similar to a certain subset of internet memes I &lt;a href="../everyday_movement_of_expanded_body/#mental-gymnastics"&gt;wrote about before&lt;/a&gt;, where a human or a non-human stand-in reminds the viewer of a bodily experience from everyday life.&lt;br /&gt;
Smoking in film and fashion can be interpreted in the same way - as a powerful, addictive, self-inflicted bodily experience, as a promise of being highly attentive to the body, the fingers, the mouth and the inside of the lungs.&lt;/p&gt;
&lt;p&gt;As smoking becomes much less acceptable socially - and to advertisers - the fashion photography looks for new ways to make the signifier more abstract - the models shown here are not-smoking emptied non-cigarettes.&lt;/p&gt;
&lt;p&gt;&lt;figure class=""&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/nonsmoking.jpg" /&gt;




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;It would be interesting to test which other bodily experiences could be promised by fashion - besides the obvious promises of eternal youth, sex and drugs. How about being uncomfortable? Being fat using a fabulous fat-suit? Freezing in the winter while wearing a down jacket with huge holes? Not being able to pee, as the process of unwrapping the clothes takes hours? Never being thirsty with a 12-liter water pack hidden in the garment? Feeling unprotected with sleeves that don&amp;rsquo;t allow your hands to touch your body, combined with an exposed belly?&lt;/p&gt;
&lt;p&gt;Include some promise of bodily experience within your work. It changes things.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;What is not in this text but could be:
- golden teeth and broken nose as a criminal status symbol
- movement restricting feathers in male peacocks as a sign of fitness
- jewellery made of wearer&amp;rsquo;s hair for cancer patients
- fidget jewellery for autists as described in &lt;a href="../essay/everyday_movement_of_expanded_body/#eigenbewegung-des-k%C3%B6rpers"&gt;a previous text&lt;/a&gt;&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 24 Dec 2017 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/smoking_as_promise/</guid></item><item><title>Man's Search for Meaning</title><link>https://nindalf.com/posts/mans-search-for-meaning/</link><description>Man's Search for Meaning offers a unique perspective on the Holocaust and introduces the theory of logotherapy.</description><author>Krishna's blog</author><pubDate>Sun, 24 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/mans-search-for-meaning/</guid></item><item><title>Installing Arch Linux on my Intel NUC</title><link>https://utf9k.net/blog/arch-nuc-install/</link><description>My self help guide to installing Arch</description><author>utf9k</author><pubDate>Sat, 23 Dec 2017 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/arch-nuc-install/</guid></item><item><title>ELBO Surgery</title><link>https://rachitsingh.com/elbo-surgery/</link><description>&lt;p&gt;&lt;strong&gt;tldr: The ubiquitous isotropic Gaussian prior for generative models doesn't make sense / doesn't work, which motivates work on priors.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At NIPS, Dawen Liang mentioned Hoffman &amp;amp; Johnson's &lt;a href="http://approximateinference.org/accepted/HoffmanJohnson2016.pdf"&gt;ELBO surgery&lt;/a&gt; paper offhand while talking about tuning KL divergences, and it's very interesting, so I thought I'd go over it. It's very clearly written, so I won't go into any of the derivations, but instead offer my interpretation.&lt;/p&gt;
&lt;h3 id="motivation"&gt;Motivation&lt;/h3&gt;
&lt;p&gt;I worked in the past on applying variational inference and comparing it to models trained via MAP/MLE inference. I decomposed the evidence lower bound (ELBO) as:&lt;/p&gt;
&lt;div&gt;
$$\mathcal{L} = \frac{1}{N}\sum_{i = 1}^N\left(\underbrace{\mathbb{E}_{q(z_n | x_n)}[\log p(x_n | z_n)]}_{\text{log-likelihood}} - \underbrace{\operatorname{KL}(q(z_n | x_n) || p(z_n))}_{\text{KL divergence}}\right)$$
&lt;/div&gt;
&lt;p&gt;This is, I think, the most common interpretation: split the ELBO into a reconstruction term and a KL divergence term. The first encourages the model to reconstruct the data, and the second &lt;em&gt;regularizes&lt;/em&gt; the model, asking the posterior distribution over $z_n$ to have a certain shape, like a Gaussian. For example, in a VAE the second term is what prevents the model from just learning a Dirac delta-like posterior $q(z_n | x_n) \sim \mathcal{N}(x_n, 0.001)$ around the original value&lt;sup class="footnote-reference" id="fr-1-1"&gt;&lt;a href="https://rachitsingh.com/elbo-surgery/#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;In the NLP world, people have seen some problems though - when we have a very powerful generative model (e.g., an RNN), the KL divergence can vanish. This means the posterior $q(z_n | x_n) \approx p(z_n)$ &lt;em&gt;learns nothing&lt;/em&gt; about the data, so the generative model $p(x_n | z_n)$ becomes like a language model. The usual trick is to anneal the KL divergence term in, so that that inference can be useful. A lot of people are unhappy with this because it adds extra hyperparameters and it feels really non-Bayesian.&lt;/p&gt;
&lt;h3 id="contribution"&gt;Contribution&lt;/h3&gt;
&lt;p&gt;The contribution of this paper is the following observation: the KL divergence above measures the distance from the posterior for a single $z_n$ to the prior, but we really care about the KL divergence from the average posterior over all data points to the prior. So they define&lt;/p&gt;
&lt;div&gt;
$$q(z) = \frac{1}{N}\sum_{n = 1}^Nq(z_n | x_n)$$
&lt;/div&gt;
&lt;p&gt;which is the &lt;em&gt;average&lt;/em&gt; posterior we see. The intuition here is that when we're trying to do inference, we shouldn't exactly be penalized for being very confident in $q(z_n | x_n)$. However, we want the &lt;em&gt;average&lt;/em&gt; distribution to be close to the prior, so this term can go to 0 safely without worrying about whether the posterior has learned something. In fact, at the cost of a lot of extra computation, we can even safely set the prior to be this distribution, or let $p(z) \triangleq q(z)$!
&lt;img alt="" src="https://rachitsingh.com/figure_1.png" title="The average distribution. On the left, we see a confident posterior over the latent variable corresponding to a point, which is penalized. On the right we see the *average* posterior with two points. " /&gt;
&lt;img alt="" src="https://rachitsingh.com/figure_2.png#smaller" title="The average distribution over 10 data points. This corresponds much better to the prior, as we'd hope." /&gt;&lt;/p&gt;
&lt;p&gt;Then, they view $n$, the index variable, as a random variable, where the interpretation is that our generative model samples $n \sim \operatorname{Unif}[N]$, and then picks a $z_n$ from $p(z)$. This isn't totally intuitive, but it makes more sense on the inference side, which we'll see below. Finally, they decompose the second term further as follows:&lt;/p&gt;
&lt;div&gt;
$$\mathcal{L} = \underbrace{\frac{1}{N}\sum_{i = 1}^N E_{q(z_n | x_n)}[\log p(x_n | z_n)]}_{\text{log-likelihood}} - \underbrace{\vphantom{\sum_{i = 1}^N}E_{q(z)}[\operatorname{KL}(q(n | z) || p(n)))]}_{\text{index-code mutual information}} - \underbrace{\vphantom{\sum_{i = 1}^N}\operatorname{KL}(q(z) || p(z))}_{\text{marginal KL}}$$
&lt;/div&gt;
&lt;p&gt;(this is not an obvious derivation, but the math checks out). Here, $q(n | z)$ (which we can decompose using Bayes' law) can be interpreted as 'the distribution over which datapoint this $z$ belongs to'. The description 'index-code mutual information' comes from an alternative way to write the expression, but I like this one more. Also, they upper bound this value by $\log N$, a not insignificant quantity! This is 11 nats on MNIST.&lt;/p&gt;
&lt;h3 id="experiments"&gt;Experiments&lt;/h3&gt;
&lt;p&gt;Finally, the most interesting section, which is the quantitative analysis: they apply the model to a set of the usual VAEs with an isotropic Gaussian prior used for binarized MNIST, and get the following results:&lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
  	&lt;th&gt;&lt;/th&gt;
    &lt;th&gt;ELBO&lt;/th&gt;
    &lt;th&gt;Average KL&lt;/th&gt;
    &lt;th&gt;Mutual info.&lt;/th&gt;
    &lt;th&gt;Marginal KL&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th class="left_column"&gt;2D latents&lt;/th&gt;
    &lt;td&gt;-129.63&lt;/td&gt;
    &lt;td&gt;7.41&lt;/td&gt;
    &lt;td&gt;7.20&lt;/td&gt;
    &lt;td&gt;0.21&lt;/td&gt;
  &lt;/tr&gt;
    &lt;tr&gt;
    &lt;th class="left_column"&gt;10D latents&lt;/th&gt;
    &lt;td&gt;-88.95&lt;/td&gt;
    &lt;td&gt;19.17&lt;/td&gt;
    &lt;td&gt;10.82&lt;/td&gt;
    &lt;td&gt;8.35&lt;/td&gt;
  &lt;/tr&gt;
    &lt;tr&gt;
    &lt;th class="left_column"&gt;20D latents&lt;/th&gt;
    &lt;td&gt;-87.45&lt;/td&gt;
    &lt;td&gt;20.2&lt;/td&gt;
    &lt;td&gt;10.67&lt;/td&gt;
    &lt;td&gt;9.53&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;So, what's going on is that as we increase the number of latent dimensions to 10/20, the marginal KL gets large! Which means that &lt;em&gt;the Gaussian prior is not good enough anymore&lt;/em&gt;. At least, that's my interpretation. This is interesting food for thought, since that gives a lot of evidence for a hunch that people have had for a while (and motivates work on new prior distributions, like &lt;a href="http://rachitsingh.com/ibp_dgm.pdf"&gt;our paper&lt;/a&gt;).&lt;/p&gt;
&lt;footer class="footnotes"&gt;
&lt;ol class="footnotes-list"&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;Well, if the latent capacity is large enough. Otherwise it might learn, e.g. a PCA-like compression, or some other compression if the inference and generation nets are more crazy. &lt;a href="https://rachitsingh.com/elbo-surgery/#fr-1-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/footer&gt;</description><author>Rachit Singh</author><pubDate>Sat, 23 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://rachitsingh.com/elbo-surgery/</guid></item><item><title>Setting up for 'SQL Queries for Mere Mortals'</title><link>https://josh.works/setting-up-sql-queries-for-mere-mortals</link><description>&lt;p&gt;This tweet is from… a while ago. Turns out I didn’t dig into this book, because the pace at Turing didn’t allow for a few weeks of thinking &lt;em&gt;just&lt;/em&gt; about SQL.&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;yes, I'm digging into sql to better my AR skills, and ultimately whatever I need to use next. &lt;a href="https://t.co/UhjyGKv1FQ"&gt;pic.twitter.com/UhjyGKv1FQ&lt;/a&gt;&lt;/p&gt;&amp;mdash; Josh Thompson (@josh_works) &lt;a href="https://twitter.com/josh_works/status/856596417095229441?ref_src=twsrc%5Etfw"&gt;April 24, 2017&lt;/a&gt;&lt;/blockquote&gt;


&lt;p&gt;I’ve got more time in my life now, and the company I work for makes &lt;em&gt;heavy&lt;/em&gt; use of SQL queries, so I’m spending a little time each day working through this book. The following started as a gist, and I’m putting here, so I can more easily share it with others.&lt;/p&gt;

&lt;h3 id="why-study-sql"&gt;Why Study SQL&lt;/h3&gt;

&lt;p&gt;Pretty much everything on the internet lives in a database. I figure any boost to my SQL skills will provide outsized returns down the road.&lt;/p&gt;

&lt;p&gt;For example, just &lt;em&gt;today&lt;/em&gt; I used some basic SQL queries to validate an assumption I had about the frequencies of &lt;code class="language-plaintext highlighter-rouge"&gt;null&lt;/code&gt; values in certain places in our database. I wouldn’t have even thought to try that, if I didn’t know in advance what I could do with a basic SQL query.&lt;/p&gt;

&lt;p&gt;If you buy this book, and want to get set up with it’s accompanying data on your own computer, so you can practice yourself and follow along with the book… read on.&lt;/p&gt;

&lt;p&gt;The friction of getting set up kept me from getting started with this book, and I don’t want that to happen to you too. :)
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’m working on wrapping my head around SQL. Be it MySql, SQLite, PostgreSQL, etc - these are all relational database management tools, and (I assume) they have much in common with each other.&lt;/p&gt;

&lt;p&gt;I’ve got a copy of &lt;a href="http://www.informit.com/store/sql-queries-for-mere-mortals-a-hands-on-guide-to-data-9780321992475"&gt;SQL Queries for Mere Mortals&lt;/a&gt;, and I plan on spending some time each day over the next ~month working through the lessons.&lt;/p&gt;

&lt;p&gt;Lesson 1 is “setting the damn thing up”. I struggled so much getting it set up, I wrote &lt;a href="http://www.informit.com/store/sql-queries-for-mere-mortals-a-hands-on-guide-to-data-9780321992475"&gt;this gist&lt;/a&gt; and gave it to a &lt;a href="https://twitter.com/richthofen"&gt;former coworker/awesome developer&lt;/a&gt; when he offered to help.&lt;/p&gt;

&lt;p&gt;Turns out, he helped me set it up! I got it working!&lt;/p&gt;

&lt;p&gt;And then Turing took over my life, and I stopped studying, then I got a job, and moved machines, and had to start the install from scratch.&lt;/p&gt;

&lt;p&gt;So, I’m writing this guide as if &lt;em&gt;you&lt;/em&gt;, dear reader, wanted to follow along through the book, and needed help getting the “dev environment” set up locally.&lt;/p&gt;

&lt;h2 id="step-1---install-mysql-on-your-machine"&gt;Step 1 - install MySQL on your machine&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;note: I ended up wiping my entire MySQL local install and instead setting it on Docker. My company uses MySQL 5.6, which is a generation behind the current 5.7, and navigating between the two locally was a massive headache. The rest of this will still work, if you’re good running MySQL 5.7.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don’t have much help for you here. I struggled hard on this. Turns out I was using Brew to manage MySQL, and that wasn’t playing nice with other tools, so I threw my hands in the air, and did a clean uninstall/re-install of MySQL on my machine.&lt;/p&gt;

&lt;p&gt;I followed &lt;a href="https://coderwall.com/p/os6woq/uninstall-all-those-broken-versions-of-mysql-and-re-install-it-with-brew-on-mac-mavericks"&gt;these instructions&lt;/a&gt; to remove/reinstall.&lt;/p&gt;

&lt;p&gt;And, the last setup command in the instructions is deprecated. Where it says to use:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;instead use:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mysqld -initialize --verbose --user=whoami --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(The latter came from a comment in the article.)&lt;/p&gt;

&lt;p&gt;In your command line, try to run &lt;code class="language-plaintext highlighter-rouge"&gt;mysql&lt;/code&gt;. If it lets you in, great! if not… read on&lt;/p&gt;

&lt;h2 id="step-11---creating-a-user-for-mysql"&gt;Step 1.1 - creating a user for MySQL&lt;/h2&gt;

&lt;p&gt;I followed the instructions in &lt;a href="https://stackoverflow.com/a/25728868/3210178"&gt;this StackOverflow post on creating MySQL users&lt;/a&gt; and got it working:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ mysql -u root

mysql&amp;gt; CREATE USER 'joshthompson'@'localhost' IDENTIFIED BY 'super_secret_password';
Query OK, 0 rows affected (0.00 sec)

mysql&amp;gt; GRANT ALL PRIVILEGES ON * . * to 'joshthompson'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql&amp;gt; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and now I can connect to the DB by running &lt;code class="language-plaintext highlighter-rouge"&gt;$ mysql -p&lt;/code&gt;. It asks for my password, I enter it, and I’m good to go.&lt;/p&gt;

&lt;h2 id="step-2---import-sample-date-on-your-machine"&gt;Step 2 - import sample date on your machine&lt;/h2&gt;

&lt;p&gt;I’m using &lt;a href="https://www.sequelpro.com/"&gt;Sequel Pro&lt;/a&gt; at the moment. I &lt;em&gt;think&lt;/em&gt; you could do this all from the command line, but since I use Sequel Pro for my real job, I want to build familiarity with the tool. (Despite “pro” in the name, the software is free.)&lt;/p&gt;

&lt;p&gt;In Sequel Pro:&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: Local Development
host: 127.0.0.1
username: your_username
password: your_password
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;click &lt;code class="language-plaintext highlighter-rouge"&gt;connect&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should now be connected to a database in Sequel Pro, and you’re ready to import some data.&lt;/p&gt;

&lt;p&gt;The book includes companion data so the reader can practice the queries mentioned in the book. &lt;a href="http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/bookreg/9780321992475/9780321992475_README.html"&gt;Here’s the readme for the data&lt;/a&gt;. The data itself is in a zip available under the “downloads” section &lt;a href="http://www.informit.com/store/sql-queries-for-mere-mortals-a-hands-on-guide-to-data-9780321992475#bss6773f413-100c-4ba8-a4a8-9325c9342776"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Sequel Pro, go to &lt;code class="language-plaintext highlighter-rouge"&gt;File &amp;gt; Import&lt;/code&gt;, and navigate to the data you downloaded and unzipped.&lt;/p&gt;

&lt;p&gt;I started small, and imported everything prefixed with &lt;code class="language-plaintext highlighter-rouge"&gt;00&lt;/code&gt;. As far as I can tell, all the files prefixed with &lt;code class="language-plaintext highlighter-rouge"&gt;00&lt;/code&gt; relate to the schema, but not the actual data. If you import one or all of them, you’ll see a very robust schema, with many tables and keys, but no actual content.&lt;/p&gt;

&lt;p&gt;&lt;img alt="what the files are/do" src="/images/sql_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;After importing the nine &lt;code class="language-plaintext highlighter-rouge"&gt;structure&lt;/code&gt; files, you might see something like this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="structure only" src="/images/sql_2.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;And, after importing the &lt;code class="language-plaintext highlighter-rouge"&gt;data&lt;/code&gt; files:&lt;/p&gt;

&lt;p&gt;&lt;img alt="now with data" src="https://cl.ly/2C282K29371K/_MySQL_5_7_20__127_0_0_1_SalesOrdersModify_Customers02.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;OK! I’m big on getting friction out of the way, and this is helpful. I’ll not touch the &lt;code class="language-plaintext highlighter-rouge"&gt;02&lt;/code&gt; files related to &lt;code class="language-plaintext highlighter-rouge"&gt;views&lt;/code&gt; yet, because &lt;em&gt;i have no idea what those do&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Lets spot check this to make sure it works.&lt;/p&gt;

&lt;p&gt;I’ve got the Third Edition of &lt;em&gt;SQL for Mere Mortals&lt;/em&gt;, published in 2014. I can pop over to page 98, in chapter 4, and run an example query on a given database, to see if it works.&lt;/p&gt;

&lt;p&gt;Here we go…&lt;/p&gt;

&lt;p&gt;The query is (in plain english) “Show me the names of all our vendors”.&lt;/p&gt;

&lt;p&gt;In sql:&lt;/p&gt;

&lt;div class="language-sql highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;VendName&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Vendors&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;Easy enough. The only thing to be mindful of seems to be selecting the right database. If the database doesn’t have the &lt;code class="language-plaintext highlighter-rouge"&gt;Vendors&lt;/code&gt; table, the query comes up blank. So I jump into one of the databases with a &lt;code class="language-plaintext highlighter-rouge"&gt;vendors&lt;/code&gt; table, run the above query, and have results! (I ran it against both &lt;code class="language-plaintext highlighter-rouge"&gt;SalesOrdersExample&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;SalesOrderModify&lt;/code&gt;, and got the same thing.&lt;/p&gt;

&lt;p&gt;&lt;img alt="success" src="/images/sql_04.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;OK, that does it for now. I’m gonna carry on with my learnings elsewhere, and will update this gist occasionally, as needed.&lt;/p&gt;

&lt;p&gt;The rest of my thinking on MySQL will &lt;em&gt;hopefully&lt;/em&gt; just be on the actual building and executing queries, both as the relate to this book, and things I’m learning/wrestling with on the job.&lt;/p&gt;

&lt;p&gt;Just for fun, and to familiarize myself with the databases and tables, I quickly worked through everything in chapter 4. It’s super basic select stuff from single tables, no joins or groupings or anything.&lt;/p&gt;

&lt;p&gt;Onward!&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Fri, 22 Dec 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/setting-up-sql-queries-for-mere-mortals</guid></item><item><title>Sleep is for backpropagation</title><link>http://dimitarsimeonov.com/2017/12/22/sleep-is-for-backpropagation</link><description>&lt;p&gt;Diving deeper and deeper into machine learning and neural networks I
can’t help but notice how some of the techniques there are metaphors
for what happens in our brains. After all, our brains a just a lot
more sophisticated and larger versions of the deep computer networks
that do computer vision, or predict clicks on ads.&lt;/p&gt;

&lt;p&gt;When I first grokked backpropagation, I was in awe about how elegant
it is. An iterative approach to computing the partial derivative of
multi-dimensional, complex probability density function. Beauty, in
the mathematical sense of the word. Then, as I learned about the more
practical aspects of it, I learned about the less intuitive concept of
“batch_size”.&lt;/p&gt;

&lt;p&gt;Every round of backpropagation makes the neural network slightly
better at its task, by updating the individual neurons based on the
errors they make. The batch size comes from the algorighm known as SGD
which will only look at small amount of examples before updating. It
makes sense to look at the data one example at a time, because humans
can learn from single examples. Yet, things tend to work better in,
when the network updates by average amount over a batch of examples.&lt;/p&gt;

&lt;p&gt;&lt;img alt="backprop" class="img-responsive" src="http://mitko.github.io/assets/image/20121222_sleep_backprop/backprop.gif" /&gt;&lt;/p&gt;

&lt;p&gt;(Image credit: https://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/)&lt;/p&gt;

&lt;p&gt;The computer will look at multiple examples, then it will update its
brain to be better at its task. A human will have a day full of work
and conversations, and then they will go to sleep. Almost as if… the
human is updating their brain connections during that time. Doing a
backpropagation over the batch of experiences during the day.&lt;/p&gt;

&lt;p&gt;Here’s how I imagine the human brain. As we go with our days, our
neurons collect feedback signals about all the things they did
wrong. Those signals manifest themselves as “error chemicals” at each
neuron, which temporary update its function. If a neuron gathers too
much error chemicals, it gets tired. When too many neurons get tired,
we need to sleep. Sleep will remove the error chemicals, and update
the underlying neurons in the direction the error chemicals
suggest. We can help this process of learning by getting enough sleep,
but also by taking naps when needed and meditating.&lt;/p&gt;

&lt;p&gt;Even if you think this “error chemical” model is nuts, I don’t
disagree with you. But I think that the model is still more useful
than nothing. At the least, I’ve prioritized getting good sleep
recently, as I’m trying to learn a whole bunch of things, and I think
sleep becomes necessary to “save” the current learnings before
starting into others. I’ve also been pacing my learning through the
day, realizing that taking breaks of mental rest but physical activity
do help to recharge me for more learning.&lt;/p&gt;

&lt;p&gt;And I’ve heard and read other things to suggest that “the error
chemical” model is not too different from reality.  For example, the
amount of sleep necessary increases with age. Babies need more sleep
and more often because their brains have so much to adapt to. And old
people don’t need too much sleep. Furthermore, at end of every day, it
often happens that our dreams reference things that happened to us,
such as eating spaghetti, or playing with a dog.&lt;/p&gt;

&lt;p&gt;&lt;img alt="dog_spaghetti" class="img-responsive" src="/assets/image/20121222_sleep_backprop/dog_spaghetti.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;And sometimes we have nightmares about trauma. PTSD is at least
partially about having learned about a version of reality that doesn’t
fit our normality assumptions.&lt;/p&gt;

&lt;p&gt;Additionally, cramming for exams doesn’t work. Not if you want to get
a deep and lasting understanding. Instead, by engaging in deliberate
and consistent practice, it is possible to master a skill over a long
time.&lt;/p&gt;

&lt;p&gt;And not just for advanced skills. Sleep is universal among
animals. Even fish sleep. Which means that sleep must have a universal
and simple purpose. And updating the error chemicals makes sense even
if you’re a dumb fish.&lt;/p&gt;

&lt;p&gt;But even if you’re not a dumb fish. If you a smart human. There’s a
bunch of research on the hippocampus. It’s where the hippopotamumi go
to college :P. It’s the area of brain responsible for memories. And it
can get full of hippos during a day of learning.&lt;/p&gt;

&lt;p&gt;&lt;img alt="hippocampus" class="img-responsive" src="/assets/image/20121222_sleep_backprop/hippocampus.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;A good night of sleep helps those hippos graduate and go around the
brain, looking for a place to settle down. Not getting enough sleep is
like failing all the hippos, so they remain in the hippocampus for
longer. They can’t graduate, but they’ve filled the hippocampus. So no
new hippos can arrive. No new memories can be made until the old
hippos graduate, or drop out.&lt;/p&gt;

&lt;p&gt;&lt;img alt="too_many_hippos" class="img-responsive" src="/assets/image/20121222_sleep_backprop/too_many_hippos.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Getting a good sleep later on won’t fully reverse the trouble of lost
sleep. The error chemicals will saturate and the neurons will stop
adapting to the new information, or they’ll start forgetting the old
information.&lt;/p&gt;

&lt;p&gt;Again, this model is approximation at best, and reflects only a small
amount of the things sleep is for. But I’ll use it for my reasoning
base.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 22 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/12/22/sleep-is-for-backpropagation</guid></item><item><title>Why Net Neutrality Matters</title><link>https://www.danstroot.com/posts/2017-12-20-why-net-neutrality-matters</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/internet_2.png" /&gt;&lt;br /&gt;&lt;br /&gt;Internet access is so fundamentally important that many people believe that Internet access should be a legal right. The British government has said that it will guarantee a legal right to high-speed internet for all homes and businesses in the U.K. by 2020 under the Digital Economy Act of 2017. Regardless of your belief in the Internet as a legal right, we should all be able to agree that access to the Internet promotes the digital economy and improves the lives of all citizens.&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2017-12-20-why-net-neutrality-matters"&gt;Why Net Neutrality Matters&lt;/a&gt; first appeared on &lt;a href="https://www.danstroot.com"&gt;Dan Stroot's Blog&lt;/a&gt;</description><author>Dan Stroot</author><pubDate>Fri, 22 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2017-12-20-why-net-neutrality-matters</guid></item><item><title>A simple GUI spreadsheet in less than 100 lines of Python</title><link>http://negfeedback.blogspot.com/2017/12/a-simple-gui-spreadsheet-in-less-than.html</link><description>&lt;h2&gt;
Original challenge: Standard library only&lt;/h2&gt;
I set myself a little challenge to write a simple spreadsheet-like program in Python in less than 100 lines, using only the standard library.&lt;br /&gt;
&lt;br /&gt;
The code in &lt;a href="https://github.com/alchemyst/minimal_spreadsheet"&gt;this repository&lt;/a&gt;&amp;nbsp;manages it in 100 non-blank lines, including comments. 88 if you ignore the comments. The full code is also at the end of this post. &lt;i&gt;Note: I have also redone the code in PyQT5. This is discussed after the tkinter code.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
This is what it the program looks like when you run it:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPoeEeXUaqJOFX1BKoa-jS1QipgWwLUxzViV8YwehsKPI7jMQRDEQdtktOAo0ydcMg0vPtqlyH3-Nz65TECYy9YCPxF4ICyVLreQF3giTlZtOvBBIYIQ0CVn7eoAjR6OM9zwMEG4kPRNU/s1600/screenshot.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPoeEeXUaqJOFX1BKoa-jS1QipgWwLUxzViV8YwehsKPI7jMQRDEQdtktOAo0ydcMg0vPtqlyH3-Nz65TECYy9YCPxF4ICyVLreQF3giTlZtOvBBIYIQ0CVn7eoAjR6OM9zwMEG4kPRNU/s640/screenshot.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
You can click on cells to edit their formulae and move around with the arrow keys. Formulae are evaluated once you press Return or navigate way from a cell. Every cell is evaluated as a Python expression. This means you don't do the Excel thing of having formulae start with =. Everything is a fomula. So the formula in A2 in the screenshot above is valid and will evaluate to 1 once focus moves away from the cell. The math module is imported by default, so you can use sin and cos and so on. I use a very cheap and nasty call of eval to make it all work, which you should never do for production code.&lt;br /&gt;
&lt;br /&gt;
Other than using eval, I also play a little fast and loose with the way objects are allowed to touch each other in the code. I allow each cell to access all their siblings directly instead of going through an intermediary. I probably also break a couple of other OO rules along the way with the way the cells propagate their calculations when they are changed. But the whole code only took a couple of hours to write and it actually works.&lt;br /&gt;
&lt;br /&gt;
And now, here is the full code:

&lt;br /&gt;
&lt;pre style="background: #ffffff; color: black;"&gt;&lt;span style="color: dimgrey;"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; tkinter &lt;span style="color: maroon; font-weight: bold;"&gt;as&lt;/span&gt; tk
&lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; math
&lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; re
&lt;span style="color: maroon; font-weight: bold;"&gt;from&lt;/span&gt; collections &lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; ChainMap

Nrows &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5&lt;/span&gt;
Ncols &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5&lt;/span&gt;

cellre &lt;span style="color: #808030;"&gt;=&lt;/span&gt; re&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #400000;"&gt;compile&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;r'&lt;/span&gt;&lt;span style="color: #0f69ff;"&gt;\b&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;[A-Z][0-9]&lt;/span&gt;&lt;span style="color: #0f69ff;"&gt;\b&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; cellname&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; f&lt;span style="color: #0000e6;"&gt;'{chr(ord("A")+j)}{i+1}'&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;class&lt;/span&gt; Cell&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;,&lt;/span&gt; siblings&lt;span style="color: #808030;"&gt;,&lt;/span&gt; parent&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;row &lt;span style="color: #808030;"&gt;=&lt;/span&gt; i
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;col &lt;span style="color: #808030;"&gt;=&lt;/span&gt; j
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings &lt;span style="color: #808030;"&gt;=&lt;/span&gt; siblings
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;name &lt;span style="color: #808030;"&gt;=&lt;/span&gt; cellname&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #0000e6;"&gt;'0'&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Dependencies - must be updated if this cell changes&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Requirements - values required for this cell to calculate&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;StringVar&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry &lt;span style="color: #808030;"&gt;=&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;widget &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Entry&lt;span style="color: #808030;"&gt;(&lt;/span&gt;parent&lt;span style="color: #808030;"&gt;,&lt;/span&gt;
                                       textvariable&lt;span style="color: #808030;"&gt;=&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var&lt;span style="color: #808030;"&gt;,&lt;/span&gt;
                                       justify&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'right'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;FocusIn&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;edit&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;FocusOut&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;update&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;Return&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;update&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;Up&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;move&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #44aadd;"&gt;-&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;Down&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;move&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #44aadd;"&gt;+&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;Left&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;move&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #44aadd;"&gt;-&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        entry&lt;span style="color: #808030;"&gt;.&lt;/span&gt;bind&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&amp;lt;Right&amp;gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;move&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; move&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; rowadvance&lt;span style="color: #808030;"&gt;,&lt;/span&gt; coladvance&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        targetrow &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;row &lt;span style="color: #44aadd;"&gt;+&lt;/span&gt; rowadvance&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;span style="color: #44aadd;"&gt;%&lt;/span&gt; Nrows
        targetcol &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;col &lt;span style="color: #44aadd;"&gt;+&lt;/span&gt; coladvance&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;span style="color: #44aadd;"&gt;%&lt;/span&gt; Ncols

        &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; focus&lt;span style="color: #808030;"&gt;(&lt;/span&gt;event&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            targetwidget &lt;span style="color: #808030;"&gt;=&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;cellname&lt;span style="color: #808030;"&gt;(&lt;/span&gt;targetrow&lt;span style="color: #808030;"&gt;,&lt;/span&gt; targetcol&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;widget
            targetwidget&lt;span style="color: #808030;"&gt;.&lt;/span&gt;focus&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; focus

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; calculate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        currentreqs &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;cellre&lt;span style="color: #808030;"&gt;.&lt;/span&gt;findall&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: dimgrey;"&gt;# Add this cell to the new requirement's dependents&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; r &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; currentreqs &lt;span style="color: #44aadd;"&gt;-&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;r&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps&lt;span style="color: #808030;"&gt;.&lt;/span&gt;add&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;name&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Add remove this cell from dependents no longer referenced&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; r &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs &lt;span style="color: #44aadd;"&gt;-&lt;/span&gt; currentreqs&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;r&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps&lt;span style="color: #808030;"&gt;.&lt;/span&gt;remove&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;name&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: dimgrey;"&gt;# Look up the values of our required cells&lt;/span&gt;
        reqvalues &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;r&lt;span style="color: #808030;"&gt;:&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;r&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; r &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; currentreqs&lt;span style="color: purple;"&gt;}&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Build an environment with these values and basic math functions&lt;/span&gt;
        environment &lt;span style="color: #808030;"&gt;=&lt;/span&gt; ChainMap&lt;span style="color: #808030;"&gt;(&lt;/span&gt;math&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #074726;"&gt;__dict__&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; reqvalues&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Note that eval is DANGEROUS and should not be used in production&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;eval&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; environment&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs &lt;span style="color: #808030;"&gt;=&lt;/span&gt; currentreqs
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; propagate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; d &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;d&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;calculate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;d&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;propagate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; edit&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; event&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;widget&lt;span style="color: #808030;"&gt;.&lt;/span&gt;select_range&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;END&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; update&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; event&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula &lt;span style="color: #808030;"&gt;=&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var&lt;span style="color: #808030;"&gt;.&lt;/span&gt;get&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;calculate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;propagate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# If this was after pressing Return, keep showing the formula&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #400000;"&gt;hasattr&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;event&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #0000e6;"&gt;'keysym'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;and&lt;/span&gt; event&lt;span style="color: #808030;"&gt;.&lt;/span&gt;keysym &lt;span style="color: #44aadd;"&gt;==&lt;/span&gt; &lt;span style="color: #0000e6;"&gt;"Return"&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;var&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;class&lt;/span&gt; SpreadSheet&lt;span style="color: #808030;"&gt;(&lt;/span&gt;tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Frame&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; rows&lt;span style="color: #808030;"&gt;,&lt;/span&gt; cols&lt;span style="color: #808030;"&gt;,&lt;/span&gt; master&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #074726;"&gt;None&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: #400000;"&gt;super&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;master&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;rows &lt;span style="color: #808030;"&gt;=&lt;/span&gt; rows
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols &lt;span style="color: #808030;"&gt;=&lt;/span&gt; cols
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cells &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;pack&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;create_widgets&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; create_widgets&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Frame for all the cells&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cellframe &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Frame&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cellframe&lt;span style="color: #808030;"&gt;.&lt;/span&gt;pack&lt;span style="color: #808030;"&gt;(&lt;/span&gt;side&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'top'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: dimgrey;"&gt;# Column labels&lt;/span&gt;
        blank &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Label&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cellframe&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        blank&lt;span style="color: #808030;"&gt;.&lt;/span&gt;grid&lt;span style="color: #808030;"&gt;(&lt;/span&gt;row&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; column&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; j &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #400000;"&gt;range&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            label &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Label&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cellframe&lt;span style="color: #808030;"&gt;,&lt;/span&gt; text&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #400000;"&gt;chr&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #400000;"&gt;ord&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'A'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #44aadd;"&gt;+&lt;/span&gt;j&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
            label&lt;span style="color: #808030;"&gt;.&lt;/span&gt;grid&lt;span style="color: #808030;"&gt;(&lt;/span&gt;row&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; column&lt;span style="color: #808030;"&gt;=&lt;/span&gt;j&lt;span style="color: #44aadd;"&gt;+&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: dimgrey;"&gt;# Fill in the rows&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; i &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #400000;"&gt;range&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;rows&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            rowlabel &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Label&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cellframe&lt;span style="color: #808030;"&gt;,&lt;/span&gt; text&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #400000;"&gt;str&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i &lt;span style="color: #44aadd;"&gt;+&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
            rowlabel&lt;span style="color: #808030;"&gt;.&lt;/span&gt;grid&lt;span style="color: #808030;"&gt;(&lt;/span&gt;row&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #44aadd;"&gt;+&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; column&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
            &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; j &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #400000;"&gt;range&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
                cell &lt;span style="color: #808030;"&gt;=&lt;/span&gt; Cell&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cells&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cellframe&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
                self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cells&lt;span style="color: #808030;"&gt;[&lt;/span&gt;cell&lt;span style="color: #808030;"&gt;.&lt;/span&gt;name&lt;span style="color: #808030;"&gt;]&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; cell
                cell&lt;span style="color: #808030;"&gt;.&lt;/span&gt;widget&lt;span style="color: #808030;"&gt;.&lt;/span&gt;grid&lt;span style="color: #808030;"&gt;(&lt;/span&gt;row&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #44aadd;"&gt;+&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; column&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #44aadd;"&gt;+&lt;/span&gt;j&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


root &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tk&lt;span style="color: #808030;"&gt;.&lt;/span&gt;Tk&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
app &lt;span style="color: #808030;"&gt;=&lt;/span&gt; SpreadSheet&lt;span style="color: #808030;"&gt;(&lt;/span&gt;Nrows&lt;span style="color: #808030;"&gt;,&lt;/span&gt; Ncols&lt;span style="color: #808030;"&gt;,&lt;/span&gt; master&lt;span style="color: #808030;"&gt;=&lt;/span&gt;root&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
app&lt;span style="color: #808030;"&gt;.&lt;/span&gt;mainloop&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;
Part 2: PyQT5&lt;/h2&gt;
&lt;div&gt;
I posted this blog to Reddit and one of the commenters mentioned that PyQT5 has a nice table widget which is more spreadsheet-like. So I re-did the spreadsheet in PyQT5. The code is functionally similar at the moment and also has approximately the same number of lines (87 non-comment code lines). The main differences are that I could use the QTableWidget to handle all the navigation. I had to do some interesting things with delegates to enable to editing mode I wanted, though, which cost me all the lines I saved from the navigation. I think my next step is going to be to extract the calculation logic into a common class which both of these can use - there is way too much duplication going on here right now!&lt;br /&gt;
&lt;br /&gt;
So, this is what the PyQT5 one looks like. It's a little more compact, but otherwise very similar. The interaction is slightly more spreadsheet-like though, and you get automatic highlighting and selection of multiple cells for free. Very nice.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbZ5BLT-5_eQdf1KWMbhUzENL0Zm2Dxp3REvBXMFPWjIiec8KzkSTaaV3ZPwI4pODQOZyasEcFinw787R-hsl-HFbprdeS6jpUCShFllrMSSnO3yKDlQFsoyMsHF71n6MiYWuW5CHwA7A/s1600/screenshot_pyqt5.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbZ5BLT-5_eQdf1KWMbhUzENL0Zm2Dxp3REvBXMFPWjIiec8KzkSTaaV3ZPwI4pODQOZyasEcFinw787R-hsl-HFbprdeS6jpUCShFllrMSSnO3yKDlQFsoyMsHF71n6MiYWuW5CHwA7A/s1600/screenshot_pyqt5.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
And here is the code. You will notice a great deal of similarity. The key to getting the edit mode thing to work properly is the piece of magic with SpreadSheetDelegate. I didn't think of that myself - I stole it from &lt;a href="https://github.com/baoboa/pyqt5/tree/master/examples/itemviews/spreadsheet"&gt;this PyQT5 example&lt;/a&gt;, which has a much nicer spreadsheet (you can change colours, fonts, print etc) with much worse formula logic.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre style="background: #ffffff; color: black;"&gt;&lt;span style="color: dimgrey;"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; re
&lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; sys
&lt;span style="color: maroon; font-weight: bold;"&gt;from&lt;/span&gt; collections &lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; ChainMap
&lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; math

&lt;span style="color: maroon; font-weight: bold;"&gt;from&lt;/span&gt; PyQt5&lt;span style="color: #808030;"&gt;.&lt;/span&gt;QtCore &lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; Qt
&lt;span style="color: maroon; font-weight: bold;"&gt;from&lt;/span&gt; PyQt5&lt;span style="color: #808030;"&gt;.&lt;/span&gt;QtWidgets &lt;span style="color: maroon; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #808030;"&gt;(&lt;/span&gt;QApplication&lt;span style="color: #808030;"&gt;,&lt;/span&gt; QMainWindow&lt;span style="color: #808030;"&gt;,&lt;/span&gt; QTableWidget&lt;span style="color: #808030;"&gt;,&lt;/span&gt;
        QTableWidgetItem&lt;span style="color: #808030;"&gt;,&lt;/span&gt; QItemDelegate&lt;span style="color: #808030;"&gt;,&lt;/span&gt; QLineEdit&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


cellre &lt;span style="color: #808030;"&gt;=&lt;/span&gt; re&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #400000;"&gt;compile&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;r'&lt;/span&gt;&lt;span style="color: #0f69ff;"&gt;\b&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;[A-Z][0-9]&lt;/span&gt;&lt;span style="color: #0f69ff;"&gt;\b&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; cellname&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; f&lt;span style="color: #0000e6;"&gt;'{chr(ord("A")+j)}{i+1}'&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;class&lt;/span&gt; SpreadSheetDelegate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;QItemDelegate&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; parent&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #074726;"&gt;None&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: #400000;"&gt;super&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;SpreadSheetDelegate&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;parent&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; createEditor&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; parent&lt;span style="color: #808030;"&gt;,&lt;/span&gt; styleOption&lt;span style="color: #808030;"&gt;,&lt;/span&gt; index&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        editor &lt;span style="color: #808030;"&gt;=&lt;/span&gt; QLineEdit&lt;span style="color: #808030;"&gt;(&lt;/span&gt;parent&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        editor&lt;span style="color: #808030;"&gt;.&lt;/span&gt;editingFinished&lt;span style="color: #808030;"&gt;.&lt;/span&gt;connect&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;commitAndCloseEditor&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; editor

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; commitAndCloseEditor&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        editor &lt;span style="color: #808030;"&gt;=&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;sender&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;commitData&lt;span style="color: #808030;"&gt;.&lt;/span&gt;emit&lt;span style="color: #808030;"&gt;(&lt;/span&gt;editor&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;closeEditor&lt;span style="color: #808030;"&gt;.&lt;/span&gt;emit&lt;span style="color: #808030;"&gt;(&lt;/span&gt;editor&lt;span style="color: #808030;"&gt;,&lt;/span&gt; QItemDelegate&lt;span style="color: #808030;"&gt;.&lt;/span&gt;NoHint&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; setEditorData&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; editor&lt;span style="color: #808030;"&gt;,&lt;/span&gt; index&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        editor&lt;span style="color: #808030;"&gt;.&lt;/span&gt;setText&lt;span style="color: #808030;"&gt;(&lt;/span&gt;index&lt;span style="color: #808030;"&gt;.&lt;/span&gt;model&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;data&lt;span style="color: #808030;"&gt;(&lt;/span&gt;index&lt;span style="color: #808030;"&gt;,&lt;/span&gt; Qt&lt;span style="color: #808030;"&gt;.&lt;/span&gt;EditRole&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; setModelData&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; editor&lt;span style="color: #808030;"&gt;,&lt;/span&gt; model&lt;span style="color: #808030;"&gt;,&lt;/span&gt; index&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        model&lt;span style="color: #808030;"&gt;.&lt;/span&gt;setData&lt;span style="color: #808030;"&gt;(&lt;/span&gt;index&lt;span style="color: #808030;"&gt;,&lt;/span&gt; editor&lt;span style="color: #808030;"&gt;.&lt;/span&gt;text&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;class&lt;/span&gt; SpreadSheetItem&lt;span style="color: #808030;"&gt;(&lt;/span&gt;QTableWidgetItem&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; siblings&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: #400000;"&gt;super&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;SpreadSheetItem&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings &lt;span style="color: #808030;"&gt;=&lt;/span&gt; siblings
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; formula&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #400000;"&gt;super&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;data&lt;span style="color: #808030;"&gt;(&lt;/span&gt;Qt&lt;span style="color: #808030;"&gt;.&lt;/span&gt;DisplayRole&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; data&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; role&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt; role &lt;span style="color: #44aadd;"&gt;==&lt;/span&gt; Qt&lt;span style="color: #808030;"&gt;.&lt;/span&gt;EditRole&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt; role &lt;span style="color: #44aadd;"&gt;==&lt;/span&gt; Qt&lt;span style="color: #808030;"&gt;.&lt;/span&gt;DisplayRole&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;display&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #400000;"&gt;super&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;SpreadSheetItem&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;data&lt;span style="color: #808030;"&gt;(&lt;/span&gt;role&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; calculate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        formula &lt;span style="color: #808030;"&gt;=&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt; formula &lt;span style="color: maroon; font-weight: bold;"&gt;is&lt;/span&gt; &lt;span style="color: #074726;"&gt;None&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;or&lt;/span&gt; formula &lt;span style="color: #44aadd;"&gt;==&lt;/span&gt; &lt;span style="color: #0000e6;"&gt;''&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;
            &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt;

        currentreqs &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;set&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;cellre&lt;span style="color: #808030;"&gt;.&lt;/span&gt;findall&lt;span style="color: #808030;"&gt;(&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        name &lt;span style="color: #808030;"&gt;=&lt;/span&gt; cellname&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;row&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;column&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: dimgrey;"&gt;# Add this cell to the new requirement's dependents&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; r &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; currentreqs &lt;span style="color: #44aadd;"&gt;-&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;r&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps&lt;span style="color: #808030;"&gt;.&lt;/span&gt;add&lt;span style="color: #808030;"&gt;(&lt;/span&gt;name&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Add remove this cell from dependents no longer referenced&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; r &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs &lt;span style="color: #44aadd;"&gt;-&lt;/span&gt; currentreqs&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;r&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps&lt;span style="color: #808030;"&gt;.&lt;/span&gt;remove&lt;span style="color: #808030;"&gt;(&lt;/span&gt;name&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: dimgrey;"&gt;# Look up the values of our required cells&lt;/span&gt;
        reqvalues &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;r&lt;span style="color: #808030;"&gt;:&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;r&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; r &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; currentreqs&lt;span style="color: purple;"&gt;}&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Build an environment with these values and basic math functions&lt;/span&gt;
        environment &lt;span style="color: #808030;"&gt;=&lt;/span&gt; ChainMap&lt;span style="color: #808030;"&gt;(&lt;/span&gt;math&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #074726;"&gt;__dict__&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; reqvalues&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: dimgrey;"&gt;# Note that eval is DANGEROUS and should not be used in production&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #400000;"&gt;eval&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;formula&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; environment&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;reqs &lt;span style="color: #808030;"&gt;=&lt;/span&gt; currentreqs

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; propagate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; d &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;deps&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;d&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;calculate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
            self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;siblings&lt;span style="color: #808030;"&gt;[&lt;/span&gt;d&lt;span style="color: #808030;"&gt;]&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;propagate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; display&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;calculate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;propagate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
        &lt;span style="color: maroon; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #400000;"&gt;str&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;value&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;class&lt;/span&gt; SpreadSheet&lt;span style="color: #808030;"&gt;(&lt;/span&gt;QMainWindow&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;,&lt;/span&gt; rows&lt;span style="color: #808030;"&gt;,&lt;/span&gt; cols&lt;span style="color: #808030;"&gt;,&lt;/span&gt; parent&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #074726;"&gt;None&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        &lt;span style="color: #400000;"&gt;super&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;SpreadSheet&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #074726;"&gt;__init__&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;parent&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;rows &lt;span style="color: #808030;"&gt;=&lt;/span&gt; rows
        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols &lt;span style="color: #808030;"&gt;=&lt;/span&gt; cols

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cells &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;create_widgets&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

    &lt;span style="color: maroon; font-weight: bold;"&gt;def&lt;/span&gt; create_widgets&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
        table &lt;span style="color: #808030;"&gt;=&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;table &lt;span style="color: #808030;"&gt;=&lt;/span&gt; QTableWidget&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;rows&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols&lt;span style="color: #808030;"&gt;,&lt;/span&gt; self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        headers &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #808030;"&gt;[&lt;/span&gt;&lt;span style="color: #400000;"&gt;chr&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #400000;"&gt;ord&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #0000e6;"&gt;'A'&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;span style="color: #44aadd;"&gt;+&lt;/span&gt; j&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; j &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #400000;"&gt;range&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;]&lt;/span&gt;
        table&lt;span style="color: #808030;"&gt;.&lt;/span&gt;setHorizontalHeaderLabels&lt;span style="color: #808030;"&gt;(&lt;/span&gt;headers&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        table&lt;span style="color: #808030;"&gt;.&lt;/span&gt;setItemDelegate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;SpreadSheetDelegate&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; i &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #400000;"&gt;range&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;rows&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
            &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt; j &lt;span style="color: maroon; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #400000;"&gt;range&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cols&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
                cell &lt;span style="color: #808030;"&gt;=&lt;/span&gt; SpreadSheetItem&lt;span style="color: #808030;"&gt;(&lt;/span&gt;self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cells&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
                self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;cells&lt;span style="color: #808030;"&gt;[&lt;/span&gt;cellname&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;]&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; cell
                self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;table&lt;span style="color: #808030;"&gt;.&lt;/span&gt;setItem&lt;span style="color: #808030;"&gt;(&lt;/span&gt;i&lt;span style="color: #808030;"&gt;,&lt;/span&gt; j&lt;span style="color: #808030;"&gt;,&lt;/span&gt; cell&lt;span style="color: #808030;"&gt;)&lt;/span&gt;

        self&lt;span style="color: #808030;"&gt;.&lt;/span&gt;setCentralWidget&lt;span style="color: #808030;"&gt;(&lt;/span&gt;table&lt;span style="color: #808030;"&gt;)&lt;/span&gt;


&lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #074726;"&gt;__name__&lt;/span&gt; &lt;span style="color: #44aadd;"&gt;==&lt;/span&gt; &lt;span style="color: #0000e6;"&gt;'__main__'&lt;/span&gt;&lt;span style="color: #808030;"&gt;:&lt;/span&gt;
    app &lt;span style="color: #808030;"&gt;=&lt;/span&gt; QApplication&lt;span style="color: #808030;"&gt;(&lt;/span&gt;sys&lt;span style="color: #808030;"&gt;.&lt;/span&gt;argv&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
    sheet &lt;span style="color: #808030;"&gt;=&lt;/span&gt; SpreadSheet&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;5&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
    sheet&lt;span style="color: #808030;"&gt;.&lt;/span&gt;resize&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;520&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;200&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
    sheet&lt;span style="color: #808030;"&gt;.&lt;/span&gt;show&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
    sys&lt;span style="color: #808030;"&gt;.&lt;/span&gt;exit&lt;span style="color: #808030;"&gt;(&lt;/span&gt;app&lt;span style="color: #808030;"&gt;.&lt;/span&gt;exec_&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;
&lt;/pre&gt;</description><author>Negative Feedback</author><pubDate>Thu, 21 Dec 2017 16:14:32 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2017/12/a-simple-gui-spreadsheet-in-less-than.html</guid></item><item><title>On Friction</title><link>https://josh.works/on-friction</link><description>&lt;p&gt;&lt;em&gt;warning. self-indulgeant diatribe coming. I generally try to avoid these, but it’s my website, and I can write what I want.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We’re rapidly approaching the end of the year, and I’ve got a few dozen ideas rolling around my head that I want to solidify my thoughts on.&lt;/p&gt;

&lt;p&gt;One of the reasons I write these words on this little corner of the internet is simply to clarify my own thinking on a given topic. &lt;a href="/type-publish-done"&gt;I try to not overthink them&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is known as &lt;a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging"&gt;rubber duck debugging&lt;/a&gt; and I’ve found it to be &lt;em&gt;enormously&lt;/em&gt; effective.&lt;/p&gt;

&lt;p&gt;I’ve found myself to be often giving the advice of “write more” to people. One of my favorite past-times is helping people get new/better jobs, and a common thread throughout that process is “write something” or “write more”. But in the same breath as I recommend writing as a means to a better job, I underscore that writing has endless value beyond the fairly transactional purpose of demonstrating competence.&lt;/p&gt;

&lt;p&gt;This act (of pen to paper/fingers to keyboard) clarifies your thinking. On anything.&lt;/p&gt;

&lt;p&gt;I’ve been resisting writing because much of my attention is unwillingly drawn to things that frustrate me. (Please reference: politics, marketing). The internet certainly doesn’t need another screed about the injustices of {unjust thing}, and I don’t plan to add another one.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;I’m &lt;em&gt;trying&lt;/em&gt; to choose to spend my attention entirely within the zone of things I can control. I’m trying to reduce my area of awareness down to that which I can control. When my awareness expands far beyond that which I can control, I spend my day angry and frustrated.&lt;/p&gt;

&lt;p&gt;Me being angry and upset at things happening in a realm I cannot control (like politics) wears on those those around me. (Ask my wife about the last time I launched into a monologue about racist zoning policies.)&lt;/p&gt;

&lt;p&gt;The low-friction path in life seems to be outrage, loss of attention, and consumption. (Ads, commercials, billboards, clickbait articles, etc.)&lt;/p&gt;

&lt;p&gt;I don’t want to live &lt;em&gt;that&lt;/em&gt; way, though, so I have to go to great effort to reduce the friction I face in doing more valuable things. If I’m confronted with a choice, in some ways, I’ve already lost. I don’t want to have to make decisions about important and &lt;em&gt;good&lt;/em&gt; things. If they are really important and valuable, I’ll find a way to automate them, or fit them into a system.&lt;/p&gt;

&lt;p&gt;(This is why regular automatic deductions of money from a checking account to an investment account are so powerful. If it’s important, &lt;em&gt;automate it&lt;/em&gt;)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OK, I get it Josh. Why are you still going on and on about friction, then? Get to the point.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ah, great point, provocative voice inside my own head. Good point.&lt;/p&gt;

&lt;p&gt;I’m writing here about reducing friction… to get back in the groove of writing things I want to write about. Writing (and publishing) sometimes feels similar to replying to a long-neglected email in an inbox.&lt;/p&gt;

&lt;p&gt;&lt;img alt="I would be honored, but I know I don't belong in your network. The person you invited was someone who had not yet inflicted this two-year ordeal upon you. I'm no longer that person." src="https://imgs.xkcd.com/comics/email_reply.png" /&gt; &lt;em&gt;Image caption: “I would be honored, but I know I don’t belong in your network. The person you invited was someone who had not yet inflicted this two-year ordeal upon you. I’m no longer that person.”&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I think my these words have helped shepherd my brain towards my point:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I’ve recently spent great effort getting other people to think certain things about me. I was actively job hunting (but not anymore!) AND I was running for city council in Golden. I didn’t realize how much self-censure I was doing throughout that process, so I only wrote a little tiny bit, and at that, it was mostly technical posts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’m employed, and am not on Golden’s city council, so I can go back to treating these posts as a simple indulgence.&lt;/p&gt;

&lt;p&gt;Ahhh… that feels great.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Wed, 20 Dec 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/on-friction</guid></item><item><title>rust dependency hell with features</title><link>https://peterlyons.com/problog/2017/12/rust-dependency-hell-with-features/</link><description>&lt;p&gt;I've encountered my first bit of rust dependency hell. I'm trying to use a combination of nom v3.2.1 (a parsing combinator framework) plus nom_pem v1.0.3 (which uses nom to parse the PEM file format) plus der-parser v0.4.4 (which uses nom to parse DER data). This would almost work EXCEPT der-parser has the following line in it's &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nom = {version = "^3.1", features = ["verbose-errors"]}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I haven't used feature toggling at all yet, and my initial reaction is &lt;em&gt;OMG whose ideas was this and how did they think this would ever work?&lt;/em&gt;. In this case, the feature &lt;code&gt;verbose-errors&lt;/code&gt; enables a totally different and incompatible Error API in nom, so it's very likely this only works if all of your nom-based deps agree on whether to use or not use this feature. One out of line and it's a hung jury: your code doesn't compile.&lt;/p&gt;
&lt;p&gt;So at the moment my thought is: only top-level application projects should use cargo feature toggles and library crates should never use them. But as I read more maybe it'll get refined to something like "feature toggles are OK only within the bounds defined by the semver version, but if a feature toggle changes the semver API conventions, it's verboten."&lt;/p&gt;
&lt;p&gt;Off to read a bit more on this topic.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 20 Dec 2017 02:00:37 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/rust-dependency-hell-with-features/</guid></item><item><title>Books of 2017</title><link>https://bastibe.de/2017-12-20-books-of-2017.html</link><description>&lt;p&gt;In late 2016, I took a short ferry flight to a small island in the area, and rekindled my love for aviation. Shortly afterwards, I started training for a pilot's license, and reading about aviation. From a literary perspective, aviation exists in the perfect goldilocks time frame of being just old enough to be thoroughly romanticized, but young enough for first-hand reports and thorough documentation to be available. What is more, powered flight has provided human observers with an unprecedented view of our world and our struggles, and is often as philosophical as it is exhilarating.&lt;/p&gt;
&lt;h1&gt;Aviation Reading List&lt;/h1&gt;
&lt;p&gt;Out of a long list of fascinating books on aviation I have read over the last two years, my favorites are:&lt;/p&gt;
&lt;figure style="float: left;"&gt;
&lt;img src="https://images.gr-assets.com/books/1348443108l/533779.jpg" width="150px" /&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/533779.Fate_Is_the_Hunter"&gt;Fate is the Hunter&lt;/a&gt; by Ernest K. Gann, a gripping memoir of the early days of aviation. It has been only a little more than a hundred years since humans first took to the skies in Kitty Hawk in 1905, yet today aviation feels as mundane as horse-drawn carriages must have felt to the Wright Brothers. Gann lived through these early days, and tells his tales from a time when aviation was still young, dangerous, and perhaps more interesting. If you want to read more like this, &lt;a href="https://www.goodreads.com/book/show/400492.Flight_of_Passage"&gt;Flight of Passage&lt;/a&gt; by Rinker Buck, and &lt;a href="https://www.goodreads.com/book/show/571406.The_Spirit_of_St_Louis"&gt;The Spirit of St. Louis&lt;/a&gt; by Charles Lindbergh are easy recommendations as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure style="float: left;"&gt;
&lt;img src="https://images.gr-assets.com/books/1503014062l/36060428.jpg" width="150px" /&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/612456.Carrying_the_Fire"&gt;Carrying the Fire&lt;/a&gt; by Michael Collins, one of the few first-hand accounts of an Apollo astronaut's voyage to the Moon. Most astronauts have published books later on, but most had them ghost-written, and none are as visceral and engaging as Michael Collins' journey on Apollo 8. It is humbling that Apollo's achievements have not been surpassed, despite our much more advanced technology and science. Other accounts worth reading are &lt;a href="https://www.goodreads.com/book/show/271540.The_Last_Man_on_the_Moon"&gt;The Last Man on the Moon&lt;/a&gt; by Gene Cernan on Apollo 17, and &lt;a href="https://www.goodreads.com/book/show/2323178.How_Apollo_Flew_to_the_Moon?ac=1&amp;amp;from_search=true"&gt;How Apollo Flew to the Moon&lt;/a&gt; by W. David Woods, for a more technical view.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure style="float: left;"&gt;
&lt;img src="https://images.gr-assets.com/books/1458495570l/26210477.jpg" width="150px" /&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/22926778-skyfaring"&gt;Skyfaring&lt;/a&gt; by Mark Vanhoenacker is a more modern, and more philosophical account of how aviation has changed our perception of the world. If you yearn to fly like I do, then this book is a balm for the soul. The almost spiritual feeling of cutting your bonds with the ground is what this book is about, despite being written in today's un-romantic days of routine commercial airliners. I love it dearly. A more grounded account of aviation's history is &lt;a href="https://www.goodreads.com/book/show/1492469.Turbulent_Skies?from_search=true"&gt;Turbulent Skies&lt;/a&gt; by T. A. Heppenheimer, and maybe &lt;a href="https://www.goodreads.com/book/show/107298.Slide_Rule?from_search=true"&gt;Slide Rule&lt;/a&gt; by Nevil Chute for some history on airships.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;

&lt;h1&gt;Fiction Reading List&lt;/h1&gt;
&lt;p&gt;But as much as I love aviation, my first love is still Science Fiction. We live in strange times of unprecedented prosperity, and yet we are strangely unsatisfied, as if the future didn't turn out to be the utopia it was meant to be. Or is this just a reflection of ourselves, how we do not live up to the future we built?&lt;/p&gt;
&lt;figure style="float: left;"&gt;
&lt;img src="https://images.gr-assets.com/books/1457598923l/29475447.jpg" width="150px" /&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/series/170872-wayfarers"&gt;A Closed and Common Orbit&lt;/a&gt; by Becky Chambers describes a more distant future, when space travel is as mundane as airliners are today, and humanity is just one of several alien species. Yet, with all its technological marvels, we still yearn for meaning and love, regardless of what strange world we live in. A Closed and Common Orbit is the second book in the series, and the first book I read. I think I prefer it in this order.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure style="float: left;"&gt;
&lt;img src="https://images.gr-assets.com/books/1328341796l/8605343.jpg" width="150px" /&gt;
&lt;/figure&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/series/50764-laundry-files"&gt;The Laundry Files&lt;/a&gt; Series by Charles Stross is closer to home. Did you ever notice how computer programming is eerily similar to the arcane incantations we use to describe magic in fiction? Where is the difference between invoking a function that effects a robot, and invoking a magic spell that affects a demon? According to Charles Stross, this difference is really only playing with semantics, and we should be very careful with our incantations, lest the ghost in the machine really does have our demise in mind. These books have made me laugh out loud so many times, like when a weaponized PowerPoint turned people into zombies, or when a structured cabling project turned out to create an inadvertent summoning grid for an elder horror.&lt;/li&gt;
&lt;/ul&gt;</description><author>bastibe.de</author><pubDate>Wed, 20 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-12-20-books-of-2017.html</guid></item><item><title>Thoughts on Crypto Currency Mania</title><link>https://martinrue.com/thoughts-on-crypto-currency-mania/</link><description>It's the end of 2017 and right now there's a huge amount of interest in buying [insert any crypto currency coin here]. Everyone wants to buy everything, and as a result we're very much in a bull market at the moment.</description><author>Martin Rue</author><pubDate>Wed, 20 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://martinrue.com/thoughts-on-crypto-currency-mania/</guid></item><item><title>And Then There Were None</title><link>https://nindalf.com/posts/and-then-there-were-none/</link><description>A review of Agatha Christie's 'And Then There Were None' highlighting the absence of her typical detectives and the prevalence of casual racism in the 1930s.</description><author>Krishna's blog</author><pubDate>Wed, 20 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/and-then-there-were-none/</guid></item><item><title>Simply encrypt or decrypt a string using Boto3 Python and AWS KMS</title><link>https://boyter.org/2017/12/simply-encrypt-string-boto3-python-aws-kms/</link><description>&lt;p&gt;Another one of those things I need to look up every now and then. Below is a snippet of how to encrypt and decrypt a string using Python and KMS in AWS. The interesting thing is that you don&amp;rsquo;t need to supply the KMS key alias in the decryption portion. So long as whatever role or key you are using can access the key it should work. For the encryption you can either supply the full ARN of the key or the alias so long as you prefix it with alias/&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 18 Dec 2017 04:54:59 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/12/simply-encrypt-string-boto3-python-aws-kms/</guid></item><item><title>Celia Celia</title><link>https://ho.dges.online/words/commonplace/celia-celia-by-adrian-mitchell/</link><description>&lt;p&gt;When I am sad and weary&lt;br /&gt;
When I think all hope has gone&lt;br /&gt;
When I walk along High Holborn&lt;br /&gt;
I think of you with nothing on.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Adrian Mitchell&lt;/em&gt;&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Mon, 18 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/celia-celia-by-adrian-mitchell/</guid></item><item><title>Learnings from building my own home server</title><link>https://captnemo.in/blog/2017/12/18/home-server-learnings/</link><description>&lt;h2 id="learnings"&gt;Learnings&lt;/h2&gt;

&lt;p&gt;I forgot to do this on the last blog post, so here is the list:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;archlinux has official packages for &lt;a href="https://wiki.archlinux.org/index.php/Microcode"&gt;intel-microcode-updates&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;wireguard is almost there. I’m running openvpn for now, waiting for the stable release.&lt;/li&gt;
  &lt;li&gt;While &lt;a href="https://traefik.io/"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;traefik&lt;/code&gt;&lt;/a&gt; is great, I’m concerned about the security model it has for connecting to Docker (uses the docker unix socket over a docker mounted volume, which gives it root access on the host). Scary stuff.&lt;/li&gt;
  &lt;li&gt;Docker Labels are a great signalling mechanism. &lt;em&gt;Update&lt;/em&gt;: After seeing multiple bugs with how &lt;code class="language-plaintext highlighter-rouge"&gt;traefik&lt;/code&gt; uses docker labels, they have limited use-cases but work great in those. Don’t try to over-architect them for all your metadata.&lt;/li&gt;
  &lt;li&gt;Terraform still needs a lot of work on their docker provider. A lot of updates destroy containers, which should be applied without needing a destroy.&lt;/li&gt;
  &lt;li&gt;I can’t proxy gitea’s SSH authentication easily, since &lt;code class="language-plaintext highlighter-rouge"&gt;traefik&lt;/code&gt; doesn’t support TCP proxying yet.&lt;/li&gt;
  &lt;li&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;docker_volume&lt;/code&gt; resource in terraform is useless, since it doesn’t give you any control over the volume location on the host. (This might be a docker limitation.)&lt;/li&gt;
  &lt;li&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;upload&lt;/code&gt; block inside a &lt;code class="language-plaintext highlighter-rouge"&gt;docker_container&lt;/code&gt; resource is a great idea. Lets you push configuration straight inside a container. This is how I push configuration straight inside the &lt;code class="language-plaintext highlighter-rouge"&gt;traefik&lt;/code&gt; container for eg:
    &lt;div class="language-hcl highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${file("&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;path&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="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toml&lt;/span&gt;&lt;span class="s2"&gt;")}"&lt;/span&gt;
  &lt;span class="nx"&gt;file&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/etc/traefik/traefik.toml"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="advice"&gt;Advice&lt;/h2&gt;

&lt;p&gt;This section is if you’re venturing into a docker-heavy terraform setup:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use &lt;code class="language-plaintext highlighter-rouge"&gt;traefik&lt;/code&gt;. Will save you a lot of pain with proxying requests.&lt;/li&gt;
  &lt;li&gt;Repeat the &lt;code class="language-plaintext highlighter-rouge"&gt;ports&lt;/code&gt; section for every IP you want to listen on. CIDRs don’t work.&lt;/li&gt;
  &lt;li&gt;If you want to run the container on boot, you want the following:
    &lt;div class="language-ini highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="py"&gt;restart&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="s"&gt;"unless-stopped"&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="py"&gt;destroy_grace_seconds&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="s"&gt;10&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="py"&gt;must_run&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="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;If you have a single &lt;code class="language-plaintext highlighter-rouge"&gt;docker_registry_image&lt;/code&gt; resource in your state, you can’t run terraform without internet access.&lt;/li&gt;
  &lt;li&gt;Breaking your docker module into &lt;code class="language-plaintext highlighter-rouge"&gt;images.tf&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;volumes.tf&lt;/code&gt;, and &lt;code class="language-plaintext highlighter-rouge"&gt;data.tf&lt;/code&gt; (for registry_images) works quite well.&lt;/li&gt;
  &lt;li&gt;Memory limits on docker containers can be too contrained. Keep an eye on logs to see if anything is getting killed.&lt;/li&gt;
  &lt;li&gt;Setup Docker TLS auth &lt;em&gt;first&lt;/em&gt;. I tried proxying Docker over apache with basic auth, but it didn’t work out well.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="mongodb-with-forceful-server-restarts"&gt;MongoDB with forceful server restarts&lt;/h2&gt;

&lt;p&gt;Since my server gets a forceful restart every few days due to power-cuts (I’m still working on a backup power supply), I faced some issues with MongoDB being unable to recover cleanly. The lockfile would indicate a ungraceful shutdown, and it would require manual repairs, which sometimes failed.&lt;/p&gt;

&lt;p&gt;As a weird-hacky-fix, since most of the errors were from the MongoDB WiredTiger engine itself, I hypothesized that switching to a more robust engine might save me from these manual repairs. I switched to MongoRocks, and while it has stopped the issue with repairs, the wiki stil doesn’t like it, and I’m facing this issue: https://github.com/Requarks/wiki/issues/313&lt;/p&gt;

&lt;p&gt;However, I don’t have to repair the DB manually, which is a win.&lt;/p&gt;

&lt;h2 id="sshd-on-specific-interface"&gt;SSHD on specific Interface&lt;/h2&gt;

&lt;p&gt;My proxy server has the following&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;eth0 139.59.22.234
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And an associated Anchor IP for static IP usecases via Digital Ocean. (&lt;code class="language-plaintext highlighter-rouge"&gt;10.47.0.5&lt;/code&gt;, doesn’t show up in &lt;code class="language-plaintext highlighter-rouge"&gt;ifconfig&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;I wanted to run the following setup:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;eth0:22&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;sshd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Anchor-IP:22&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;simpleproxy&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;gitea:ssh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;where gitea is the git server hosting &lt;code class="language-plaintext highlighter-rouge"&gt;git.captnemo.in&lt;/code&gt;. This way:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I could SSH to the proxy server over 22&lt;/li&gt;
  &lt;li&gt;And directly SSH to the Gitea server over 22 using a different IP address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, &lt;code class="language-plaintext highlighter-rouge"&gt;sshd&lt;/code&gt; doesn’t allow you to listen on a specific interface, and since the &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; IP is non-static I can’t rely on it.&lt;/p&gt;

&lt;p&gt;As a result, I’ve resorted to just using 2 separate ports:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;22&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;simpleproxy&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;gitea:ssh&lt;/code&gt;
&lt;code class="language-plaintext highlighter-rouge"&gt;222&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;sshd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are some hacky ways around this by creating a new service that boots SSHD after network connectivity, but I thought this was much more stable.&lt;/p&gt;

&lt;h2 id="wikijs-public-pages"&gt;Wiki.js public pages&lt;/h2&gt;

&lt;p&gt;I’m using wiki.js setup at &lt;a href="https://wiki.bb8.fun"&gt;https://wiki.bb8.fun&lt;/a&gt;. A specific requirement I had was public pages, so that I could give links to people for specific resources that could be browser without a login.&lt;/p&gt;

&lt;p&gt;However, I wanted the default to be authenticated, and only certain pages to be public. The config for this was surprisingly simple:&lt;/p&gt;

&lt;h3 id="yaml-config"&gt;YAML config&lt;/h3&gt;

&lt;p&gt;You need to ensure that &lt;code class="language-plaintext highlighter-rouge"&gt;defaultReadAccess&lt;/code&gt; is false:&lt;/p&gt;

&lt;div class="language-yml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;defaultReadAccess&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="guest-access"&gt;Guest Access&lt;/h3&gt;

&lt;p&gt;The following configuration is set for the guest user:&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/img/wiki.js-guest-access.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Now any pages created under the &lt;code class="language-plaintext highlighter-rouge"&gt;/public&lt;/code&gt; directory are now browseable by anyone.&lt;/p&gt;

&lt;p&gt;Here is a sample page: &lt;a href="https://wiki.bb8.fun/public/nebula"&gt;https://wiki.bb8.fun/public/nebula&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="docker-ca-cert-authentication"&gt;Docker CA Cert Authentication&lt;/h2&gt;

&lt;p&gt;I wrote a script that goes with the docker TLS guide to help you setup TLS authentication&lt;/p&gt;



&lt;h2 id="openvpn-default-gateway-client-side-configuration"&gt;OpenVPN default gateway client side configuration&lt;/h2&gt;

&lt;p&gt;I’m running a OpenVPN configuration on my proxy server. Howver, I don’t always want to use my VPN as the default route, only when I’m in an untrusted network. I still however, want to be able to connect to the VPN and use it to connect to other clients.&lt;/p&gt;

&lt;p&gt;The solution is two-fold:&lt;/p&gt;

&lt;h3 id="server-side"&gt;Server Side&lt;/h3&gt;

&lt;p&gt;Make sure you &lt;em&gt;do not&lt;/em&gt; have the following in your OpenVPN &lt;code class="language-plaintext highlighter-rouge"&gt;server.conf&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;push "redirect-gateway def1 bypass-dhcp"&lt;/code&gt;&lt;/p&gt;

&lt;h3 id="client-side"&gt;Client Side&lt;/h3&gt;

&lt;p&gt;I created 2 copies of the VPN configuration files. Both of the them have identical config, except for this one line:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;redirect-gateway def1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If I connect to the VPN config using this configuration, all my traffic is forwarded over the VPN. If you’re using Arch Linux, this is as simple as creating 2 config files:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;/etc/openvpn/client/one.conf&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;/etc/openvpn/client/two.conf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And running &lt;code class="language-plaintext highlighter-rouge"&gt;systemctl start openvpn-client@one&lt;/code&gt;. I’ve enabled my non-defaut-route VPN service, so it automatically connects to on boot.&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;</description><author>Nemo's Home</author><pubDate>Mon, 18 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/12/18/home-server-learnings/</guid></item><item><title>Some thoughts about running a wiki</title><link>https://utf9k.net/blog/wiki-thoughts/</link><description>I ran a Wiki for a little while and here's what I learned</description><author>utf9k</author><pubDate>Sun, 17 Dec 2017 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/wiki-thoughts/</guid></item><item><title>Your first robot: A beginner's guide to ROS and Ubuntu Core [1/5]</title><link>https://kyrofa.com/posts/your-first-robot-a-beginner-s-guide-to-ros-and-ubuntu-core-1-5/</link><description>UPDATE: I&amp;rsquo;m leaving this series up for historical purposes, but please note that I no longer recommend Ubuntu Core or snaps for use in robotics.
Some time ago I created a blog/video series that walked the reader through creating a prototype using the Robot Operating System (ROS) and taking it to production using Ubuntu Core. However, that series was intended more for robotics professionals; it assumed quite a bit of ROS knowledge, and required some costly equipment (the robot was about $1k).</description><author>kyrofa's blog</author><pubDate>Sun, 17 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/your-first-robot-a-beginner-s-guide-to-ros-and-ubuntu-core-1-5/</guid></item><item><title>rust converting bytes chars and strings</title><link>https://peterlyons.com/problog/2017/12/rust-converting-bytes-chars-and-strings/</link><description>&lt;p&gt;I found converting from many representations of essentially the same data really inconsistent and hard to memorize in rust. I was doing a lot of work that frequently switched between text and binary and couldn't find a good quick reference cheat sheet, so I sat down to pair with &lt;a href="https://jaredmcdonald.github.io/"&gt;Jared McDonald&lt;/a&gt; at Recurse Center and code one up.&lt;/p&gt;
&lt;p&gt;Whether you've got some bytes, chars, Strings, strs, arrays, or vecs, we'll get you from A to B!&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;use std::str;

fn main() {
    &amp;#x2f;&amp;#x2f; This is &amp;quot;hello world&amp;quot; as an array of bytes.
    &amp;#x2f;&amp;#x2f; You can also start from a byte string b&amp;quot;hello world&amp;quot; and debug print that to get the
    &amp;#x2f;&amp;#x2f; utf8 encoded decimal values
    println!(&amp;quot;hello byte string: {:?}&amp;quot;, b&amp;quot;hello world&amp;quot;);

    &amp;#x2f;&amp;#x2f; OK so let&amp;#x27;s say you have an array of u8s
    let array_of_u8 = [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100];

    &amp;#x2f;&amp;#x2f; [u8] to String (lossy)
    &amp;#x2f;&amp;#x2f; Any invalid bytes that are not utf8 will be replaced with
    &amp;#x2f;&amp;#x2f; the unicode replacement character &amp;#x27;\u{FFFD}&amp;#x27;
    &amp;#x2f;&amp;#x2f; You get a Cow (Clone on Write) not exactly a String
    let string_utf8_lossy = String::from_utf8_lossy(&amp;amp;array_of_u8);
    println!(&amp;quot;string_utf8_lossy: {}&amp;quot;, string_utf8_lossy);

    &amp;#x2f;&amp;#x2f; [u8] to String (result)
    &amp;#x2f;&amp;#x2f; The non-lossy version needs a vec not an array
    let mut vec_of_u8 = vec![];
    vec_of_u8.extend_from_slice(&amp;amp;array_of_u8);
    let string_utf8_result = String::from_utf8(vec_of_u8).unwrap();
    println!(&amp;quot;string_utf8_result: {}&amp;quot;, string_utf8_result);

    &amp;#x2f;&amp;#x2f; [u8] to str (result)
    let str_utf8_result = str::from_utf8(&amp;amp;array_of_u8).unwrap();
    println!(&amp;quot;str_utf8_result: {}&amp;quot;, str_utf8_result);

    &amp;#x2f;&amp;#x2f; [u8] to str (lossy)
    &amp;#x2f;&amp;#x2f; There is no str::from_utf8_lossy. Have to use String::from_utf8_lossy

    &amp;#x2f;&amp;#x2f; [u8] to Vec&amp;lt;char&amp;gt;
    let vec_of_chars: Vec&amp;lt;char&amp;gt; = array_of_u8.iter().map(|byte| *byte as char).collect();
    println!(&amp;quot;vec_of_chars: {:?}&amp;quot;, vec_of_chars);

    &amp;#x2f;&amp;#x2f; Vec&amp;lt;char&amp;gt; to Vec&amp;lt;u8&amp;gt;
    let vec_of_u8s: Vec&amp;lt;u8&amp;gt; = vec_of_chars.iter().map(|c| *c as u8).collect();
    println!(&amp;quot;vec_of_u8s: {:?}&amp;quot;, vec_of_u8s);

    &amp;#x2f;&amp;#x2f; Vec&amp;lt;char&amp;gt; to String
    let mut string_of_collected_chars: String = vec_of_chars.iter().collect();
    println!(&amp;quot;string_of_collected_chars: {}&amp;quot;, string_of_collected_chars);

    &amp;#x2f;&amp;#x2f; Now we have a mutable String. We can push chars
    string_of_collected_chars.push(&amp;#x27;!&amp;#x27;);

    &amp;#x2f;&amp;#x2f; and we can push a str
    string_of_collected_chars.push_str(&amp;quot;!!&amp;quot;);

    &amp;#x2f;&amp;#x2f; String to str
    let str_slice = &amp;amp;string_of_collected_chars[..5];
    println!(&amp;quot;str_slice: {}&amp;quot;, &amp;amp;str_slice);

    &amp;#x2f;&amp;#x2f; String to [u8]
    let array_of_u8_from_string = string_of_collected_chars.as_bytes();
    println!(&amp;quot;array_of_u8_from_string: {:?}&amp;quot;, array_of_u8_from_string);

    &amp;#x2f;&amp;#x2f; String to Vec&amp;lt;char&amp;gt;
    let vec_of_chars_to_string: Vec&amp;lt;char&amp;gt; = string_of_collected_chars.chars().collect();
    println!(&amp;quot;vec_of_chars: {:?}&amp;quot;, vec_of_chars_to_string);

    &amp;#x2f;&amp;#x2f; String from several Strings
    let concat_strings = vec![&amp;quot;abc&amp;quot;.to_string(), &amp;quot;def&amp;quot;.to_string()].concat();
    println!(&amp;quot;concat_strings: {}&amp;quot;, concat_strings);
    let joined_strings = vec![&amp;quot;abc&amp;quot;.to_string(), &amp;quot;def&amp;quot;.to_string()].join(&amp;quot;---&amp;quot;);
    println!(&amp;quot;joined_strings: {}&amp;quot;, joined_strings);
}
&lt;/code&gt;&lt;/pre&gt;</description><author>Pete's Points</author><pubDate>Sat, 16 Dec 2017 20:57:12 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/rust-converting-bytes-chars-and-strings/</guid></item><item><title>Magit amend commit author</title><link>https://xenodium.com/magit-amend-commit-author</link><description>&lt;p&gt;Rarely use it, but handy. Use Magit to amend git commit author.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rebase interactively (r, i).&lt;/li&gt;
&lt;li&gt;Move point to commit to ammend.&lt;/li&gt;
&lt;li&gt;Execute command (x).&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;git commit --amend --author=&amp;quot;name &amp;lt;email&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Commit (c, c).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/amend-git-commit-author-on-magit/amending.gif" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 16 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/magit-amend-commit-author</guid></item><item><title>Get scrollbar width in JavaScript</title><link>https://muffinman.io/blog/get-scrollbar-width-in-javascript/</link><description>&lt;article class="article"&gt;&lt;p&gt;Another one-liner I love, that returns body scrollbar width.
If scrollbar is not shown it will return zero (including mobile devices).&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;getScrollbarWidth&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token dom variable"&gt;window&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;innerWidth&lt;/span&gt; &lt;span class="token operator"&gt;-&lt;/span&gt; &lt;span class="token dom variable"&gt;document&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;documentElement&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;clientWidth&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Click on the button to try it yourself:&lt;/p&gt;
&lt;div&gt;&lt;button class="btn btn--sm btn--demo"&gt;Get scrollbar width!&lt;/button&gt;&lt;/div&gt;
&lt;h2 id="browser-support"&gt;Browser support &lt;a class="anchor-link" href="#browser-support"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tested on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows: IE9, IE10, IE11, Edge&lt;/li&gt;
&lt;li&gt;MacOS: Safari, Firefox, Chrome, Opera&lt;/li&gt;
&lt;li&gt;iOS: Safari, Chrome&lt;/li&gt;
&lt;li&gt;Android: Chrome&lt;/li&gt;
&lt;/ul&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 15 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/get-scrollbar-width-in-javascript/</guid></item><item><title>Homebrew install from cache</title><link>https://xenodium.com/homebrew-install-from-cache</link><description>&lt;p&gt;Came across a 404 while installing graphviz-2.40.1.tar.gz via homebrew. If you can find the package elsewhere, copy over to homebrew's cache directory.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew --cache
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 13 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/homebrew-install-from-cache</guid></item><item><title>Recurse Center 23: SQL window functions</title><link>https://peterlyons.com/problog/2017/12/recurse-center-23-sql-window-functions/</link><description>&lt;p&gt;Today was the first day where I focused primarily on my SQL project, which was my second priority overall. I did most of the pgexercises on aggregation. There were quite a few of them and by the end they were really challenging. I learned bit about common table expressions which seem awesome and windowing functions which seem great for the business rollup type reports which are otherwise frustrating in regular SQL. I met with the study group today and we lamented the lack of good material that actually teaches this stuff clearly. We are looking at 3-4 books to potentially select.&lt;/p&gt;
&lt;p&gt;I managed to get into code flow this afternoon on tealeaves and I expanded my arsenal of test key files to include the special &lt;code&gt;-o&lt;/code&gt; openssh-key-v1 format for the rsa, dsa, and ecdsa algorithms. ed25519 keys always use this format, but the other algorithms can be saved in 2 formats, this one or ASN.1.&lt;/p&gt;
&lt;p&gt;The good news is that some of my nom code to parse this format in the public key code can be re-used for private key code as well. I'm excited to refactor to that tomorrow.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 13 Dec 2017 01:01:30 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-23-sql-window-functions/</guid></item><item><title>How to resolve 'X defined in resolvers, but not in schema' with babel-plugin-inline-import</title><link>https://maxrozen.com/inline-import-graphql-issues</link><description>Showing how to resolve the dreaded 'Query.X defined in resolvers, but not in schema' issue when your X is **definitely** defined in both</description><author>Max Rozen</author><pubDate>Tue, 12 Dec 2017 20:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/inline-import-graphql-issues</guid></item><item><title>Recurse Center 22: tealeaves refactored</title><link>https://peterlyons.com/problog/2017/12/recurse-center-22-tealeaves-refactored/</link><description>&lt;p&gt;Today I finished a big push of work on tealeaves and got the code fully cleaned up and merged to master and all the tests passing again. When I introduced &lt;code&gt;nom_pem&lt;/code&gt; last week things destabilized and it took a while to shake all that out. I'm about ready to start adding some linter style rules like making sure the filesystem permissions on your private keys are restrictive.&lt;/p&gt;
&lt;p&gt;I also worked a bit more on pgexercises this afternoon but they really are just exercises with nothing to actually teach you the SQL you need, so I switched back to some Khan Academy tutorials I had worked on about 2 years ago.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Tue, 12 Dec 2017 03:17:07 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-22-tealeaves-refactored/</guid></item><item><title>Few things I learned as an engineer at Twitter</title><link>http://dimitarsimeonov.com/2017/12/12/few-things-i-learned-as-an-engineer-at-twitter</link><description>&lt;p&gt;A month ago I left a job as a software engineer and data scientist at
Twitter.&lt;/p&gt;

&lt;p&gt;I was there 4.4 years and I learned a great deal out of it. I not only
got significantly better at the job-description part of my job -
contributing to code and data analysis - but I also picked up a few
bits about what makes larger efforts and collaboration successful.&lt;/p&gt;

&lt;p&gt;So… without pretense of completeness or correctness, and without
further ado, here is a sample of things I learned.&lt;/p&gt;

&lt;h1 id="its-better-to-get-a-relatively-smaller-win-now-than-a-larger-one"&gt;It’s better to get a relatively smaller win now, than a larger one&lt;/h1&gt;

&lt;p&gt;later.&lt;/p&gt;

&lt;p&gt;Shipping a successful feature brings more resources and people towards
your project and will actually accelerate the larger, future win. Work
is like a Hydra. Kill one head “successfully” and three more will grow
out of it. You’ll have more work to do. When a project is done
successfully, that usually opens up other possibilities, on top if
it. It also brings momentum to that work stream. Exciting people like
to join exciting projects, and successful projects are more exciting.&lt;/p&gt;

&lt;p&gt;I was on the Timelines team when we were moving from reverse-chron
timeline to a ranked one. This project was successful and helped our
team grow, and attracted awesome people to join the team. Shipping a
win made the team better and able to ship further wins faster. If we
were to wait until we’ve done some of the follow up work, it would
have taken a lot longer to get it done without the new team
members. MVPs rule.&lt;/p&gt;

&lt;h1 id="working-together-is-not-a-zero-sum-game"&gt;Working together is not a zero-sum game.&lt;/h1&gt;

&lt;p&gt;We mutually help each other, but it’s counter-productive to keep score
of how much each person has contributed. Keep helping and supporting
others and it will pay back, in unpredictable ways.&lt;/p&gt;

&lt;p&gt;Most times I’ve taken time to help with other’s brainstorm, or work
through some issue with them, or pay extra effort in code reviews and
design reviews, I’ve felt an increase in comradeship from the other
person, and I’ve received more unsolicited help and advice from them
in the future. Not only this helped us do better work, it made it more
of a pleasure. Teamwork matters. Can’t do it alone. Teams will beat
geniuses about 99.99% of the time in the short term, and 100% in the
long term.  What we’ve been able to accomplish as a team is a lot more
than what each of us can do by themselves.&lt;/p&gt;

&lt;p&gt;In a typical project there are just too many details to get right for
a single person. Even for the smallest code changes, we do code
reviews and having a different person with a detached perspective on
the problem take a look often finds ways to improve it. This is even
more apparent when there’s a larger project which requires different
roles. No matter how smart I may think I am, it is pretty clear that
some aspects I’d never think about, even if given unlimited time.&lt;/p&gt;

&lt;p&gt;Collaboration amplifies. Or if you like TPS reports, you might want to
call it synergy :)&lt;/p&gt;

&lt;h1 id="doing-a-lot-of-code-reviews-for-others-the-fastest-ways-to-learn"&gt;Doing a lot of code reviews for others the fastest ways to learn&lt;/h1&gt;

&lt;p&gt;It helps to keep up with what all the teammates are doing, builds up
karma, and is the best way to discover the code patterns to use. It
also gets a lot easier to do with time - economies of scale.&lt;/p&gt;

&lt;p&gt;As a relatively junior engineer to begin with, there were a lot of
systems and patterns that I didn’t know and understand. Doing a lot of
code reviews for my more senior teammates showed me the way they write
code, the considerations they make and helped me learn about the
different systems we were using as a team. There were times during
which I tried to review almost all code by teammates. This really
helped me keep up with what each of them is doing, and gave me enough
context so I can provide more adequate and specific suggestions. It
also made it easier to write my code which interacted, or built upon
their code, which increased my productivity - at least measured
quantitatively. I believe there was a qualitative increase as well, as
code reviews enhance collaboration, and not merely cooperation.&lt;/p&gt;

&lt;p&gt;If you are a junior engineer, or new to a team or company - doing a
lot of code reviews is the hands down best way to get better. It’s
also my favorite example of collaboration done right.&lt;/p&gt;

&lt;h1 id="make-bigdata-small"&gt;Make BigData small.&lt;/h1&gt;

&lt;p&gt;When analyzing large amounts of data, it’s important to aggregate and
summarize as much as possible. As much as we don’t like to admit it,
we as humans are not good at pattern recognition. We can recognize
straight lines, and some high level features, but that’s about it.&lt;/p&gt;

&lt;p&gt;Often, I had to analyze terabytes of data. I had Scalding, Hadoop and
MapReduce as tools, but still, I had to find ways to summarize that
data to only a handfull of dimensions and metrics and create plots for
those, that make sense for humans. For data-mining it was a two-stage
process. First, create a small dimensions and metrics dataset that
would fit in memory or in database. Then, it’s a lot easier to mine
this smaller dataset for insights, than having to go back to
Hadoop. Each iteration and new idea takes seconds, not hours to
investigate.&lt;/p&gt;

&lt;p&gt;I really like the way Tableau approaches it, by explicitly calling out
“Dimensions” and “Metrics” for the small data table. Dimensions are
how you can slice and dice the data, and metrics are statistics for
each possible slice. To anyone new to data mining, this would be my
first advice.&lt;/p&gt;

&lt;h1 id="visualization-matters"&gt;Visualization matters.&lt;/h1&gt;

&lt;p&gt;How we communicate our findings is as important, and as hard to get
right as deriving the findings in first place. The most common bias,
myself included, is to overestimate the importance of the findings,
and underestimate the importance of the communication.&lt;/p&gt;

&lt;p&gt;I took a one-day course by Edward Tufte on how to present quantitative
data and it was well worth it. It taught me how it is important to
show comparisons, causality, proper documentation, and not to
underestimate the communicative power of text labels. Text labels
rule. I’ve learned the hard way that it takes just as much work to
communicate a finding effectively, than to do the work for the
finding. Sometimes even many times more.&lt;/p&gt;

&lt;h1 id="if-something-it-isnt-tested-it-will-break"&gt;If something it isn’t tested, it WILL break.&lt;/h1&gt;

&lt;p&gt;If it’s tested, it might still break. This so far has been true 100%
of the time.&lt;/p&gt;

&lt;p&gt;Unit tests have saved my butt many times. I don’t know if anyone can
write bug-free code, but almost every time I’ve written unit tests
I’ve caught bugs and code design issues. I learned to associate
writing tests with finding bugs so much that I do it all the time, and
avoid giving a “Shipit!” to other people’s code if they don’t have
tests.&lt;/p&gt;

&lt;p&gt;One vivid example is from the day of launching the ranked timeline. We
had to make some last day changes the day before, which came from high
level. It was also impossible to push the launch date further until
we’ve done more testing, due to press commitments. We had added new
code, and added a whole bunch of unit tests for it. But we forgot to
unit test one case and that did break during the launch. I felt
embarrassed. Exceptions in production, and delaying the launch by a
few hours. At time though, we were not panicked and calmly proceeded
to write some more unit tests to reproduce the issue, as to be certain
when it’s fixed. Our manager read the situation correctly and tried to
give us the calm and isolation so we can focus on the issue. He
offered to bring us coffee.&lt;/p&gt;

&lt;h1 id="clean-data-models-are-worth-the-investment"&gt;Clean data models are worth the investment.&lt;/h1&gt;

&lt;p&gt;It’s worth the time to make sure data model and structs are right for
the case, and have clear semantics. If you are clobbering and reusing
fields that will cost you more in the future.&lt;/p&gt;

&lt;p&gt;Me and my teammates were working with a result structure representing
tweets. A field in the structure was used for multiple purposes, which
were most likely mutually exclusive at the time the data structure was
designed. Or maybe it was designed with only one case in mind and the
other one sneaked in there, in the same field, as it is a PITA to
update data format once live. Anyhow, all was rainbow and sunshines,
except not. There was a bunch of work required to parse out the
different cases into a less ambiguous format, and everything broke
when we were migrating, rebuilding one of the services and a different
person had to re-do the parsing in a different language, and the
quirks of the fields were only documented in some old JIRA tickets.&lt;/p&gt;

&lt;p&gt;We spent much more time working around a clumsy data format that would
have been necessary to do it right the first time. We also had tricky
to fix production bugs that remained undiagnosed for a while. This
kind of tech debt comes with a steep interest rate and unpleasant
payment schedule.&lt;/p&gt;

&lt;h1 id="names-stick"&gt;Names stick.&lt;/h1&gt;

&lt;p&gt;My professor in college used to say that naming is very powerful. He’s
so right. So when coming up with a name for some feature or behavior,
find a good one. Chances are, that everyone will start using the name
and it will be impossible to change later.&lt;/p&gt;

&lt;p&gt;I’ve had my fun of observing that process in vivo, when I started
using the term “headless reply” for one of my project, and in the
following months I started hearing it in other contexts and other
projects. Perhaps I didn’t coin that term, but sure enough I hadn’t
heard it before. I’ve seen other suboptimal terms start to get used so
much that it just becomes impossible to start calling them something
else.&lt;/p&gt;

&lt;p&gt;Except in very rare cases, names don’t change. Once they’re in
people’s minds you can’t press Fn+F6 and do a “Refactor -&amp;gt; Rename” on
them in IntelliJ.&lt;/p&gt;

&lt;h1 id="every-metric-will-become-a-vanity-metric"&gt;Every metric will become a vanity metric.&lt;/h1&gt;

&lt;p&gt;Monthly active users, User active minutes, etc. These usually are
great to optimize in some cases, but will stop being what correlates
well with user satisfaction and product health in the medium-long
term.&lt;/p&gt;

&lt;p&gt;Of course, it’s a lot easier to see when &lt;em&gt;other&lt;/em&gt; teams are over
optimizing a given metric. It’s a lot harder to be self-critical. Over
the long term, the product built is the best fit to the targeted
metrics. Oh. Key. Ars. If these metrics don’t evolve, the product will
overfit.&lt;/p&gt;

&lt;h1 id="estimate-time-generously-and-then-pad-it-some-more"&gt;Estimate time generously. And then pad it some more.&lt;/h1&gt;

&lt;p&gt;Work will always take longer than you thought, even when you adjust
for that. Nobody will complain if you get it done sooner,
instead. There’s a very asymmetrical cost reward to any engineer to
whether their estimate is too long, or too short.&lt;/p&gt;

&lt;p&gt;When I’ve been asked to estimate how long it will take me to do a
certain work, I’ve always had the inclination to imagine the steps of
the work and imagine how long they’ll take. But this doesn’t account
for meetings, off-sites, missed edge cases, time spent helping other
team-mates, and other delays beyond my control. And also…&lt;/p&gt;

&lt;h1 id="after-the-first-90-of-each-project-its-time-for-the-other-90"&gt;After the first 90% of each project, it’s time for the other 90%.&lt;/h1&gt;

&lt;p&gt;For example, if building product, no matter how hard you think about
it there will always be edge cases which users are doing, that are
broken and need further work.&lt;/p&gt;

&lt;p&gt;We’ve always, always found issues when dogfooding new features, and
many times we’ve had to iterated in A/B tests. Every rare, or weird,
use pattern will happen in very small percentage of the time. But
that’s still too many times when the product is used by hundreds of
millions of users every day. The question I learned to ask myself is
not whether any unexpected behaviour would happen, the question is
what will the code do when it inevitably happens.&lt;/p&gt;

&lt;h1 id="volunteer-for-more-projects-than-you-can-do"&gt;Volunteer for more projects than you can do.&lt;/h1&gt;

&lt;p&gt;It’s better to drop a less important, and less exciting project than
to be stuck on it as the only project.&lt;/p&gt;

&lt;p&gt;I think this tends to work because more important projects are usually
more exciting. It becomes possible to communicate the benefits of the
more important and exciting project to the manager and convince them
that you should focus more on it, and not the less important one.&lt;/p&gt;</description><author>D13V</author><pubDate>Tue, 12 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/12/12/few-things-i-learned-as-an-engineer-at-twitter</guid></item><item><title>2017 Notre Dame CSE 20133/20232 Final Project Presentations</title><link>https://cscrunch.com/blog/corey-pennycuff/2017-notre-dame-cse-2013320232-final-project-presentations</link><description>&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
&lt;a href="https://www.youtube.com/playlist?list=PLZqirAnnqaCbZ4te10ELYRK1GH1mMdVBJ"&gt;Here&lt;/a&gt; are a few videos that were created by the students of the 2017 CSE 20133/20232 programming class, to demonstrate their end-of-semester projects.  This class consisted of EE and other non-CS engineering students, and taught programming using C and C++.&lt;/p&gt;
&lt;p&gt;Videos included here are done with the permission of the students, and I will add additional videos to the playlist if and when more students decide to make their project videos public.&lt;/p&gt;
&lt;p&gt;I am very proud of what the students accomplished, and with the variety of ideas and inginuity of the students.  They all did great!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;section class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above view-mode-rss"&gt;&lt;h2 class="field-label"&gt;Tags:&amp;nbsp;&lt;/h2&gt;&lt;ul class="field-items"&gt;&lt;li class="field-item even"&gt;&lt;a href="https://cscrunch.com/tags/cc"&gt;C/C++&lt;/a&gt;&lt;/li&gt;&lt;li class="field-item odd"&gt;&lt;a href="https://cscrunch.com/tags/notre-dame"&gt;Notre Dame&lt;/a&gt;&lt;/li&gt;&lt;li class="field-item even"&gt;&lt;a href="https://cscrunch.com/tags/project-presentations"&gt;Project Presentations&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/section&gt;</description><author>CS Crunch</author><pubDate>Mon, 11 Dec 2017 21:45:09 GMT</pubDate><guid isPermaLink="true">https://cscrunch.com/blog/corey-pennycuff/2017-notre-dame-cse-2013320232-final-project-presentations</guid></item><item><title>How to style react-select with styled-components or emotion</title><link>https://maxrozen.com/style-react-select-styled-components-emotion</link><description>Styling react-select can be annoying. Here's a quick guide on how to do it with popular CSS-in-JS libraries.</description><author>Max Rozen</author><pubDate>Mon, 11 Dec 2017 20:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/style-react-select-styled-components-emotion</guid></item><item><title>Should I buy Bitcoin?</title><link>https://nindalf.com/posts/should-i-buy-bitcoin/</link><description>This article explores the question of whether or not to invest in Bitcoin, examining its value as a currency and asset, as well as its potential for future growth and stability.</description><author>Krishna's blog</author><pubDate>Mon, 11 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/should-i-buy-bitcoin/</guid></item><item><title>The Mathematics of 2048: Counting States by Exhaustive Enumeration</title><link>http://jdlm.info/articles/2017/12/10/counting-states-enumeration-2048.html</link><description>&lt;p&gt;&lt;strong&gt;Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2017-12-11&lt;/strong&gt; This post was &lt;a href="https://news.ycombinator.com/item?id=15894126"&gt;discussed on Hacker News&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is the third in a series. Next: &lt;a href="/articles/2018/03/18/markov-decision-process-2048.html"&gt;Optimal Play with Markov Decision Processes&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot of 2048 with an improbable but reachable board configuration" src="/assets/2048/2048_improbable.png" style="width: 40%; float: right; margin-left: 10pt; border: 6pt solid #eee;" /&gt;&lt;/p&gt;

&lt;p&gt;So far in this series on the mathematics of &lt;a href="http://gabrielecirulli.github.io/2048"&gt;2048&lt;/a&gt;, we’ve seen that &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;it takes at least 938.8 moves&lt;/a&gt; on average to win, and we’ve &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html"&gt;obtained some rough estimates&lt;/a&gt; on the number of possible states using combinatorics.&lt;/p&gt;

&lt;p&gt;In this post, we will try to refine those estimates by simply counting every reachable state by brute force enumeration. There are many states, so this will require some computer science as well as mathematics. With efficient processing and storage of states, we’ll see that it is possible to enumerate all reachable states for 2x2 and 3x3 boards.&lt;/p&gt;

&lt;p&gt;Enumeration of all states for the full game on a 4x4 board remains an open problem. I ran the code on an OVH HG-120 instance with 32 cores at 3.1GHz and 120GB RAM for one month, during which it enumerated 1.3 trillion states, which is a respectable half a million states per second, but that turns out to be nowhere near enough. At present, the best we we’ll be able to do on the 4x4 board is to enumerate all states for the game played up to the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;Overall, the results show that the combinatorial estimates from the last post were substantial overestimates, as suspected. However, the state space for the full game is still very large. If a large nation state or tech company decided that 2048 was their top priority, which may not be the craziest thing that’s happened this year, I think they could probably finish the job.&lt;/p&gt;

&lt;p&gt;The (research quality) code behind this article is &lt;a href="https://github.com/jdleesmiller/twenty48#3-number-of-states-by-exhaustive-enumeration"&gt;open source&lt;/a&gt;, mainly in ruby and C++.&lt;/p&gt;

&lt;h1 id="counting-states"&gt;Counting States&lt;/h1&gt;

&lt;p&gt;Here a &lt;em&gt;state&lt;/em&gt; captures a complete configuration of the board by specifying the value of the tile, if any, in each of the board’s cells. Our overall goal is to count all of the states that can actually occur in the game and no more. In the previous post, the estimates from (very basic) combinatorics counted many states that can’t actually occur in the game. By enumerating states systematically from each of the possible start states, we ensure that the states we count are actually reachable in play.&lt;/p&gt;

&lt;p&gt;We also have some freedom in choosing which states are interesting enough to count. Because the game ends when we obtain a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile, we won’t care about where that tile is or what else is on the board, so we can condense all of the states with a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile into a special “win” state. Similarly, if we lose, we won’t care exactly how we lost; we can condense all of losing states into a special “lose” state.&lt;/p&gt;

&lt;h1 id="canonicalization-and-symmetry"&gt;Canonicalization and Symmetry&lt;/h1&gt;

&lt;p&gt;Many other non-interesting states that we’d like to avoid counting arise from the fact that some states are trivially related to each other by rotation or reflection. For example, in the game on a 2x2 board, the states&lt;/p&gt;
&lt;p align="center"&gt;
  &lt;img alt="4 8 2 -" src="/assets/2048/2x2_s2_3_1_0.svg" /&gt;
  and
  &lt;img alt="8 4 - 2" src="/assets/2048/2x2_s3_2_0_1.svg" /&gt;
&lt;/p&gt;
&lt;p&gt;are just mirror images — they are reflections through the vertical axis. If we swiped left in the first state, it would be essentially equivalent to swiping right in the second. We can therefore reduce the number of states we have to worry about by treating these states as equivalent. In general, the number of such equivalent states is the number of elements in the &lt;a href="https://en.wikipedia.org/wiki/Dihedral_group"&gt;dihedral group&lt;/a&gt; for the square, \(D_4\), which is 8. For the first state above, these eight states are:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img alt="Eight states with the same canonical state as 4 8 2 -" src="/assets/2048/2x2_canonical.svg" /&gt;&lt;/p&gt;
&lt;p&gt;In this diagram, which is called a cycle graph, ⤴ denotes a rotation counterclockwise by 90° and ↔ denotes a reflection about the vertical axis. The three states at the top are obtained by one or more rotations; for example, ⤴² means two rotations of 90°, which add up to a rotation of 180°. The four states at the bottom are obtained by zero or more rotations followed by a reflection.&lt;/p&gt;

&lt;p&gt;When the tiles in a state are arranged in a symmetrical pattern, the number of equivalent states may be less than 8, because the symmetry means that some of the states in the above diagram will be identical. For example, the state &lt;img src="/assets/2048/2x2_s2_1_1_0.svg" style="height: 2em;" /&gt; has only four, because it is symmetric along the diagonal. However, particularly on 3x3 and 4x4 boards, states with symmetric arrangements of tiles are not so common, so overall we can expect to reduce the number of states we need to count by roughly a factor of 8 by choosing only one of these equivalent states as the &lt;em&gt;canonical&lt;/em&gt; state.&lt;/p&gt;

&lt;h1 id="states-as-numbers"&gt;States as Numbers&lt;/h1&gt;

&lt;p&gt;Which of the equivalent states should we choose as the canonical state? To answer this question, it will be helpful to think about states as numbers. We’ll also see that this has significant computational benefits in the appendices.&lt;/p&gt;

&lt;p&gt;To write a state as a number, we can start in the top left and read the cells by rows; for each cell, we write a \(0\) digit if the cell is empty, and the digit \(i\) if the cell contains the \(2^i\) tile. For example, on a 2x2 board, the state &lt;img alt="4 8 2 -" src="/assets/2048/2x2_s2_3_1_0.svg" style="height: 2em;" /&gt;
would be written as the number \(2310\), because \(4 = 2^2\), \(8 = 2^3\), \(2 = 2^1\), and the last cell is empty.&lt;/p&gt;

&lt;p&gt;Since we’re only interested in numbers up to 2048, which is \(2^{11}\), we could in principle write any state as a number in base 12 (rather than base 10, as we are accustomed to). However, because computers run on binary numbers, it will be more convenient to think of each state as a number in base 16 — that is, hexadecimal. The state above would therefore be more properly written as &lt;code class="language-plaintext highlighter-rouge"&gt;0x2310&lt;/code&gt; for computer scientists or \(2310_{16}\) for mathematicians.&lt;/p&gt;

&lt;p&gt;To find the canonical state, we simply try all eight possible rotations and reflections, convert the resulting states to numbers, and then pick the smallest one. For our example state, &lt;img alt="4 8 2 -" src="/assets/2048/2x2_s2_3_1_0.svg" style="height: 2em;" /&gt;, the candidates and their corresponding numbers are:&lt;/p&gt;

&lt;table style="width: 1%; margin: 0px auto;"&gt;
&lt;thead&gt;&lt;tr&gt;&lt;th&gt;State&lt;/th&gt;&lt;th&gt;Number&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="4 8 2 -" src="/assets/2048/2x2_s2_3_1_0.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x2310&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="8 4 - 2" src="/assets/2048/2x2_s3_2_0_1.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x3201&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="2 - 4 8" src="/assets/2048/2x2_s1_0_2_3.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x1023&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="4 2 8 -" src="/assets/2048/2x2_s2_1_3_0.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x2130&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="- 8 2 4" src="/assets/2048/2x2_s0_3_1_2.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x0312&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="2 4 - 8" src="/assets/2048/2x2_s1_2_0_3.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x1203&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="- 2 8 4" src="/assets/2048/2x2_s0_1_3_2.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;0x0132&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img alt="8 - 4 2" src="/assets/2048/2x2_s3_0_2_1.svg" style="height: 2em;" /&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x3021&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The state &lt;img alt="- 2 8 4" src="/assets/2048/2x2_s0_1_3_2.svg" style="height: 2em;" /&gt; has the smallest number, &lt;code class="language-plaintext highlighter-rouge"&gt;0x0132&lt;/code&gt;, so that is the canonical state for &lt;img alt="4 8 2 -" src="/assets/2048/2x2_s2_3_1_0.svg" style="height: 2em;" /&gt;. In general, this system for choosing canonical states tends to put tiles with larger values toward the bottom right corner.&lt;/p&gt;

&lt;h1 id="enumeration"&gt;Enumeration&lt;/h1&gt;

&lt;p&gt;Now we’re ready to start enumerating states — it’s all computation from now on. The idea is to generate all possible (canonical) start states, then for each one try each possible move, then for each move generate all possible (canonical) successor states. In code (ruby) form, the basic algorithm for enumerating states looks like this:&lt;/p&gt;

&lt;div class="language-rb highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;board_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_exponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# Open all of the possible canonicalized start states.&lt;/span&gt;
  &lt;span class="n"&gt;opened&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_canonicalized_start_states&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;board_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;closed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;opened&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any?&lt;/span&gt;
    &lt;span class="c1"&gt;# Treat opened as a stack, so this is a depth-first search.&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opened&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;

    &lt;span class="c1"&gt;# If we've already processed the state, or if this is&lt;/span&gt;
    &lt;span class="c1"&gt;# a win or lose state, there's nothing more to do for it.&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;member?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;win?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_exponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lose?&lt;/span&gt;

    &lt;span class="c1"&gt;# Process the state: open all of its possible canonicalized successors.&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:down&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;random_successors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;successor&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;opened&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;successor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;canonicalize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;closed&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code for generating start states is &lt;a href="https://github.com/jdleesmiller/twenty48/blob/479f646e81c38f1967e4fc5942617f9650d2c735/lib/twenty48/builder.rb#L59-L68"&gt;here&lt;/a&gt;, and the code for the rest of the State methods, such as &lt;code class="language-plaintext highlighter-rouge"&gt;random_successors&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;canonicalize&lt;/code&gt;, is &lt;a href="https://github.com/jdleesmiller/twenty48/blob/479f646e81c38f1967e4fc5942617f9650d2c735/lib/twenty48/state.rb"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If we run this code for the game on the 2x2 board played up to the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile, which we’ve &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html#fnref:smallest-board"&gt;previously established&lt;/a&gt; is the highest tile reachable on the 2x2 board, we get 57 states (&lt;a href="/assets/2048/enumeration_2x2_ungrouped.svg"&gt;click to enlarge&lt;/a&gt;):&lt;/p&gt;
&lt;p align="center"&gt;
  &lt;a href="/assets/2048/enumeration_2x2_ungrouped.svg"&gt;&lt;img alt="States from the enumeration of the 2x2 game to 32" src="/assets/2048/enumeration_2x2_ungrouped.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;In this diagram, each edge is a possible state-successor pair. For example, from the state &lt;img alt="- - 2 2" src="/assets/2048/2x2_s0_0_1_1.svg" style="height: 2em;" /&gt;, we could swipe left or right, which would result in a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile, and then the game adds a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile at random, which leads to
&lt;img alt="- 2 4 -" src="/assets/2048/2x2_s0_1_2_0.svg" style="height: 2em;" /&gt;,
&lt;img alt="- - 2 4" src="/assets/2048/2x2_s0_0_1_2.svg" style="height: 2em;" /&gt;,
&lt;img alt="- 4 4 -" src="/assets/2048/2x2_s0_2_2_0.svg" style="height: 2em;" /&gt; or
&lt;img alt="- - 4 4" src="/assets/2048/2x2_s0_0_2_2.svg" style="height: 2em;" /&gt; after canonicalization;
or we could swipe up or down, which would leave the two &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles unmerged and lead to
&lt;img alt="- 2 2 2" src="/assets/2048/2x2_s0_1_1_1.svg" style="height: 2em;" /&gt; or
&lt;img alt="- 2 4 2" src="/assets/2048/2x2_s0_1_2_1.svg" style="height: 2em;" /&gt; after canonicalization.&lt;/p&gt;

&lt;p&gt;Not shown are the special ‘lose’ and ‘win’ states, so in total we have 59 states for the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile. This compares favorably to the estimate of 529 states from the (simple) combinatorics arguments in the previous blog post. We’ve saved about one order of magnitude!&lt;/p&gt;

&lt;p&gt;When we try to run this ruby code on the 3x3 or 4x4 boards, however, we quickly hit two problems: it’s very slow, and it runs out of memory for the &lt;code class="language-plaintext highlighter-rouge"&gt;closed&lt;/code&gt; set. I’ve included three appendices with the details of how to speed up the calculations and manage the large amounts of data involved, but first let’s see some results.&lt;/p&gt;

&lt;h1 id="results"&gt;Results&lt;/h1&gt;

&lt;p&gt;The numbers of states for the various games we’ve looked at in this series of blog posts are:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Board Size&lt;/th&gt;
      &lt;th&gt;Maximum Tile&lt;/th&gt;
      &lt;th&gt;Combinatorics Bound&lt;/th&gt;
      &lt;th&gt;Actual&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;2x2&lt;/th&gt;
      &lt;th&gt;32&lt;/th&gt;
      &lt;td align="right"&gt;529&lt;/td&gt;
      &lt;td align="right"&gt;59&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th&gt;3x3&lt;/th&gt;
      &lt;th&gt;1024&lt;/th&gt;
      &lt;td align="right"&gt;786,513,819&lt;/td&gt;
      &lt;td align="right"&gt;25,179,014&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th&gt;4x4&lt;/th&gt;
      &lt;th&gt;64&lt;/th&gt;
      &lt;td align="right"&gt;2,816,814,934,817&lt;/td&gt;
      &lt;td align="right"&gt;40,652,843,435&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th&gt;4x4&lt;/th&gt;
      &lt;th&gt;2048&lt;/th&gt;
      &lt;td align="right"&gt;44,096,167,159,459,777&lt;/td&gt;
      &lt;td align="right"&gt;\(\gg\) 1.3 trillion&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Just like the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile is the highest reachable tile on the 2x2 board, the &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt; tile &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html#fnref:smallest-board"&gt;is the highest&lt;/a&gt; on the 3x3 board. Exhaustive enumeration of states shows that the 3x3 game contains about 25 million states, which is a factor of 31 lower than the rough ‘Combinatorics Bound’ from &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html"&gt;the previous post&lt;/a&gt;. For the game on the 4x4 board to the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile, which is the largest game on the 4x4 board that I was able to completely enumerate, the factor is even larger, at 69. As expected, the (very basic) combinatorics bounds were quite loose, because they count many states that can’t occur in the game or are trivially related to each other.&lt;/p&gt;

&lt;p&gt;For the 3x3 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt; tile, there are too many states to draw a diagram like the one for the 2x2 game above. However, we can gain some insight into that 25 million figure by counting states in groups by (1) the sum of the tiles on the board and (2) the value of the maximum tile on the board. The sum of the tiles on the board increases by either 2 or 4 with each move &lt;sup id="fnref:property-3"&gt;&lt;a class="footnote" href="#fn:property-3" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;, so the game generally progresses from left to right on this graph:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/enumeration_3x3_to_1024.svg"&gt;&lt;img alt="Number of states by tile sum and maximum tile value in the 3x3 game to 1024" src="/assets/2048/enumeration_3x3_to_1024.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Early in the game, when the sum of the tiles is small, the number of states grows fairly smoothly and linearly with the sum of tiles. However, later in the game when the board fills up, there are sharp drops around where the sum of tiles reaches a larger power of two, for example at around sums 128 and 256. These drops indicate that the 3x3 game is tightly constrained by the small size of the board — there are not many ways to survive past these drops without merging most of the tiles together into a larger one.&lt;/p&gt;

&lt;p&gt;It’s also notable that the same structure seems to repeat each time a larger maximum tile is reached (that is, each time the shade of blue in the plot gets darker). The 64, 128, 256 and 512 max tile curves each have a similar slope at the start and a ‘step’ at about 26,000 states per tile sum. In terms of gameplay, this repetition reflects the fact that once you merge most of the tiles together to get the next largest one, the board is mostly empty again, except for the newly merged tile, so the game sort of ‘resets’ at that point.&lt;/p&gt;

&lt;p&gt;We might hope that the game on the 4x4 board would also show some of these characteristics, but at least up to tile sum 380, this is apparently not the case. After running the enumeration for one month and counting over 1.3 trillion states, the results to date for the full game of 2048 look like:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/enumeration_4x4_to_2048_partial.svg"&gt;&lt;img alt="Number of states by tile sum and maximum tile value in the 4x4 game to 2048" src="/assets/2048/enumeration_4x4_to_2048_partial.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We see smooth and uninterrupted growth in the total number of states. Whereas the game on the 3x3 board topped out at about 80 thousand states per tile sum, the game on the 4x4 board shows no sign of slowing down at 27 billion states per tile sum &lt;sup id="fnref:resolve"&gt;&lt;a class="footnote" href="#fn:resolve" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;We can still see the rise and fall in the number of states with each maximum tile value, and it becomes clearer if we unstack these counts and plot them on a logarithmic scale:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/enumeration_4x4_to_2048_partial_log.svg"&gt;&lt;img alt="Number of states by tile sum and maximum tile value in the 4x4 game to 2048 on a log scale" src="/assets/2048/enumeration_4x4_to_2048_partial_log.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The top line in black shows the total number of states, summing over all the maximum tile values, which are again shown in shades of blue. Each blue arc shows the growth and later decay in the number of states with a given maximum tile value, as the game progresses. The bending down of the total (black line) shows that the growth in the number of states per tile sum tapers off as the game progresses, but the numbers are already quite large.&lt;/p&gt;

&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;We’ve improved our estimates for the number of states in the game of 2048 on the 2x2 and 3x3 boards by one to two orders of magnitude, compared to the previous (basic) combinatorial estimates. The number of states for the game on the 4x4 board remains too large to enumerate in full, but we have at least managed to completely enumerate the states for the 4x4 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile, and we’ve made an attempt at enumerating the states for the full game.&lt;/p&gt;

&lt;p&gt;The explicit enumeration of states counts only states that can be reached in actual game play, but even with that restriction there are still some surprising states included in the count. For example, in the last figure above, the arc that shows the number of states with at most a &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile does not stop until tile sum 348. There are four states with tile sum 348 and no &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile, one of which I chose for the cover image of this post: &lt;sup id="fnref:cover"&gt;&lt;a class="footnote" href="#fn:cover" rel="footnote"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="State from layer 348 with no 64 tile; contains diagonal bands of 16s and 32s" src="/assets/2048/4x4_s2_3_4_5_4_5_4_5_5_4_5_4_4_5_4_5.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;It contains seven &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tiles and seven &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tiles arranged in a nice striped pattern that makes it very difficult to merge any of them. I find it quite surprising that it’s possible to play to such a state without losing, and indeed it seems quite improbable, especially if one is ‘playing well’.&lt;/p&gt;

&lt;p&gt;In the next post, we’ll explore what it means to ‘play well’ in a rigorous way by modeling the game of 2048 as a &lt;a href="https://en.wikipedia.org/wiki/Markov_decision_process"&gt;Markov Decision Process&lt;/a&gt; and finding an &lt;em&gt;optimal policy&lt;/em&gt; for the 2x2 and 3x3 games — that is, we will find a strategy for playing those game that we can show mathematically to be at least as good as any other possible strategy.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1 id="appendix-a-bit-bashing-for-efficiency"&gt;Appendix A: Bit Bashing for Efficiency&lt;/h1&gt;

&lt;p&gt;Profiling the ruby code above revealed that most of the time was being spent on state manipulation — for example, moving tiles, counting available tiles, and reflecting or rotating states to find canonical states. Let’s see how we can speed it up.&lt;/p&gt;

&lt;p&gt;The hexadecimal numerical representation for states has a convenient property: for the 4x4 board, we need to store 16 numbers, where each number takes 4 bits, for a total of 64 bits. Now that we all use 64-bit computers, this is an auspicious number: the whole board state can fit into a single 64-bit (8-byte) machine word. For example, the 4x4 state (which is a winning state, because it has a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile)&lt;/p&gt;
&lt;p align="center"&gt;&lt;img alt="- 4 4 2048 - 2 8 - 4 - 2 - - - - -" src="/assets/2048/4x4_s0_2_2_11_0_1_3_0_2_0_1_0_0_0_0_0.svg" /&gt;&lt;/p&gt;
&lt;p&gt;would be written &lt;code class="language-plaintext highlighter-rouge"&gt;0x022b013020100000&lt;/code&gt; in hexadecimal, or more clearly with the addition of line breaks to make a 4x4 grid:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;022b
0130
2010
0000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the state represented as a 64-bit integer, we can also implement many common manipulations on states very efficiently using bit mask and shift operations, often without loops &lt;sup id="fnref:bit-bashing"&gt;&lt;a class="footnote" href="#fn:bit-bashing" rel="footnote"&gt;4&lt;/a&gt;&lt;/sup&gt;. For example, the C++ function to reflect a 4x4 board state horizontally looks like:&lt;/p&gt;
&lt;div class="language-cpp highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="nf"&gt;reflect_horizontally&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;c1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xF000F000F000F000ULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;c2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x0F000F000F000F00ULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;c3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x00F000F000F000F0ULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;c4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x000F000F000F000FULL&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;c1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&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="n"&gt;c2&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&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="n"&gt;c3&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&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="n"&gt;c4&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;12&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;While initially quite opaque, all this is doing is shuffling bits around. The role of first bit mask, &lt;code class="language-plaintext highlighter-rouge"&gt;0xF000F000F000F000ULL&lt;/code&gt;, becomes clearer if we omit the &lt;code class="language-plaintext highlighter-rouge"&gt;0x&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;ULL&lt;/code&gt;, which just tell the compiler that this is non-negative 64-bit integer in hexadecimal, and again add line breaks to make a 4x4 grid:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;F000
F000
F000
F000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The binary representation of the hexadecimal digit &lt;code class="language-plaintext highlighter-rouge"&gt;F&lt;/code&gt; is &lt;code class="language-plaintext highlighter-rouge"&gt;1111&lt;/code&gt;, so the effect of this bit mask is to make &lt;code class="language-plaintext highlighter-rouge"&gt;c1&lt;/code&gt; contain only the values in the first column of the board and zero bits everywhere else. The bit shift &lt;code class="language-plaintext highlighter-rouge"&gt;c1 &amp;gt;&amp;gt; 12&lt;/code&gt; at the end of the function moves the first column 12 bits, which is to say three 4-bit cells, to the right, which makes it the last column. Similarly, &lt;code class="language-plaintext highlighter-rouge"&gt;c2&lt;/code&gt; selects the second column, and &lt;code class="language-plaintext highlighter-rouge"&gt;c2 &amp;gt;&amp;gt; 4&lt;/code&gt; moves it one cell to the right, and so on with the third and fourth columns to reverse the order of the columns.&lt;/p&gt;

&lt;p&gt;Some functions take a bit more work to decipher. If you’re in the mood for a puzzle, here’s a function that counts the number of cells available (value zero) in a 4x4 state (you can find &lt;a href="https://github.com/jdleesmiller/twenty48/blob/479f646e81c38f1967e4fc5942617f9650d2c735/ext/twenty48/state.hpp#L68-L83"&gt;my explanation in comments here&lt;/a&gt;):&lt;/p&gt;
&lt;div class="language-cpp highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;cells_available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;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;state&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="mh"&gt;0x1111111111111111ULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mh"&gt;0x1111111111111111ULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&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="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="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;count&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;Profiling (with &lt;a href="https://en.wikipedia.org/wiki/Perf_(Linux)"&gt;perf&lt;/a&gt;) showed that such tricks made a big difference — compared to the obvious implementations with arrays and loops, these functions require very few CPU instructions and contain few or no branches, which allows the CPU to keep its &lt;a href="https://en.wikipedia.org/wiki/Instruction_pipelining"&gt;instruction pipelines&lt;/a&gt; full.&lt;/p&gt;

&lt;h1 id="appendix-b-layers-and-mapreduce-for-parallelism"&gt;Appendix B: Layers and MapReduce for Parallelism&lt;/h1&gt;

&lt;p&gt;The next challenge is that we can’t keep the whole &lt;code class="language-plaintext highlighter-rouge"&gt;closed&lt;/code&gt; set in memory. To break up the state space into manageably sized pieces, we can use the following property of the game: &lt;em&gt;The sum of the tiles on the board increases by either 2 or 4 with each move.&lt;/em&gt; This property holds because merging two tiles does not change the sum of the tiles on the board, and the game then adds either a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile. &lt;sup id="fnref:property-3:1"&gt;&lt;a class="footnote" href="#fn:property-3" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;This property is useful here because it means that we can organize the states into &lt;em&gt;layers&lt;/em&gt; according to the sum of their tiles. We can therefore generate the whole state space by working through a single layer at a time, rather than having to deal with the whole state space at once.&lt;/p&gt;

&lt;p&gt;To parallelize the work within each layer, we can use the &lt;a href="https://en.wikipedia.org/wiki/MapReduce"&gt;MapReduce&lt;/a&gt; concept made famous by Google. The ‘map’ step here is to take one complete layer of states with sum \(s\) and break it up into pieces; then, for each piece in parallel, generate all of the successor states, which will have either sum \(s + 2\) or \(s + 4\). The ‘reduce’ step is to merge all of the pieces for the layer with sum \(s + 2\) together into a complete layer, removing any duplicates. The pieces with sum \(s + 4\) are retained until the next layer, in which states have sum \(s + 2\), is processed, at which point they will be included in the merge. This may be easier to see in an animation (made with &lt;a href="https://d3js.org"&gt;d3&lt;/a&gt;):&lt;/p&gt;

&lt;div id="map-reduce"&gt;&lt;/div&gt;

&lt;p&gt;In the map step for each piece, it is feasible to maintain the set of successor states in memory. To make the merge in the reduce step efficient, we want the map step to output a list of states for each piece in order by their state numbers so we can merge the pieces together in linear time. Here Google again comes to our aid: they have released a handy in-memory &lt;a href="https://code.google.com/archive/p/cpp-btree/"&gt;B-tree implementation&lt;/a&gt; that plays well with the C++ standard template library. &lt;a href="https://en.wikipedia.org/wiki/B-tree"&gt;B-trees&lt;/a&gt; are most commonly found in relational database systems, where they are often used to maintain indexes on columns. They keep data in order and provide logarithmic time lookup and also logarithmic time insertion — much better than logarithmic plus linear time insertion into a sorted list — with relatively little memory overhead.&lt;/p&gt;

&lt;p&gt;To break the state space up into even smaller pieces, which reduces the amount of work we need to do in each merge step, we can exploit an another property of the game: &lt;em&gt;the maximum tile value on the board must either stay the same or double with each move.&lt;/em&gt; This property holds because the maximum tile value never decreases, and when it does increase, it can only increase as the result of merging two tiles — that is, even if you have for example four &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tiles in a row and you merge them, after one move the result is two &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tiles, not one &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;Together with the property above, this means that from a list of states in which all states have tile sum \(s\) and maximum tile value \(k\), the generated successors will all fall into one of four pieces:&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th align="right"&gt;Piece&lt;/th&gt;
      &lt;th align="right"&gt;1&lt;/th&gt;
      &lt;th align="right"&gt;2&lt;/th&gt;
      &lt;th align="right"&gt;3&lt;/th&gt;
      &lt;th align="right"&gt;4&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th align="right"&gt;Tile Sum&lt;/th&gt;
      &lt;td align="right"&gt;\(s+2\)&lt;/td&gt;
      &lt;td align="right"&gt;\(s+2\)&lt;/td&gt;
      &lt;td align="right"&gt;\(s+4\)&lt;/td&gt;
      &lt;td align="right"&gt;\(s+4\)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th align="right"&gt;Max Tile Value&lt;/th&gt;
      &lt;td align="right"&gt;\(k\)&lt;/td&gt;
      &lt;td align="right"&gt;\(2k\)&lt;/td&gt;
      &lt;td align="right"&gt;\(k\)&lt;/td&gt;
      &lt;td align="right"&gt;\(2k\)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;There is a bit more bookkeeping to keep track of which pieces need to be merged together at each step, but it is basically the same idea. Here are the 57 states (excluding the ‘win’ and ‘lose’ states) for the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile again, this time with the states grouped by tile sum and maximum tile value, here written \(s / k\):&lt;/p&gt;
&lt;p align="center"&gt;
  &lt;a href="/assets/2048/enumeration_2x2_grouped.svg"&gt;&lt;img alt="States from the enumeration of the 2x2 game to 32 with grouping into parts by sum and max value" src="/assets/2048/enumeration_2x2_grouped.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;For example, in the leftmost piece, both states have tile sum 4 and maximum tile value &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt;. The transitions from that piece are to pieces with tile sum either 6 or 8 and maximum tile value &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;. Compared to the original diagram of these states without grouping, it’s also easier to see that you always transition to a state with a tile sum that is either 2 or 4 larger, like in the &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;first post&lt;/a&gt; in this series.&lt;/p&gt;

&lt;h1 id="appendix-c-encoding-and-compression"&gt;Appendix C: Encoding and Compression&lt;/h1&gt;

&lt;p&gt;When working with billions or trillions of states, and each state takes 8 bytes, even fitting them all on disk is not trivial (or at least not cheap). To reduce the storage space required, and also the amount of input/output required, we can exploit the fact that the states are stored as sorted lists of integers — rather than storing each integer in full, we can store the differences between successive integers. These differences will generally be smaller than the integers themselves, so it is usually possible to store the differences in a smaller number of bytes. Using a &lt;a href="https://en.wikipedia.org/wiki/Variable-width_encoding"&gt;variable-width encoding scheme&lt;/a&gt; to store the differences ensures that we use only the number of bytes we need. &lt;sup id="fnref:variable-width"&gt;&lt;a class="footnote" href="#fn:variable-width" rel="footnote"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;For example, the list of states for the 4x4 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile with tile sum 380 and maximum tile value &lt;code class="language-plaintext highlighter-rouge"&gt;128&lt;/code&gt; contains 21,705,361,721 states &lt;sup id="fnref:resolve:1"&gt;&lt;a class="footnote" href="#fn:resolve" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;. At 8 bytes per state, that would be roughly 161GiB. However, with variable-width encoding, it takes only 35GiB — a compression factor of 4.6 — or about 1.7 bytes per state.&lt;/p&gt;

&lt;p&gt;For longer term storage and transport over Internet, I also &lt;a href="/articles/2017/05/01/compression-pareto-docker-gnuplot.html"&gt;tried several compression programs&lt;/a&gt; on the variable-width encoded data. To evaluate the different programs, I used a smaller list of states with tile sum 260 and maximum tile value &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt;; it contained 30,954,422 states, which is about 1/700th the number in the 380/128 layer mentioned above, and it weighed in at 64MiB after variable-width encoding. For each of the programs, and for each of their supported compression levels, I measured the elapsed time for compression and the resulting compressed size using this smaller list of states.&lt;/p&gt;

&lt;p&gt;Three programs emerged on the resulting &lt;a href="/articles/2017/05/01/compression-pareto-docker-gnuplot.html"&gt;Pareto frontier&lt;/a&gt;: Facebook’s &lt;a href="https://github.com/facebook/zstd"&gt;Zstandard&lt;/a&gt;, Google’s &lt;a href="https://github.com/google/brotli"&gt;Brotli&lt;/a&gt; and &lt;a href="http://www.7-zip.org/"&gt;7-zip&lt;/a&gt;. After scaling size and time up by a factor of 700 to estimate performance on the larger 380/128 layer, the frontier looks like:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/sum-0260.max_value-5.scale-701.svg"&gt;&lt;img alt="Pareto frontier for selecting a compression program for lists of 2048 states" src="/assets/2048/sum-0260.max_value-5.scale-701.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Here closer to the origin is better; we see Zstandard performing best for relatively fast and light compression, and 7zip performing best for relatively slow and heavy compression. From the graph, we can see that Zstandard at compression level 11 is fairly close to the origin, and it turned out to minimize the particular linear cost function that I used. The results on the smaller layer suggested that Zstandard level 11 would reduce the 380/128 layer from 35GiB to about 10GiB. In fact, it did much better: it reduced it from 35GiB to 3.8GiB, for another factor of 9.2, or about 1.5 &lt;em&gt;bits&lt;/em&gt; per state. I think that’s quite remarkable.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://twitter.com/h0peth0mas"&gt;Hope Thomas&lt;/a&gt; for reviewing drafts of this article.&lt;/p&gt;

&lt;p&gt;If you’ve read this far, perhaps you should &lt;a href="https://twitter.com/jdleesmiller"&gt;follow me on twitter&lt;/a&gt;, or even apply to work at &lt;a href="https://www.overleaf.com/jobs"&gt;Overleaf&lt;/a&gt;. &lt;code class="language-plaintext highlighter-rouge"&gt;:)&lt;/code&gt;&lt;/p&gt;

&lt;h1 id="footnotes"&gt;Footnotes&lt;/h1&gt;









&lt;!--
To make the state diagram:

Go to http://gabrielecirulli.github.io/2048/
Open dev console
gm = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager)
// Remove the two random tiles (if needed); for me they were:
gm.grid.removeTile(new Tile({x: 0, y: 2}))
gm.grid.removeTile(new Tile({x: 3, y: 3}))
gm.actuate()
// Board should be empty
gm.grid.insertTile(new Tile({x: 0, y: 0}, 4))
gm.grid.insertTile(new Tile({x: 1, y: 0}, 8))
gm.grid.insertTile(new Tile({x: 2, y: 0}, 16))
gm.grid.insertTile(new Tile({x: 3, y: 0}, 32))

gm.grid.insertTile(new Tile({x: 0, y: 1}, 16))
gm.grid.insertTile(new Tile({x: 1, y: 1}, 32))
gm.grid.insertTile(new Tile({x: 2, y: 1}, 16))
gm.grid.insertTile(new Tile({x: 3, y: 1}, 32))

gm.grid.insertTile(new Tile({x: 0, y: 2}, 32))
gm.grid.insertTile(new Tile({x: 1, y: 2}, 16))
gm.grid.insertTile(new Tile({x: 2, y: 2}, 32))
gm.grid.insertTile(new Tile({x: 3, y: 2}, 16))

gm.grid.insertTile(new Tile({x: 0, y: 3}, 16))
gm.grid.insertTile(new Tile({x: 1, y: 3}, 32))
gm.grid.insertTile(new Tile({x: 2, y: 3}, 16))
gm.grid.insertTile(new Tile({x: 3, y: 3}, 32))

gm.actuate()
// Board should have the state.
--&gt;
&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:property-3"&gt;
      &lt;p&gt;This property was called called &lt;em&gt;Property 3&lt;/em&gt; in the &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html"&gt;previous post&lt;/a&gt;, and we also used it anonymously in the &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;first post&lt;/a&gt;. It is a very useful property. &lt;a class="reversefootnote" href="#fnref:property-3"&gt;&amp;#8617;&lt;/a&gt; &lt;a class="reversefootnote" href="#fnref:property-3:1"&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:resolve"&gt;
      &lt;p&gt;These figures come from the one month build on the full 4x4 game, which used an additional technique for reducing the size of the state space: for each state, it looked one move ahead to see whether the next move was a definite win or a definite loss; if it was, the state was collapsed to a special ‘one move to win’ or ‘one move to lose’ state. This technique was not very effective, however, because states that are close to a loss tend to have few very successors anyway, and because win states only occur much later in the game, and the enumeration process never reached a win state. I therefore haven’t included it in the main body of the article, but the &lt;a href="https://github.com/jdleesmiller/twenty48/blob/479f646e81c38f1967e4fc5942617f9650d2c735/ext/twenty48/valuer.hpp"&gt;code is here&lt;/a&gt;. The state counts mentioned in this article for the partial enumeration of states with the 4x4 board to the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile are slightly reduced compared to what they would be without this technique, but only slightly. &lt;a class="reversefootnote" href="#fnref:resolve"&gt;&amp;#8617;&lt;/a&gt; &lt;a class="reversefootnote" href="#fnref:resolve:1"&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:cover"&gt;
      &lt;p&gt;In case you are wondering, I faked that screenshot; I didn’t actually play the game to that state! &lt;a class="reversefootnote" href="#fnref:cover"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:bit-bashing"&gt;
      &lt;p&gt;The bit bashing techniques used here are based mainly on &lt;a href="https://github.com/nneonneo/2048-ai/blob/1f25f2e19e82a477600fd1b437e710d584f99e99/2048.cpp"&gt;2048-ai&lt;/a&gt; by Robert Xiao and &lt;a href="https://github.com/kcwu/2048-c/blob/209a1f5ea635222a859c493a90d3304328117af3/micro_optimize.cc"&gt;2048-c&lt;/a&gt; by Kuang-che Wu, with some help from &lt;a href="http://graphics.stanford.edu/~seander/bithacks.html"&gt;Bit Twiddling Hacks&lt;/a&gt; by Sean Eron Anderson. The original motivation for 2048-ai and 2048-c was to allow real time search for 2048 AI bots. &lt;a class="reversefootnote" href="#fnref:bit-bashing"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:variable-width"&gt;
      &lt;p&gt;Variable width encodings are most commonly encountered in the &lt;a href="https://en.wikipedia.org/wiki/UTF-8"&gt;UTF-8&lt;/a&gt; character encoding for unicode, which you are using as you read this webpage. They are also sometimes used for storing &lt;a href="https://en.wikipedia.org/wiki/Database_index"&gt;integer primary key indexes&lt;/a&gt; in some databases, which also face the problem of efficiently storing large lists of sorted integers. The implementation used here is &lt;a href="https://github.com/cruppstahl/libvbyte"&gt;libvbyte&lt;/a&gt; from Christoph Rupp, based on work by &lt;a href="https://github.com/lemire/MaskedVbyte"&gt;Daniel Lemire&lt;/a&gt;. &lt;a class="reversefootnote" href="#fnref:variable-width"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>jdlm.info</author><pubDate>Sun, 10 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://jdlm.info/articles/2017/12/10/counting-states-enumeration-2048.html</guid></item><item><title>Hour of Code 2017</title><link>https://www.mikekasberg.com/blog/2017/12/09/hour-of-code-2017.html</link><description>&lt;p&gt;The &lt;a href="https://hourofcode.com/us"&gt;Hour of Code&lt;/a&gt; is an annual event to encourage
Computer Science education during &lt;a href="https://csedweek.org/"&gt;Computer Science Education
Week&lt;/a&gt;. I participated this year by volunteering at an
elementary school, where I spent about an hour introducing the students to
computer programming through &lt;a href="https://scratch.mit.edu/"&gt;Scratch&lt;/a&gt;. I think
Scratch is a great way to introduce people (both young and old) to programming
because it is simple enough that beginners can get started very quickly, but
also powerful enough to create good-looking games (like this &lt;a href="https://scratch.mit.edu/projects/17341536/"&gt;Flappy Bird
Clone&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id="asteroid-field-a-game"&gt;Asteroid Field (A Game)&lt;/h2&gt;

&lt;p&gt;I designed my own lesson for the Hour of Code 2017. I wanted my lesson to be
centered around designing a simple game. The game needed to be fun to play, but
still exceptionally simple - simple enough that 5th grade students could program
a more-or-less functional copy in roughly an hour. I designed an &lt;a href="https://scratch.mit.edu/projects/187823663/"&gt;Asteroid Field
Game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, although the game linked above is pretty simple (roughly 60 lines of
Scratch code), I needed to simplify it even more to ensure that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the program was not too complex for 5th-graders, and&lt;/li&gt;
  &lt;li&gt;we could program it in about an hour.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To that end, I created an &lt;a href="https://scratch.mit.edu/projects/188595736/"&gt;even more simple
version&lt;/a&gt; of the same game. This one
is only 20 lines of Scratch code, and some of those (such as the score) are
optional. I felt that programming a game like this was within the reach of 5th
grade students, and I planned the lesson in chunks so that we would finish
&lt;em&gt;something&lt;/em&gt; that resembles the Asteroid Field game, even if we didn’t finish
completely.&lt;/p&gt;

&lt;p&gt;Overall, the lesson was a huge success. The class loved it, and I think many of
them came away from the lesson with a better understanding of &lt;em&gt;what programming
is&lt;/em&gt; than they had going in. Perhaps more importantly, I think that for many kids
this opened a doorway to a new world. I hope that for at least a few students I
sparked an interest in computer science that they will pursue for many years to
come.&lt;/p&gt;

&lt;p&gt;If you’re interested in seeing the lesson, you can check out &lt;a href="https://docs.google.com/document/d/17zNhIeBrRy4l6vY3fIrG6gye4rsPbf0GaVWZOww-hos/edit?usp=sharing"&gt;the lesson
plan&lt;/a&gt;
and &lt;a href="https://docs.google.com/presentation/d/1GiAH6giiEN-whpG_N6uPdZZW7DCss6u-5YX6OQr1D4k/edit?usp=sharing"&gt;the
slides&lt;/a&gt;.
The Scratch game and source code, along with some of my other Scratch projects,
can be found on &lt;a href="https://scratch.mit.edu/users/mkasberg/"&gt;my Scratch profile&lt;/a&gt;.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sat, 09 Dec 2017 22:30:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/12/09/hour-of-code-2017.html</guid></item><item><title>NIPS 2017</title><link>https://rachitsingh.com/nips/</link><description>&lt;p&gt;I'm starting this blog to share research ideas that I have, and some solutions to problems I find along the way. I've been helped immensely by other people's blogs in the past, and want to do the same. Also it'll give me a chance to communicate the way I approach problems, and hopefully people will give me alternative perspectives either by email (&lt;a href="mailto:rachitsingh@outlook.com"&gt;rachitsingh@outlook.com&lt;/a&gt;) or in the comments, once I figure out how that works.&lt;/p&gt;
&lt;p&gt;I'm going to steadily post my thoughts on NIPS 2017 (summary: lots of exposure to new ideas, very glad I went); but as a start I'm going to explain how we went: Jeffrey Ling and I submitted a &lt;a href="http://approximateinference.org/2017/accepted/SinghEtAl2017.pdf"&gt;short paper&lt;/a&gt; on Indian Buffet Processes to the &lt;a href="http://approximateinference.org"&gt;NIPS workshop on Advances in Approximate Bayesian Inference (AABI)&lt;/a&gt;, and we were accepted. See the &lt;a href="https://github.com/rachtsingh/ibp_vae"&gt;repo&lt;/a&gt; for runnable code and some more information. I'll blog about the IBP as well soon, possibly after we have our ArXiv preprint up (soon!).&lt;/p&gt;</description><author>Rachit Singh</author><pubDate>Sat, 09 Dec 2017 10:47:37 GMT</pubDate><guid isPermaLink="true">https://rachitsingh.com/nips/</guid></item><item><title>Recurse Center 21: nom and combinators</title><link>https://peterlyons.com/problog/2017/12/recurse-center-21-nom-and-combinators/</link><description>&lt;p&gt;Last night I asked RC about whether &lt;code&gt;nom&lt;/code&gt; or &lt;code&gt;untrusted&lt;/code&gt; seemed like better crate choices for parsing mixed text and binary file formats. This morning I woke up super early for no reason and was ready to go so I watched RC alumnus Stefanie Schirmer's talk on parser combinators.&lt;/p&gt;
&lt;div class="youtube-video-container"&gt;

&lt;/div&gt;
&lt;p&gt;Then I was excited to dig in so after I commuted in to RC early I searched on crates for "nom pem" since the PEM format was what I needed to parse next. I found an existing crate &lt;code&gt;nom_pem&lt;/code&gt; that looked promising so I gave it a whirl. I was able to get it to parse a test file but I couldn't get at the parsed data. I was getting a "that field is private" error which was odd. How was I supposed to do anything with this parser if the parser output is private? So I looked again at the crate and saw "Last updated 2 hours ago". That was not the most recent update, that was the only update ever. Someone had published a nom PEM parsing crate to crates.io while I was watching the combinator video!&lt;/p&gt;
&lt;p&gt;So I was download number 5 (probably a bunch of bots beat me to it) for that crate and the first github star. Within a few hours I had forked it and sent in 3 small PRs to fix trivial but showstopper issues, and by the afternoon they all had been merged. Go open source!&lt;/p&gt;
&lt;p&gt;So I dove into learning &lt;code&gt;nom&lt;/code&gt; which makes heavy use of macros which are hard. I spent basically all day starting with the most trivial example of like "can I tell that 'a' is the letter 'a'?" and eventually was at the point where I could parse the openssh public key format. Then I started to refactor that code into tealeaves but there's still more to do.&lt;/p&gt;
&lt;p&gt;Today I also heard one of the RC mini-batchers talk about some cool clojure spec libraries and had a nice dinner out instead of take-out which was fun.&lt;/p&gt;
&lt;p&gt;Today's unix command line tip is that there's a golang project by google called &lt;a href="https://github.com/google/der-ascii"&gt;der-ascii&lt;/a&gt; that can translate both ways between the binary DER format used in some crypto stuff and an editable ascii version. Works like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;grep -v - files&amp;#x2f;ssh-rsa-1024-a-private-key.pem| base64 -D | der2ascii
SEQUENCE {
  INTEGER { 0 }
  INTEGER { `00a3475d589021587893902869f524c6493856c3ad46f28eeee793a22da33dfd0c690f67a99b3acef3dcc877f4ad98fb91feb6c39d25a28871ad73a03bc7143a559de8eb22e3ca69a72ca6059a7ff5526878de96d29d82f2227be0308efb1e9f5fbf256c11f35e7ee8213961980b208666463f48c115a884aabc1ba7705f3293a7` }
  INTEGER { 65537 }
  INTEGER { `3bfa5915d14c0e7dac67061176159e2903630bda38f79cfdb15f8ff187c79b8ed580ed29667641d35ec4dd1baa314a282512e9e46e10b86259bee19b53d3e06140b6b2bfaaf9434b92569e5f67cd7d90deeeb0fb609fcdacb83518da6e7f39dc5c39bfb726362458fae49c03127338799e1104183cb4015a71b5f1cea91dd621` }
  INTEGER { `00d07dcd4433eebddf5ca318643c4b6066bc37ebd01e9b9468e8b97a0d9542b15ad236247a43f35b9a54acc7398ef9b0283658ca103e1b3e2eed4bf9f0b2abf4bf` }
  INTEGER { `00c87c1d8693dc1d624e30e6627fd79246da11aac0f95467193226a348cfb0ec2c605516cb73a472d558b54752666445046bb4e02057227260208f744832a29319` }
  INTEGER { `0b2b622ed0356f18a346dd8ca92a449cdc6286909cc32afd3fd287f66853ad5ab73e4d4ffb89f3135e8bef1467537b1b7c65df55656e62337365099bda8699d3` }
  INTEGER { `394f31697ceed8ff76f68784f4a27cd0001a38c37d02618e5445b33b67135e0fb961d9684320692b0f769272bd8e4024695d850bf99c8131755d4c922ed74651` }
  INTEGER { `54dfe6859a0ca3df5d85bbc031b6da4428af4328629157045495aedc9f3056b2538ebf513fbcc4bfe79d4a35a7cc3afedf79b7f856997cb3783dfad052a6ca06` }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty handy! I couldn't find it in homebrew so I had to compile it by hand and manually install it, but it works.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 09 Dec 2017 03:37:35 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-21-nom-and-combinators/</guid></item><item><title>Deep living</title><link>http://dimitarsimeonov.com/2017/12/09/deep-living</link><description>&lt;p&gt;Imagine doing a lot of fun things, a lot of travel, and a lot of
pleasure. Imagine laying down on the beach, sipping a Margarita. The
salty rim of the glass. A feeling of being refreshed and
cheered. Getting up from a beach bed and laying down on a massage
table, relaxing and drifting off to sleep. Later on, a tasty dinner
with the partner, dancing the calories away in the night club, and
having sex.&lt;/p&gt;

&lt;p&gt;We imagine ourselves in the above situation. And we think - “ah, this
is good life”. Well, it’s good, but it is not deep. We are indulging
our primal senses. Our neuron receptors. Our input layer.&lt;/p&gt;

&lt;p&gt;That’s called vacation. That’s not living. Vacation is necessary for
our low-level pleasure senses to recover from the numbness that
surrounds them in the everyday grind. We work hard to make money to
give ourselves pleasure, and as we work, we start to forget what
pleasure is. That’s why we need vacation. That’s why we need
weekends. To remind us. To strengthen and realign our understanding of
pleasure. To develop our input layer.&lt;/p&gt;

&lt;p&gt;And on top of the pleasure layer, we have our reason. Reason is the
next layer in the deep neural network in our brain. Reason builds on
top of pleasure and pain. We rely on it in everyday tasks, such as
deciding what to eat, and how warm to dress. It lets us figure out how
to maximize pleasure. It helps us deduce that we can increase the
thermostat when we feel cold, or eat a pizza when we are
hungry. Without reason, we’ll be worse off than most
animals. Especially those damn raccoons. They’ll take our pizza.&lt;/p&gt;

&lt;p&gt;But them raccoons get smarter and smarter, and we need to keep
updating our reasoning if want pizza. That’s why we develop strategies
as a layer on top of reason. We get a dog and teach it recognize
racoon smell, so we’re alert next time they come to steal our pizza.&lt;/p&gt;

&lt;p&gt;On top of strategies, we have principles and values. We value pizza,
and we value not being cheated. Our principle is that we don’t let
raccoons steal our pizza. We’re getting into emotion territory
now. Our principles and values derive from our emotions. Our emotions
dictate whether we feel sympathy or annoyance at those less strong and
less smart, and whether we feel admiration or fear towards the
stronger and smarter.&lt;/p&gt;

&lt;p&gt;Emotions are at the opposite end of the chain of neural layers, and
every swing of our emotions results in a swing in the layers after
it - strategy, reasons, and pleasure. Emotions are another input
layer. From top.&lt;/p&gt;

&lt;p&gt;As we get exposed to physical and emotional pleasures and pain, the
whole neural network shakes like a battle rope.  But this rope of
neurons is our identity. This is how we make decisions. We take the
whole rope into account when deciding to eat a pizza, get a dog, or
shoot a raccoon.&lt;/p&gt;

&lt;p&gt;The more this rope shakes, the more confused we are, and less
consistent in our decisions. When we change our strategy and
principles, we get dumber, and eviler. It doesn’t matter that we may
think of ourselves as good. Our actions define us, not our intentions.&lt;/p&gt;

&lt;p&gt;When we act with our emotions and senses, we become losers. Because we
let them attack and disrupt our decisions and actions and make them
inconsistent with the principles and strategies we have. So these principles and strategies no longer work.&lt;/p&gt;

&lt;p&gt;We are our decisions and actions, not our thoughts. Not our
intentions. Our actions.&lt;/p&gt;

&lt;p&gt;And here finally I can deliver my thesis. To live life fully, truly,
madly, deeply, like winners, we need to pin down our reasoning,
strategies and principles, we need to cut them out of granite so that
emotions and senses can’t sway or bend them easily, and our decisions
derive from a strong fixed point.&lt;/p&gt;

&lt;p&gt;It’s not an easy thing to do. It’s not pleasure. Pleasure is input
layer, and fear is the mind killer. We need to insulate our decision
making from pleasure and emotions. Not to fully separate, because then
we become robots, but to at least prevent minor swings in pleasure and
emotion to shake us out of our path in life.&lt;/p&gt;

&lt;p&gt;Living deeply, it’s a struggle. Struggle to stay focused and our
paths, struggle to keep eating healthy, struggle to treat others
kindly even when they don’t treat us kindly. Struggle to not be lazy
and procrastinate. Struggle to not act stupid. To keep refining and
improving our principles and strategies in a conscious way.&lt;/p&gt;

&lt;p&gt;Living deeply doesn’t feel easy. Because we’re making hard decisions, putting
effort in when we don’t feel like it, and abstaining from bad habits
when they are tempting. It’s sacrificing our time in order to help
others, or ignoring others in order to focus on the top
priorities. The choice might go either way depending on our principles
and the situation, but it will be hard, from emotional, and from
comfort viewpoint.&lt;/p&gt;

&lt;p&gt;Living deeply doesn’t feel exciting. It requires hard work which can
often get boring, repetitive, and ungrateful. It involves hours and
days of preparation and planning for a handful of interesting minutes
of high impact.&lt;/p&gt;

&lt;p&gt;Living deeply is mentally stressful. It requires us to ask the hard questions,
to be humble and to examine our values. It requires us to have
difficult conversations, and to do a lot of uncomfortable preventive
actions.&lt;/p&gt;

&lt;p&gt;And yet, living deeply feels like living. It feels like a breath of
fresh cold air.  Because we know we are on our own path.&lt;/p&gt;</description><author>D13V</author><pubDate>Sat, 09 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/12/09/deep-living</guid></item><item><title>Handling advanced product imports in WooCommerce</title><link>https://daniel.do/article/handling-advanced-product-imports-in-woocommerce</link><description>Learn how to handle advanced things like core fees when importing products into WooCommerce.</description><author>Daniel Immke</author><pubDate>Sat, 09 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/handling-advanced-product-imports-in-woocommerce</guid></item><item><title>CLI for alerts via Slack</title><link>https://blog.harterrt.com/slack_alerts.html</link><description>&lt;p&gt;I finally got a chance to scratch an itch today.&lt;/p&gt;
&lt;h2 id="problem"&gt;Problem&lt;/h2&gt;
&lt;p&gt;When working with bigger ETL jobs,
I frequently run into jobs that take hours to run.
I usually either step away from the computer
or work on something less important while the job runs.
I &lt;strong&gt;don't have a good …&lt;/strong&gt;&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Fri, 08 Dec 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/slack_alerts.html</guid></item><item><title>Recurse Center 20: Parsing is hard. Let's go shopping.</title><link>https://peterlyons.com/problog/2017/12/recurse-center-20-parsing-is-hard-lets-go-shopping/</link><description>&lt;p&gt;So I've found that the &lt;code&gt;pem&lt;/code&gt; crate I've been using doesn't parse headers, which are present in encrypted dsa private key files, and the &lt;code&gt;mailparse&lt;/code&gt; crate doesn't parse properly with unix newlines, which seems to be what openssh generates even though in theory the RFCs involved require carriage return newline AFAIK.&lt;/p&gt;
&lt;p&gt;So I spent most of the day writing my own PEM parser that handles headers and thinking about the things rust programmers think about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can this be done without allocating any extra memory?&lt;/li&gt;
&lt;li&gt;Have I failed at life if I have to copy this 10-byte string before freeing it 4 nanoseconds later?&lt;/li&gt;
&lt;li&gt;Can I represent all of my data as a giant enum so rust models it as a single &lt;code&gt;u64&lt;/code&gt; bitfield or something?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You know, that kind of stuff.&lt;/p&gt;
&lt;p&gt;But after another shopping spree on crates dot io I'm leaning heavily toward learning to use the &lt;code&gt;nom&lt;/code&gt; crate to parse this. There's even an open github issue asking for an example DER private key parser, which is what I've been working on. However, the &lt;code&gt;untrusted&lt;/code&gt; crate also looks promising. Tomorrow I'll see how quickly I can get something easy done with &lt;code&gt;nom&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I also gave a talk on Serverless today and pointed out my &lt;a href="https://github.com/focusaurus/hexagonal-lambda"&gt;hexagonal-lambda&lt;/a&gt; sample project.&lt;/p&gt;
&lt;p&gt;Here's the unix tip of the day. If you have some utf8 characters encoded as hexadecimal you can convert to regular utf8 like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;echo 65636473612d736861322d6e69737470333834 | xxd -r -p&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Which prints &lt;code&gt;ecdsa-sha2-nistp384&lt;/code&gt;&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 08 Dec 2017 05:13:00 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-20-parsing-is-hard-lets-go-shopping/</guid></item><item><title>Global Component Registration</title><link>https://dylanpaulus.com/posts/2017/global-component-registration/</link><description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Often, I find myself looking through open-source projects to see how they solve issues. Not bugs, but problems in code that cause repetition or excessive boilerplate. &lt;a href="https://ux.stackexchange.com/questions/12045/what-is-a-modal-dialog-window#12046"&gt;Modals&lt;/a&gt; have given me problems, specifically when having to create a specialized modal for different workflows. They are awkward. Modals, in the DOM, live outside of the scope of the current workflow. And, part of their state usually lives outside of the modal itself (hide/show). I came accross an interesting solution to the modal problem while looking through &lt;a href="https://github.com/getinsomnia/insomnia"&gt;Insomnia's&lt;/a&gt; code. This is a different post than what I normally do. I'll just be posting code as an example, and filling in the explaination through comments. Hopefully this will work as a reference, and starting point to play around with the idea.&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// ModalHandler.js
const modals = {};

/*
 * This function takes in a component, and then adds a
 * reference to it through a friendly named key-&amp;gt;value.
 */
export function registerModal(component) {
  if (!component) {
    return;
  }

  modals[component.name] = component;
}

/*
 * show() takes the component we want to show, and some additional
 * arguments. We'll then call the 'show' function on the component.
 * This allows us to 'activate' a component anywhere, but invert
 * control to the relative component.
 */
export function show(component, ...args) {
  const elem = modals[component.name];
  if (elem.show &amp;amp;&amp;amp; typeof elem.show === "function") {
    return elem.show(...args);
  }

  console.warn(`show() function is missing from ${component.name}.`);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// App.jsx
import React, { Component } from "react";
import { registerModal } from "./ModalHandler";

class Base extends Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;MyApp /&amp;gt;
        {/*
          This component is pretty regular except for this next bit.
          We'll pass in registerModal() to the component's ref we'll
          show later on
        */}
        &amp;lt;Modal ref={registerModal} /&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { show } from "./ModalHandler";
import Modal from "./Modal";

class MyApp extends Component {
  showModal = () =&amp;gt; {
    // Will call the .show() function
    // on the Modal component
    show(Modal);
  };

  render() {
    return &amp;lt;button onClick={this.showModal}&amp;gt;Show Modal&amp;lt;/button&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// Modal.jsx
import React, { Component } from "react";

class Modal extends Component {
  state = {
    isOpen: false,
  };

  // This is the show() function that'll be invoked
  // when this component is passed to ModalHandler.js' show() function
  show = () =&amp;gt; {
    this.setState({ isOpen: true });
  };

  render() {
    if (!this.state.isOpen) {
      return null;
    }

    return (
      &amp;lt;div&amp;gt;
        Modal!
        &amp;lt;button onClick={() =&amp;gt; this.setState({ isOpen: false })}&amp;gt;Close&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Fri, 08 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2017/global-component-registration/</guid></item><item><title>Afrocubism</title><link>https://rybakov.com/blog/afrocubism/</link><description>&lt;p&gt;&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/schwadrat_P1M0974.jpg" /&gt;




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;In the winter of 2013 I went to Guinea with a few friends. Guinea is one of my favourite destinations, since Silvia, the mother of my friend Christoph, is working there at a medical laboratory. And having nice people on the ground makes travelling to a foreign country much more enjoyable.&lt;/p&gt;
&lt;p&gt;Guinea is an interesting country to visit. It is rich in natural resources, which leads to wealth being concentrated in the hands of a few powerful families. It also means that tourism is non-existent and the only white people present are professionals working at mining companies and NGOs. You can be the only white person in a densely populated area, and you get eyed on the streets - it feels like everything you do would be talked about later, so you end up being not only a guest but also an ambassador for your culture.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Thu, 07 Dec 2017 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/afrocubism/</guid></item><item><title>Experiments are releases</title><link>https://blog.harterrt.com/experiments_are_releases.html</link><description>&lt;p&gt;&lt;a href="https://github.com/mozilla/missioncontrol"&gt;Mission Control&lt;/a&gt;
was a major 2017 initiative for the Firefox Data team.
The goal is to provide release managers with near-real-time
release-health metrics minutes after going public.
Will has a
&lt;a href="https://wlach.github.io/blog/2017/10/mission-control/"&gt;great write up here&lt;/a&gt;
if you want to read more.&lt;/p&gt;
&lt;p&gt;The key here is that the data has to be …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 07 Dec 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/experiments_are_releases.html</guid></item><item><title>Recurse Center 19: ASN.1 Tagged Context</title><link>https://peterlyons.com/problog/2017/12/recurse-center-19-asn-1-tagged-context/</link><description>&lt;p&gt;Coding on tealeaves today was mostly pulling interesting bits out of ssh keys. Misc things discovered&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;openssh will only generate 1024 bit dsa keys, which are not secure, but longer key sizes are supported by other software&lt;/li&gt;
&lt;li&gt;ecdsa keys the "bits" field represents either 256, 384, or 521 bit size curves and those are the only valid sizes&lt;/li&gt;
&lt;li&gt;The specific curves are encoded in ASN.1 as object identifiers that appear to be assigned well-known OIDs which tell you which curve it is&lt;/li&gt;
&lt;li&gt;At least one &lt;a href="https://security.stackexchange.com/questions/5096/rsa-vs-dsa-for-ssh-authentication-keys/46781#46781"&gt;stackoverflow answerer&lt;/a&gt; thinks ecdsa is backdoored by the NSA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also was struggling with tooling, which I guess is the name of the game in lower-level systems programming, and I ended up writing a little rust unix utility to hard wrap files at 32 characters after stripping whitespace so I can pipe hex dumps into it and get nice column widths. That was actually fairly fast and easy to do so for simple things it feels like once you're over the learning curve rust might actually deliver on its promise of scripting language ease with no-compromise performance at runtime.&lt;/p&gt;
&lt;p&gt;Later I paired with one of the RC mini-batchers who taught me about &lt;code&gt;fold -w 32&lt;/code&gt; which is a standard unix tool that can do most of the same thing.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 07 Dec 2017 01:22:37 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-19-asn-1-tagged-context/</guid></item><item><title>Desirable features of experimentation tools</title><link>https://blog.harterrt.com/good_experiment_tools.html</link><description>&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;At Mozilla,
we're quickly climbing up our
&lt;a href="https://cdn-images-1.medium.com/max/1600/1*7IMev5xslc9FLxr9hHhpFw.png"&gt;Data Science Hierarchy of Needs&lt;/a&gt;
&lt;sup&gt;1&lt;/sup&gt;.
I think the next big step for our data team
is to &lt;strong&gt;make experimentation feel natural&lt;/strong&gt;.
There are a few components to this (e.g. training or culture)
but improving the &lt;strong&gt;tooling is going to be …&lt;/strong&gt;&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Wed, 06 Dec 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/good_experiment_tools.html</guid></item><item><title>5000 concepts for Europe? The first one is...</title><link>https://stop.zona-m.net/2017/12/5000-concepts-for-europe-the-first-one-is.../</link><description>&lt;p&gt;In the first 12 hours from its actual public announcement, my proposal of a &lt;a href="https://stop.zona-m.net/2017/12/5000-concepts-for-europe-a-book-proposal/"&gt;&amp;ldquo;5000 concepts for Europe&amp;rdquo; book&lt;/a&gt; yeld some unexpected (for me, at least) results.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 06 Dec 2017 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/12/5000-concepts-for-europe-the-first-one-is.../</guid></item><item><title>Reading Simple Haskell</title><link>https://gilmi.me/post/2017/12/06/reading-simple-haskell</link><description>I wrote a presentation-style resource that tries to present a small part of Haskell and hopefully make it a little more accessible and a little less scary.</description><author>λm.me</author><pubDate>Wed, 06 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://gilmi.me/post/2017/12/06/reading-simple-haskell</guid></item><item><title>Simple JavaScript API wrapper</title><link>https://muffinman.io/blog/simple-javascript-api-wrapper/</link><description>&lt;article class="article"&gt;&lt;p&gt;For handling API calls I have a small snippet I&amp;#x27;m copying from project to project.
I decided to clean it up, make more generic and share it.
It is intended to be a starting point, so you might want to customize it to your custom needs.&lt;/p&gt;
&lt;h2 id="what-it-does"&gt;What it does? &lt;a class="anchor-link" href="#what-it-does"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is a simple wrapper around
&lt;span class="sidenote__text" tabindex="0"&gt;native &lt;code&gt;fetch&lt;/code&gt;.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;If you need a polyfill &lt;a href="https://www.npmjs.com/package/isomorphic-fetch"&gt;isomorphic-fetch&lt;/a&gt; is a great one.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For successful requests it will parse the response and return it.&lt;/li&gt;
&lt;li&gt;When
&lt;span class="sidenote__text" tabindex="0"&gt;HTTP error occurs&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;It detects errors based on request's HTTP status.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
it will throw a custom error with status code, error message and
response (parsed if it is a JSON).&lt;/li&gt;
&lt;li&gt;If request never gets resolved, same custom error will be thrown but
response will be set to &lt;code&gt;null&lt;/code&gt; and status code to &lt;code&gt;REQUEST_FAILED&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please note that function will return a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;Promise&lt;/a&gt;
so you need to handle how it resolves.&lt;/p&gt;
&lt;h2 id="code"&gt;Code &lt;a class="anchor-link" href="#code"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is written as a native ES2015 module, which means you may need to
transpile it depending on your browser support policy.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// ------------------------------------------------------ //&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Simple JavaScript API wrapper&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://muffinman.io/blog/simple-javascript-api-wrapper&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// ------------------------------------------------------ //&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// For demo purposes I&amp;#x27;m using this awesome Star Wars API&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token constant"&gt;API_URL&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;https://swapi.tech/api&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Custom API error to throw&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;ApiError&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;message&lt;span class="token punctuation"&gt;,&lt;/span&gt; data&lt;span class="token punctuation"&gt;,&lt;/span&gt; status&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;let&lt;/span&gt; response &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword null nil"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;let&lt;/span&gt; isObject &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;false&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// We are trying to parse response&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;try&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    response &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;JSON&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;parse&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;data&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    isObject &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;true&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;catch&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;e&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    response &lt;span class="token operator"&gt;=&lt;/span&gt; data&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;response&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; response&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;message&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; message&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; status&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method-variable function-variable method function property-access"&gt;toString&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token template-string"&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;message&lt;/span&gt; &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;\nResponse:\n&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; isObject &lt;span class="token operator"&gt;?&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;JSON&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;stringify&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;response&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token keyword null nil"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;2&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;response&lt;/span&gt; &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// API wrapper function&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token function-variable function"&gt;fetchResource&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;path&lt;span class="token punctuation"&gt;,&lt;/span&gt; userOptions &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Define default options&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; defaultOptions &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Define default headers&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; defaultHeaders &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; options &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Merge options&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token spread operator"&gt;...&lt;/span&gt;defaultOptions&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token spread operator"&gt;...&lt;/span&gt;userOptions&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Merge headers&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;headers&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token spread operator"&gt;...&lt;/span&gt;defaultHeaders&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token spread operator"&gt;...&lt;/span&gt;userOptions&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;headers&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Build Url&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; url &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token template-string"&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; &lt;span class="token constant"&gt;API_URL&lt;/span&gt; &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;/&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; path &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Detect is we are uploading a file&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; isFile &lt;span class="token operator"&gt;=&lt;/span&gt; options&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;body&lt;/span&gt; &lt;span class="token keyword"&gt;instanceof&lt;/span&gt; &lt;span class="token class-name"&gt;File&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Stringify JSON data&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// If body is not a file&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;options&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;body&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="token keyword"&gt;typeof&lt;/span&gt; options&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;body&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;object&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="token operator"&gt;!&lt;/span&gt;isFile&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    options&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;body&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;JSON&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;stringify&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;options&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;body&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Variable which will be used for storing response&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;let&lt;/span&gt; response &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword null nil"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token function"&gt;fetch&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;url&lt;span class="token punctuation"&gt;,&lt;/span&gt; options&lt;span class="token punctuation"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;then&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;responseObject&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Saving response for later use in lower scopes&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      response &lt;span class="token operator"&gt;=&lt;/span&gt; responseObject&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// HTTP unauthorized&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token number"&gt;401&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token comment"&gt;// Handle unauthorized requests&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token comment"&gt;// Maybe redirect to login page?&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Check for error HTTP error codes&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; &lt;span class="token number"&gt;200&lt;/span&gt; &lt;span class="token operator"&gt;||&lt;/span&gt; response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token operator"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="token number"&gt;300&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token comment"&gt;// Get response as text&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;text&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Get response as json&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;json&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// &amp;quot;parsedResponse&amp;quot; will be either text or javascript object depending if&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// &amp;quot;response.text()&amp;quot; or &amp;quot;response.json()&amp;quot; got called in the upper scope&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;then&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;parsedResponse&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Check for HTTP error codes&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; &lt;span class="token number"&gt;200&lt;/span&gt; &lt;span class="token operator"&gt;||&lt;/span&gt; response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token operator"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="token number"&gt;300&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token comment"&gt;// Throw error&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token keyword control-flow"&gt;throw&lt;/span&gt; parsedResponse&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Request succeeded&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; parsedResponse&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token keyword control-flow"&gt;catch&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;error&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Throw custom API error&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// If response exists it means HTTP error occured&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;response&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token keyword control-flow"&gt;throw&lt;/span&gt; &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;ApiError&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token template-string"&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;span class="token string"&gt;Request failed with status &lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt; &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;.&lt;/span&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; error&lt;span class="token punctuation"&gt;,&lt;/span&gt; response&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;status&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;else&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token keyword control-flow"&gt;throw&lt;/span&gt; &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;ApiError&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;error&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;toString&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token keyword null nil"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;REQUEST_FAILED&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;export&lt;/span&gt; &lt;span class="token keyword module"&gt;default&lt;/span&gt; fetchResource&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="usage"&gt;Usage &lt;a class="anchor-link" href="#usage"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;fetchResource&lt;/code&gt; accepts two arguments, mandatory URL and optional options to be passed to the &lt;code&gt;fetch&lt;/code&gt; request.
If you wrap each API request in a function with it&amp;#x27;s specific options it will be easier to maintain.&lt;/p&gt;
&lt;p&gt;Few examples:&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Simple get request&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;getUsers&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token function"&gt;fetchResource&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;users&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Post request with payload&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;signIn&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;username&lt;span class="token punctuation"&gt;,&lt;/span&gt; password&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token function"&gt;fetchResource&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;signin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;method&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;POST&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;body&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      username&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      password&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Put request, with file data and custom headers&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;uploadAvatar&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;userId&lt;span class="token punctuation"&gt;,&lt;/span&gt; file&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token function"&gt;fetchResource&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token template-string"&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;span class="token string"&gt;users/&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; userId &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;/avatar/&lt;/span&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;method&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;PUT&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;body&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; file&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;headers&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token string-property property"&gt;&amp;#x27;Content-Type&amp;#x27;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; file&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;type&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you call newly created API functions,
they will return a Promise, so you need to define &lt;code&gt;then&lt;/code&gt; (and &lt;code&gt;catch&lt;/code&gt; for errors).&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;getUsers&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;then&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;userData&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Do something with the &amp;quot;data&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token keyword control-flow"&gt;catch&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;error&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Handle error&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// error.message (error text)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// error.status (HTTTP status or &amp;#x27;REQUEST_FAILED&amp;#x27;)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// error.response (text, object or null)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="demo"&gt;Demo &lt;a class="anchor-link" href="#demo"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&amp;#x27;ve cooked a small demo to show it in practice, in which I used free &lt;a href="https://swapi.tech"&gt;Star Wars API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to play with it &lt;a href="https://codepen.io/stanko/pen/LOoPQp?editors=0110"&gt;on CodePen&lt;/a&gt;.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 06 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/simple-javascript-api-wrapper/</guid></item><item><title>Recurse Center 18: SQL joins</title><link>https://peterlyons.com/problog/2017/12/recurse-center-18-sql-joins/</link><description>&lt;p&gt;Today I mostly worked on some &lt;a href="https://pgexercises.com"&gt;pgexercises&lt;/a&gt;. I learned some good things and did some fairly complex joins but I still feel like I need a lot more practice with joins before I'll actually get that clear light bulb of understanding. Our study group met and reviewed some stuff and made plans. I was hoping to also do some web security capture the flag exercises AND make progress on tealeaves but didn't even come close to getting to either of those today.&lt;/p&gt;
&lt;p&gt;My general feeling is as per my focusaurus username, I do much better working on just 1 thing at a time and the past few days I've tried to sprinkle in some web security and SQL stuff and my main rust/tealeaves project basically came to a halt. I think mostly this is OK as I can work heads down alone on tealeaves when I get home but the other topics benefit a lot from working with my peers here. We'll see how I feel in another 2 days or so. I was casually hoping to have tealeaves be mostly working for modern ssh key formats by Thursday but it might not quite get there including CLI usability stuff.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 06 Dec 2017 01:37:08 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-18-sql-joins/</guid></item><item><title>How to use docker to run local databases</title><link>https://peterlyons.com/problog/2017/12/how-to-use-docker-to-run-local-databases/</link><description>&lt;p&gt;Here's how I run use docker to run databases for local development. I think my approach is the simplest I've seen and if something is unnecessary I skip it. You don't need data containers or port mappings, so I don't use them. The goal here is to make it very easy to run databases while developing applications or doing DB development work. It's basically the same for macOS and linux but I'm currently on macOS so that's where my instructions come from.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Same process works mostly the same for many databases (postgresql, mysql, mongodb, redis, etc)&lt;/li&gt;
&lt;li&gt;Data persists as expected&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Can start/stop containers, reboot host without losing data&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;When we want to wipe data and start fresh, that's easy too&lt;/li&gt;
&lt;li&gt;Easy to transfer files into the container and out of the container&lt;/li&gt;
&lt;li&gt;Easy to get a shell inside  the container to run tools there (psql etc)&lt;/li&gt;
&lt;li&gt;Easy to purge when done&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="my-approach"&gt;My Approach&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use a single docker-compose yaml file because 1 file is the easiest number of files to have&lt;/li&gt;
&lt;li&gt;Each database gets 2 volume mounts
&lt;ul&gt;
&lt;li&gt;1 for ad hoc file transfer
&lt;ul&gt;
&lt;li&gt;This is always &lt;code&gt;'~/docker-volumes/host:/host'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;1 for the database data itself
&lt;ul&gt;
&lt;li&gt;The left/host path follows the pattern &lt;code&gt;~/docker-volumes/container-name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the right/container path needs to match the path the container stores data by default. You'll need to look at the container's docs to find the correct path to use. I've provided correct values for some popular databases below.&lt;/li&gt;
&lt;li&gt;Look at &lt;a href="https://hub.docker.com"&gt;hub.docker.com&lt;/a&gt;, search for your DB container by name, then search in the page for &lt;code&gt;-v&lt;/code&gt; and you'll usually find it&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Databases run on their default port bound to loopback
&lt;ul&gt;
&lt;li&gt;Simplest thing. Least surprise.&lt;/li&gt;
&lt;li&gt;Also allows DB management GUIs to work easily.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If DB users are required, set their password to "password"
&lt;ul&gt;
&lt;li&gt;This is local stuff that does not need much security&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-compose-file"&gt;The compose file&lt;/h2&gt;
&lt;pre class="language-yaml "&gt;&lt;code class="language-yaml"&gt;# Run with:
# docker-compose -f ~&amp;#x2f;projects&amp;#x2f;dotfiles&amp;#x2f;docker-compose-local-dev.yml up -d
version: &amp;#x27;2&amp;#x27;
services:
  # https:&amp;#x2f;&amp;#x2f;hub.docker.com&amp;#x2f;_&amp;#x2f;postgres&amp;#x2f;
  postgres:
    container_name: &amp;#x27;postgres&amp;#x27;
    ports: [&amp;#x27;127.0.0.1:5432:5432&amp;#x27;]
    volumes: [
      # for ad-hoc transfers in&amp;#x2f;out of container
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;host:&amp;#x2f;host&amp;#x27;,
      # for DB data itself
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;postgres:&amp;#x2f;var&amp;#x2f;lib&amp;#x2f;postgresql&amp;#x2f;data&amp;#x27;
      ]
    image: &amp;#x27;postgres&amp;#x27;
    environment:
      POSTGRES_PASSWORD: &amp;#x27;password&amp;#x27;
      PGDATA: &amp;#x27;&amp;#x2f;var&amp;#x2f;lib&amp;#x2f;postgresql&amp;#x2f;data&amp;#x2f;pgdata&amp;#x27;
  mysql:
    container_name: &amp;#x27;mysql&amp;#x27;
    ports: [&amp;#x27;127.0.0.1:3306:3306&amp;#x27;]
    volumes: [
      # for ad-hoc transfers in&amp;#x2f;out of container
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;host:&amp;#x2f;host&amp;#x27;,
      # for DB data itself
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;mysql:&amp;#x2f;var&amp;#x2f;lib&amp;#x2f;mysql&amp;#x27;
      ]
    image: &amp;#x27;mysql&amp;#x27;
    environment:
      MYSQL_ROOT_PASSWORD: &amp;#x27;password&amp;#x27;
  mongo:
    container_name: &amp;#x27;mongo&amp;#x27;
    ports: [&amp;#x27;127.0.0.1:27017:27017&amp;#x27;]
    volumes: [
      # for ad-hoc transfers in&amp;#x2f;out of container
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;host:&amp;#x2f;host&amp;#x27;,
      # for DB data itself
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;mongo:&amp;#x2f;data&amp;#x2f;db&amp;#x27;
      ]
    image: &amp;#x27;mongo&amp;#x27;
  dynamodb:
   container_name: &amp;#x27;dynamodb&amp;#x27;
   ports: [&amp;#x27;127.0.0.1:8000:8000&amp;#x27;]
   volumes: [
        # for ad-hoc transfers in&amp;#x2f;out of container
        &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;host:&amp;#x2f;host&amp;#x27;,
        # for DB data itself
        &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;dynamodb:&amp;#x2f;var&amp;#x2f;dynamodb_local&amp;#x27;
        ]
   image: &amp;#x27;peopleperhour&amp;#x2f;dynamodb&amp;#x27;
  redis:
    container_name: &amp;#x27;redis&amp;#x27;
    ports: [&amp;#x27;127.0.0.1:6379:6379&amp;#x27;]
    volumes: [
      # for ad-hoc transfers in&amp;#x2f;out of container
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;host:&amp;#x2f;host&amp;#x27;,
      # for DB data itself
      &amp;#x27;~&amp;#x2f;docker-volumes&amp;#x2f;redis:&amp;#x2f;data&amp;#x27;
      ]
    image: &amp;#x27;redis&amp;#x27;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check the &lt;a href="https://github.com/focusaurus/dotfiles/blob/master/docker-compose-local-dev.yml"&gt;docker compose file in my github dotfiles repo&lt;/a&gt; for latest version.&lt;/p&gt;
&lt;h2 id="how-to-do-basic-operations"&gt;How to do basic operations&lt;/h2&gt;
&lt;p&gt;Commands are run from the host (macOS) terminal unless explicitly marked as run from within a container.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start everything: &lt;code&gt;docker-compose -f local-dev.yml up -d&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Stop everything: &lt;code&gt;docker-compose -f local-dev.yml down&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Start some DBs but not all: &lt;code&gt;docker-compose -f local-dev.yml up -d postgres mongo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Get a shell in the DB container: &lt;code&gt;docker exec -i -t postgres bash&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;From here you can run the DB repl in the container like &lt;code&gt;psql&lt;/code&gt;, &lt;code&gt;mongo&lt;/code&gt;, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Copy a file into the container: &lt;code&gt;cp some-file.sql ~/docker-volumes/host&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Read a file from within the DB container:
&lt;ul&gt;
&lt;li&gt;Get a shell: &lt;code&gt;docker exec -i -t postgres bash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Read the file (container shell): &lt;code&gt;more /host/some-file.sql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Copy a file from the container out to the host
&lt;ul&gt;
&lt;li&gt;Get a shell: &lt;code&gt;docker exec -i -t postgres bash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy (container shell): &lt;code&gt;cp /path/to/some/file /host&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Fully wipe the data and start over for one database
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker-compose -f local-dev.yml stop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rm -rf ~/docker-volumes/postgres &amp;amp;&amp;amp; mkdir ~/docker-volumes/postgres&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose -f local-dev.yml up -d postgres&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bonus-docker-shell-aliases"&gt;Bonus docker shell aliases&lt;/h2&gt;
&lt;p&gt;These may come in handy:&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;alias dcf=&amp;quot;docker-compose -f ~&amp;#x2f;projects&amp;#x2f;dotfiles&amp;#x2f;docker-compose-local-dev.yml&amp;quot;
alias dcup=&amp;quot;docker-compose -f ~&amp;#x2f;projects&amp;#x2f;dotfiles&amp;#x2f;docker-compose-local-dev.yml up -d&amp;quot;
alias deit=&amp;quot;docker exec --interactive --tty&amp;quot;
alias doco=&amp;quot;docker-compose&amp;quot;
alias dpa=&amp;quot;docker ps -a&amp;quot;
alias drit=&amp;#x27;docker run --rm --interactive --tty&amp;#x27;
&lt;/code&gt;&lt;/pre&gt;</description><author>Pete's Points</author><pubDate>Wed, 06 Dec 2017 01:25:41 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/how-to-use-docker-to-run-local-databases/</guid></item><item><title>My First Program</title><link>https://www.mikekasberg.com/blog/2017/12/04/my-first-program.html</link><description>&lt;p&gt;On the &lt;a href="https://stackoverflow.blog/podcasts/"&gt;StackOverflow Podcast&lt;/a&gt;, they
always ask their guests on the show how they got introduced to programming.
Whenever I listen to that segment of the podcast, I always think back to my
first experiences with programming, and how I built on those to get where I am
today. I like the podcast segment a lot, and I think it’s fun to share these
stories. So, in honor of &lt;a href="https://csedweek.org/"&gt;Computer Science Education
Week&lt;/a&gt;, I’m going to write a blog post about some of my
first programming experiences.&lt;/p&gt;

&lt;h2 id="learn-to-program-basic"&gt;Learn to Program BASIC&lt;/h2&gt;

&lt;p&gt;I always wanted to learn to program. From a pretty young age, I grasped the idea
that there were people out there who could make computers do whatever they
wanted them to. To me, this idea was enchanting. But I also realized that I had
&lt;em&gt;no idea&lt;/em&gt; how to do this, and didn’t really know anyone who did. I wanted to
learn to program, but didn’t know how to get started.&lt;/p&gt;

&lt;p&gt;I think I noticed &lt;em&gt;Learn to Program BASIC&lt;/em&gt; in the back of a Scholastic book
order. I convinced my mom to buy it for me. (After all, it &lt;em&gt;was&lt;/em&gt; educational
software.) &lt;em&gt;Learn to Program BASIC&lt;/em&gt; was essentially a series of video lessons
for the BASIC programming language.
The software also came with its own BASIC compiler and execution environment, so
it was relatively easy to write and run simple code. The first real program I
ever wrote would have been some kind of “Hello World” program in BASIC,
following one of the first lessons. (A video like &lt;a href="https://www.youtube.com/watch?v=uBYz9syhNAA"&gt;this
one&lt;/a&gt;. Wow, that’s so horrible. But
still, nostalgia…) Incredibly,
&lt;em&gt;Learn to Program BASIC&lt;/em&gt; still has a &lt;a href="https://www.amazon.com/Interplays-Learn-Program-Basic-Required/dp/B0048O15RG/ref=sr_1_1?ie=UTF8&amp;amp;qid=1512434786&amp;amp;sr=8-1&amp;amp;keywords=interplay+learn+to+program+basic"&gt;product page on
Amazon&lt;/a&gt;
(although it appears to be sold out).&lt;/p&gt;

&lt;p&gt;I worked through many of the lessons, but ultimately became frustrated. I could
write a lot of simple text-based programs (add two numbers, ask a user’s name,
etc), but never learned enough to create any kind of program on my own that wasn’t
text-based. Perhaps I was still too young to completely grasp some of the more
advanced concepts, but I don’t think I ever programmed anything really
interesting in BASIC. I wanted to learn how to write computer games with real
graphics, and my understanding of BASIC and the programming environment I was
working in wasn’t enough to let me do anything exciting. &lt;em&gt;Learn to Program
BASIC&lt;/em&gt; got me off to a great start, but also left me thirsty for more knowledge.&lt;/p&gt;

&lt;h2 id="game-maker"&gt;Game Maker&lt;/h2&gt;

&lt;p&gt;As I grew a little older, one of my primary motivations for wanting to
learn to program was to make computer games. Video games get expensive quickly,
and my childhood brain thought that if I simply wrote the game myself, I could play whatever I
wanted, essentially for free. My desire to write video games led me to an
application called &lt;a href="https://web.archive.org/web/20030623090955/http://gamemaker.nl:80/"&gt;&lt;em&gt;Game
Maker&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Game Maker&lt;/em&gt; was great software (for my 13 year old self), and I used it to make
a couple of games. Back in 2003, it was free. I remember that one of the games I
wrote was a type of “laser tag” game, where multiple players could play on the
same keyboard. One used WASD while the other used the arrow keys. Eventually, I
think I added a 3rd and 4th player using other keyboard keys, to get even more
friends in at once. Game maker produced a Windows executable (.exe) that I could
put on a floppy disk and share with friends. I was really proud of the game I
made, and learned a ton about programming in the process. It worked well, and
the games I made were actually fun to play for a while.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Game Maker&lt;/em&gt; is still available, although it’s changed a lot. It’s now sold as
&lt;a href="https://www.yoyogames.com/gamemaker"&gt;GameMaker Studio&lt;/a&gt; by YoYo Games.&lt;/p&gt;

&lt;h2 id="scratch"&gt;Scratch&lt;/h2&gt;

&lt;p&gt;Looking back on what I did with &lt;em&gt;Game Maker&lt;/em&gt;, it’s really similar to what many
kids are introduced to today with &lt;a href="https://scratch.mit.edu/"&gt;Scratch&lt;/a&gt;. &lt;em&gt;Game
Maker&lt;/em&gt; used it’s own programming language called GML (Game Maker Language).
Using GML, you could essentially program sprites to respond to events. The
language had simple commands (like move 10 left). Scratch is really the same
thing, but it runs in a web browser and you program with blocks. I like to
think that if I was a 10 year old today, I’d be learning to program by writing
games in Scratch. So it’s great to see it gaining popularity in elementary and
middle schools as an introduction to computer science.&lt;/p&gt;

&lt;h2 id="cs-education-week"&gt;CS Education Week&lt;/h2&gt;

&lt;p&gt;Computer Science Education Week is December 4-10, 2017. What are you doing this
week to support computer science education? I’ll be doing an &lt;a href="https://hourofcode.com/us"&gt;Hour of
Code&lt;/a&gt; later this week at an elementary school, where
I’ll be teaching one of &lt;a href="https://scratch.mit.edu/users/mkasberg/"&gt;my own
lessons&lt;/a&gt; in Scratch. I’ve written
several different games in Scratch over the last couple of years, primarily to
use as teaching material. These days, when I write a game in Scratch, I try to
keep the code (and the game) as simple as possible. My goal is to show the kids
I’m teaching that you can make something fun with code that’s simple and easy to
understand. I hope to write more about some of the Scratch lessons I’ve
developed in the near future.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Tue, 05 Dec 2017 04:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/12/04/my-first-program.html</guid></item><item><title>Recurse Center 17: ssh public keys</title><link>https://peterlyons.com/problog/2017/12/recurse-center-17-ssh-public-keys/</link><description>&lt;p&gt;This morning I paired on figuring out the structure of rsa private keys which was much easier since someone already wrote &lt;a href="https://etherhack.co.uk/asymmetric/docs/rsa_key_breakdown.html"&gt;detailed documentation&lt;/a&gt; with fabulous color-coded binary structures. So mostly we just needed to figure out specifically what is meant when someone says "this is a 1024-bit rsa key". The answer is it's the size of the &lt;em&gt;modulus&lt;/em&gt; field.&lt;/p&gt;
&lt;p&gt;Then we needed the rust code to parse it out, which we used the &lt;code&gt;yasna&lt;/code&gt; crate for. My pair had an excellent catch of the fact that we were getting an error due to "extra data at end of file" because we were only parsing the first few fields and ignore the rest which are uninteresting, but yasna expects you to fully parse the ASN.1 structure it seems.&lt;/p&gt;
&lt;p&gt;After that we dug into the public key formats which are generally smaller and simpler. I think I have ed25519 and rsa figured out and can confirm you can match corresponding private/public keys by a common value in the payload. Also you can detect trivial tampering of the algorithm label field as that data is duplicated in the base64 payload (which you could of course also tamper with).&lt;/p&gt;
&lt;p&gt;This afternoon there was a great web security presentation and a bunch of us will be doing a web security capture the flag exercise/contest this week. Looks fun but I think I'll have to time-box my effort as there are at least 48 vulnerabilities to be found and it's mostly unaided discovery of them.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Tue, 05 Dec 2017 03:48:47 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-17-ssh-public-keys/</guid></item><item><title>searchcode plexus</title><link>https://boyter.org/2017/12/searchcode-plexus/</link><description>&lt;h3 id="plexus-a-combination-of-interlaced-parts-a-network"&gt;Plexus &amp;ldquo;A combination of interlaced parts; a network.&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;For a while I have been neglecting searchcode.com while working on searchcode server. This is of course not an ideal situation and as such I have started working on it again. The following is just a brief list of things I am considering, problems, issues etc…&lt;/p&gt;
&lt;p&gt;So back when I first started working on searchcode I wrote it using PHP. For searchcode next (the current version) I rewrote it using Python and Django. I had intented to continue using this stack for the forseeable future when I chose it. I quite like writing Python code and at the time the performance was acceptable. When I started writing searchcode server however I wanted to make it as easy to install as possible. The reason being that I considered it a competitive advantage to have users installing searchcode without any pain and be off and running. At the time I considered writing it in Go or Rust but had little experience with either language. I decided to pull on my sensible pants and chose Java which is a language I had worked with before and had excellent library support. With the 8th version Java had become considerably less painful to work with.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 05 Dec 2017 03:12:02 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/12/searchcode-plexus/</guid></item><item><title>Links - December 5th, 2017</title><link>https://faingezicht.com/links/2017/12/05/links/</link><description>This is another crypto heavy post with plenty of the links in some way discussing crypto assets, but bear with me: there's other good stuff to read, too.</description><author>Avy Faingezicht</author><pubDate>Tue, 05 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/12/05/links/</guid></item><item><title>An introduction to Ada's simple numeric types</title><link>https://www.jviotti.com/2017/12/05/an-introduction-to-adas-simple-numeric-types.html</link><description>This article introduces the numeric types available in Ada 2012</description><author>Juan Cruz Viotti</author><pubDate>Tue, 05 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.jviotti.com/2017/12/05/an-introduction-to-adas-simple-numeric-types.html</guid></item><item><title>December 2017 Projects</title><link>https://venam.net/blog/programming/2017/12/05/december-projects.html</link><description>Five months have past since my last post about personal projects and endeavours but it feels like I've been stagnating for much longer.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Tue, 05 Dec 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/programming/2017/12/05/december-projects.html</guid></item><item><title>The Empire of Oil</title><link>https://rybakov.com/blog/empire-of-oil/</link><description>&lt;p&gt;&lt;a href="http://www.costacompagnie.org/en/"&gt;Costa Compagnie&lt;/a&gt; was preparing the &lt;em&gt;Empire of Oil&lt;/em&gt; 360° movie to show at Ballhaus Ost in Berlin.&lt;/p&gt;
&lt;p&gt;Two days before the premiere:&lt;/p&gt;
&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/ballhauspano2.gif" /&gt;




&lt;/figure&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Mon, 04 Dec 2017 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/empire-of-oil/</guid></item><item><title>Submission Date vs Activity Date</title><link>https://blog.harterrt.com/dates.html</link><description>&lt;p&gt;My comments on
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1422892"&gt;Bug 1422892&lt;/a&gt;
started to get long,
so I started untangling my thoughts here.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;From
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1422892"&gt;the bug&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We experimented with using &lt;code&gt;activity_date&lt;/code&gt; instead of &lt;code&gt;submission_date&lt;/code&gt;
when developing the &lt;code&gt;clients_daily&lt;/code&gt; etl job.
We should summarize our findings and decide on 
which of these measures we'd like to standardize against …&lt;/p&gt;&lt;/blockquote&gt;</description><author>blog.harterrt.com</author><pubDate>Mon, 04 Dec 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/dates.html</guid></item><item><title>5000 concepts for Europe: a book proposal</title><link>https://stop.zona-m.net/2017/12/5000-concepts-for-europe-a-book-proposal/</link><description>&lt;p&gt;Thirty years ago (*) a Mr E. D. Hirsch Jr. wrote a book titled &lt;a href="https://books.google.it/books?id=e6tiAQAACAAJ&amp;amp;dq=%E2%80%9CCultural+Literacy:+What+Every+American+Needs+to+Know%E2%80%9D&amp;amp;hl=it&amp;amp;sa=X&amp;amp;ved=0ahUKEwihs5PcsPDXAhVDOBQKHV6UDQkQ6AEIMzAB"&gt;&amp;ldquo;Cultural Literacy: What Every American Needs to Know&amp;rdquo;&lt;/a&gt;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 04 Dec 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/12/5000-concepts-for-europe-a-book-proposal/</guid></item><item><title>Frequently Answered Questions about: 5000 concepts for Europe</title><link>https://stop.zona-m.net/5000-concepts-faq/</link><description>&lt;p&gt;These are the Frequently Answered Questions for the book project &lt;a href="https://stop.zona-m.net/2017/12/5000-concepts-for-europe-a-book-proposal/"&gt;5000 concepts for Europe&lt;/a&gt;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 04 Dec 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/5000-concepts-faq/</guid></item><item><title>Flutter for React Native Devs in 30 Seconds</title><link>https://www.swyx.io/flutter-for-react-native-devs-in-30-seconds-78g</link><description>You may have heard of Flutter, Google's answer to React Native. What should you know?</description><author>swyx's site RSS Feed</author><pubDate>Sun, 03 Dec 2017 18:06:18 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/flutter-for-react-native-devs-in-30-seconds-78g</guid></item><item><title>The Leftovers: Season 3</title><link>https://olshansky.info/tv/the_leftovers_season_3/</link><description>Olshansky's review of The Leftovers: Season 3</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 03 Dec 2017 11:36:12 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/the_leftovers_season_3/</guid></item><item><title>Aventador Renders Revisited</title><link>https://blog.yiningkarlli.com/2017/12/lambo-renders-revisited.html</link><description>&lt;p&gt;A long time ago, I made &lt;a href="http://blog.yiningkarlli.com/2013/03/stratified-versus-uniform-sampling.html"&gt;some&lt;/a&gt; &lt;a href="http://blog.yiningkarlli.com/2013/03/first-progress-on-new-pathtracing-core.html"&gt;posts&lt;/a&gt; that featured a cool Lamborghini Aventador model.
Recently, I revisited that model and made some new renders using the current version of Takua, mostly just for fun.
To me, one of the most important parts of writing a renderer has always been being able to actually use the renderer to make fun images.
The last time I rendered this model was something like four years ago, and back then Takua was still in a very basic state; the renders in those old posts don’t even have any shading beyond 50% grey lambertian surfaces!
The renders in this post utilize a lot of advanced features that I’ve added since then, such as a proper complex layered Bsdf and texturing system, advanced bidirectional light transport techniques, huge speed improvements to ray traversal, advanced motion blur and generalized time capabilities, and more.
I’m way behind in writing up many of these features and capabilities, but in the meantime, I thought I’d post some for-fun rendering projects I’ve done with Takua.&lt;/p&gt;

&lt;p&gt;All of the renders in this post are directly from Takua, with a basic white balance and conversion from HDR EXR to LDR PNG being the only post-processing steps.
Each render took about half a day to render (except for the wireframe render, which was much faster) on a 12-core workstation at 2560x1440 resolution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Dec/lambo_orangered.png"&gt;&lt;img alt="Figure 1: An orange-red Lamborghini Aventador, rendered in Takua a0.7 using VCM." src="https://blog.yiningkarlli.com/content/images/2017/Dec/preview/lambo_orangered.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shading the Aventador model was a fun, interesting exercise.
I went for a orange-red paint scheme since, well, Lamborghinis are supposed to look outrageous and orange-red is a fairly exotic paint scheme (I suppose I could have picked green or yellow or something instead, but I like orange-red).
I ended up making a triple-lobe shader with a metallic base, a dielectric lobe, and a clear-coat lobe on top of that. 
The base lobe uses a GGX microfacet metallic Brdf.
Takua’s shading system implements a proper metallic Fresnel model for conductors, where the Fresnel model includes both a &lt;em&gt;Nd&lt;/em&gt; component representing refractive index and a &lt;em&gt;k&lt;/em&gt; component representing the extinction coefficient for when an electromagnetic wave propagates through a material.
For conductors, the final Fresnel index of refraction for each wavelength of light is defined by a complex combination of &lt;em&gt;Nd&lt;/em&gt; and &lt;em&gt;k&lt;/em&gt;.
For the base metallic lobe, most of the color wound up coming from the &lt;em&gt;k&lt;/em&gt; component.
The dielectric lobe is meant to simulate paint on top of a car’s metal body; the dielectric lobe is where most of the orange-red color comes from.
The dielectric lobe is again a GGX microfacet Brdf, but with a dielectric Fresnel model, which has a much simpler index of refraction calculation than the metallic Fresnel model does.
I should note that Takua’s current standard material implementation actually only supports a single primary specular lobe and an additional single clear-coat lobe, so for shaders authored with both a metallic and dielectric component, Takua takes a blend weight between the two components and for each shading evaluation stochastically selects between the two lobes according to the blend weight.
The clear-coat layer on top has just a slightly amount of extinction to provide just a bit more of the final orange look, but is mostly just clear.&lt;/p&gt;

&lt;p&gt;All of the window glass in the render is tinted slightly dark through extinction instead of through a fixed refraction color.
Using proper extinction to tint glass is more realistic than using a fixed refraction color.
Similarly, the red and yellow glass used in the head lights and tail lights are colored through extinction.
The brake disks use an extremely high resolution bump map to get the brushed metal look.
The branding and markings on the tire walls are done through a combination of bump mapping and adjusting the roughness of the microfacet Brdf; the tire treads are made using a high resolution normal map.
There’s no &lt;a href="http://blog.yiningkarlli.com/2017/05/subdivision-and-displacement.html"&gt;displacement mapping&lt;/a&gt; at all, although in retrospect the tire treads probably should be displacement mapped if I want to put the camera closer to them.
Also, I actually didn’t really shade the interior of the car much, since I knew I was going for exterior shots only.&lt;/p&gt;

&lt;p&gt;Eventually I’ll get around to implementing a proper car paint Bsdf in Takua, but until then, the approach I took here seems to hold up reasonable well as long as the camera doesn’t get super close up to the car.&lt;/p&gt;

&lt;p&gt;I lit the scene using two lights: an HDR skydome from &lt;a href="http://hdri-skies.com"&gt;HDRI-Skies&lt;/a&gt;, and a single long, thin rectangular area light above the car.
The skydome provides the overall soft-ish lighting that illuminates the entire scene, and the rectangular area light provides the long, interesting highlights on the car body that help with bringing out the car’s shape.&lt;/p&gt;

&lt;p&gt;For all of the renders in this post, I used my VCM integrator, since the scene contains a lot of subtle caustics and since the inside of the car is lit entirely through glass.
I also wound up modifying my &lt;a href="http://blog.yiningkarlli.com/2015/03/adaptive-sampling.html"&gt;adaptive sampler&lt;/a&gt;; it’s still the same adaptive sampler that I’ve had for a few years now, but with an important extension.
Instead of simply reducing the total number of paths per iteration as areas reach convergence, the adaptive sampler now keeps the number of paths the same and instead reallocates paths from completed pixels to high-variance pixels.
The end result is that the adaptive sampler is now much more effective at eliminating fireflies and targeting caustics and other noisy areas.
In the above render, some pixels wound up with as few as 512 samples, while a few particularly difficult pixels finished with as many as 20000 samples.
Here is the adaptive sampling heatmap for Figure 1 above; brighter areas indicate more samples. Note how the adaptive sampler found a number of areas that we’d expect to be challenging, such as the interior through the car’s glass windows, and parts of the body with specular inter-reflections.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Dec/lambo_sampleMask.png"&gt;&lt;img alt="Figure 2: Adaptive sampling heatmap for Figure 1. Brighter areas indicate more samples." src="https://blog.yiningkarlli.com/content/images/2017/Dec/preview/lambo_sampleMask.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently implemented support for arbitrary camera shutter curves, so I thought doing a motion blurred render would be fun.
After all, Lamborghinis are supposed to go fast!
I animated the Lamborghini driving forward in Maya; the animation was very basic, with the main body just translating forward and the wheels both translating and rotating.
Of course Takua has proper rotational motion blur.
The motion blur here is effectively multi-segment motion blur; generating multi-segment motion blur from an animated sequence in Takua is very easy due to how Takua handles and understands time.
I actually think that Takua’s concept of time is one of the most unique things in Takua; it’s very different from how every other renderer I’ve used and seen handles time.
I intend to write more about this later.
Instead of an instantaneous shutter, I used a custom cosine-based shutter curve that places many more time samples near the center of the shutter interval than towards the shutter open and close.
Using a shutter shape like this wound up being important to getting the right look to the motion blur; even the car is moving extremely quickly, the overall form of the car is still clearly distinguishable and the front and back of the car appear more motion-blurred than the main body.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Dec/lambo_orangered_motionblur.png"&gt;&lt;img alt="Figure 3: Motion blurred render, using multi-segment motion blur with a cosine-based shutter curve." src="https://blog.yiningkarlli.com/content/images/2017/Dec/preview/lambo_orangered_motionblur.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since Takua has a procedural wireframe texture now, I also did a wireframe render.
I mentioned my procedural wireframe texture in a previous post, but I didn’t write about how it actually works.
For triangles and quads, the wireframe texture is simply based on the distance from the hitpoint to the nearest edge.
If the distance to the nearest edge is smaller than some threshold, draw one color, otherwise, draw some other color.
The nearest edge calculation can be done as follows (the variable names should be self-explanatory):&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;float calculateMinDistance(const Poly&amp;amp; p, const Intersection&amp;amp; hit) const {
    float md = std::numeric_limits&amp;lt;float&amp;gt;::infinity();
    const int verts = p.isQuad() ? 4 : 3;
    for (int i = 0; i &amp;lt; verts; i++) {
        const glm::vec3&amp;amp; cur = p[i].m_position;
        const glm::vec3&amp;amp; next = p[(i + 1) % verts].m_position;
        const glm::vec3 d1 = glm::normalize(next - cur);
        const glm::vec3 d2 = hit.m_point - cur;
        const float l = glm::length((cur + d1 * glm::dot(d1, d2) - hit.m_point));
        md = glm::min(md, l * l);
    }
    return md;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The topology of the meshes are pretty strange, since the car model came as a triangle mesh, which I then subdivided:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Dec/lambo_wireframe.png"&gt;&lt;img alt="Figure 4: Procedural wireframe texture." src="https://blog.yiningkarlli.com/content/images/2017/Dec/preview/lambo_wireframe.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The material in the wireframe render only uses the lambertian diffuse lobe in Takua’s standard material; as such, the adaptive sampling heatmap for the wireframe render is interesting to compare to Figure 2.
Overall the sample distribution is much more even, and areas where diffuse inter-reflections are present got more samples:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Dec/lambo_wireframe_sampleMask.png"&gt;&lt;img alt="Figure 5: Adaptive sampling heatmap for Figure 4. Brighter areas indicate more samples. Compare with Figure 2." src="https://blog.yiningkarlli.com/content/images/2017/Dec/preview/lambo_wireframe_sampleMask.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Takua’s shading model supports layering different materials through parameter blending, similar to how the &lt;a href="https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf"&gt;Disney Brdf&lt;/a&gt; (and, at this point, &lt;a href="http://blog.selfshadow.com/publications/s2017-shading-course/walster/s2017_pbs_volumetric_notes.pdf"&gt;most&lt;/a&gt; &lt;a href="http://blog.selfshadow.com/publications/s2017-shading-course/dreamworks/s2017_pbs_dreamworks_notes.pdf"&gt;other&lt;/a&gt; &lt;a href="http://blog.selfshadow.com/publications/s2017-shading-course/pixar/s2017_pbs_pixar_notes.pdf"&gt;shading&lt;/a&gt; &lt;a href="http://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides.pdf"&gt;systems&lt;/a&gt;) handles material layering.
I wanted to make an even more outrageous looking version of the Aventador than the orange-red version, so I used the procedural wireframe texture as a layer mask to drive parameter blending between a black paint and a metallic gold paint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Dec/lambo_gold.png"&gt;&lt;img alt="Figure 6: An outrageous Aventador paint scheme using a procedural wireframe texture to blend between black and metallic gold car paint." src="https://blog.yiningkarlli.com/content/images/2017/Dec/preview/lambo_gold.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Sun, 03 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2017/12/lambo-renders-revisited.html</guid></item><item><title>Rocket - A Rust game running on WASM</title><link>https://ochagavia.nl/blog/rocket-a-rust-game-running-on-wasm/</link><description>Two weeks ago, Alex Crichton&amp;rsquo;s PR adding a target for WebAssembly to the Rust compiler was merged. There are many differences between this target and the Emscripten one, but the important one for me is that it doesn&amp;rsquo;t depend on external stuff like the Emscripten SDK (which IIRC used to be a pain to get working on Windows, but seems to be better now).
After seeing the examples on hellorust.com, I thought it would be interesting to try to adapt my game Rocket to work on the browser through the wasm32-unknown-unknown target.</description><author>Consulting on Adolfo Ochagavía</author><pubDate>Sun, 03 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ochagavia.nl/blog/rocket-a-rust-game-running-on-wasm/</guid></item><item><title>Serverless Machine Learning at Google</title><link>https://www.swyx.io/serverless-machine-learning-at-google-cp9</link><description>---</description><author>swyx's site RSS Feed</author><pubDate>Sun, 03 Dec 2017 00:25:33 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/serverless-machine-learning-at-google-cp9</guid></item><item><title>Are we human? Or are we reCAPTCHA?</title><link>https://www.swyx.io/are-we-human-or-are-we-recaptcha-blm</link><description>---</description><author>swyx's site RSS Feed</author><pubDate>Sat, 02 Dec 2017 23:49:06 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/are-we-human-or-are-we-recaptcha-blm</guid></item><item><title>Firebase Analytics in 30 Seconds</title><link>https://www.swyx.io/firebase-analytics-in-30-seconds-6pp</link><description>---</description><author>swyx's site RSS Feed</author><pubDate>Sat, 02 Dec 2017 22:57:12 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/firebase-analytics-in-30-seconds-6pp</guid></item><item><title>Medical Machine Learning in 30 Seconds</title><link>https://www.swyx.io/medical-machine-learning-in-30-seconds-dh1</link><description>---</description><author>swyx's site RSS Feed</author><pubDate>Sat, 02 Dec 2017 18:41:14 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/medical-machine-learning-in-30-seconds-dh1</guid></item><item><title>React Window decorators</title><link>https://muffinman.io/blog/react-decorators-and-scroll-manager/</link><description>&lt;article class="article"&gt;&lt;p&gt;Two days ago I released two npm packages,
&lt;a href="https://www.npmjs.com/package/window-scroll-manager"&gt;window-scroll-manager&lt;/a&gt; and
&lt;a href="https://www.npmjs.com/package/react-window-decorators"&gt;react-window-decorators&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="scroll-manager"&gt;Scroll manager &lt;a class="anchor-link" href="#scroll-manager"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span class="sidenote__text" tabindex="0"&gt;Scroll manager&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;&lt;a href="https://muffinman.io/react-plx/"&gt;Plx&lt;/a&gt; uses the
same scroll manager so I extracted it to the standalone package.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
is just a simple wrapper around scroll event, that broadcasts custom
&lt;code&gt;window-scroll&lt;/code&gt; event once per &lt;code&gt;requestAnimationFrame&lt;/code&gt;.
Idea comes from &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Events/scroll#Example"&gt;MDN&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="react-decorators"&gt;React decorators &lt;a class="anchor-link" href="#react-decorators"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;or higher order components are the bees knees,
as they bring easy way to track window scroll and resize events in React.
They will track and inject props directly into React components.
Check the &lt;a href="https://muffinman.io/react-window-decorators/"&gt;demo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Two decorators included are:&lt;/p&gt;
&lt;h3 id="withscroll-decorator"&gt;withScroll decorator &lt;a class="anchor-link" href="#withscroll-decorator"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;tracks and injects window scroll position (by using scroll manager)&lt;/p&gt;
&lt;h3 id="withwindow-decorator"&gt;withWindow decorator &lt;a class="anchor-link" href="#withwindow-decorator"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;tracks and injects window size, orientation and
&lt;span class="sidenote__text" tabindex="0"&gt;breakpoint&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;User needs to pass breakpoints definition.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="how-do-they-work"&gt;How do they work? &lt;a class="anchor-link" href="#how-do-they-work"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both scroll and resize decorators are listening to custom events,
rather than the native ones. This is because both
&lt;span class="sidenote__text" tabindex="0"&gt;&lt;code&gt;scroll&lt;/code&gt; and &lt;code&gt;resize&lt;/code&gt; events&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Especially scroll event.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
are triggered a lot and can cause performance issues.&lt;/p&gt;
&lt;p&gt;That&amp;#x27;s why I introduced custom &lt;code&gt;window-scroll&lt;/code&gt; and &lt;code&gt;window-resize&lt;/code&gt; events.
Plus, all updates are wrapped in &lt;code&gt;requestAnimationFrame&lt;/code&gt; and resize event is
debounced (configurable, 250ms by default).&lt;/p&gt;
&lt;p&gt;So the heavy lifting is done by scroll and window managers, which are both singletons,
while the React decorators are slim components that inject props to the wrapped component.&lt;/p&gt;
&lt;p&gt;Please note that using &lt;code&gt;withScroll&lt;/code&gt; on a lot of components
can introduce performance issues. Then again ten-ish should work just fine.
I used these on numerous projects, they are battle tested, but it took me
some time to put in the effort to release them as a standalone package.&lt;/p&gt;
&lt;h2 id="check-the-code"&gt;Check the code &lt;a class="anchor-link" href="#check-the-code"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Of course, both packages are available on GitHub:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Stanko/window-scroll-manager"&gt;Scroll manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Stanko/react-window-decorators"&gt;React decorators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sat, 02 Dec 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-decorators-and-scroll-manager/</guid></item><item><title>Recurse Center 16: tealeaves is useful</title><link>https://peterlyons.com/problog/2017/12/recurse-center-16-tealeaves-is-useful/</link><description>&lt;p&gt;Today I refactored all my various scratch iterations of code to dig into the details of an ed25519 openssh private key file and integrated that into the main &lt;code&gt;tealeaves&lt;/code&gt; executable file. I added some unit tests for edge cases and I've so far been pleased with how unit testing is in rust. The cargo command line is weird for testing: I often have to do something like &lt;code&gt;RUST_BACKTRACE=1 cargo test --jobs=1 long_field -- --nocapture&lt;/code&gt; to try to debug which seems silly.&lt;/p&gt;
&lt;p&gt;But basically I can run tealeaves now on my &lt;code&gt;~/.ssh&lt;/code&gt; and it prints and accurate and useful description of what each file is.&lt;/p&gt;
&lt;p&gt;There's also now a SQL study group happening so I'll be spending some time on that which was my minor project for RC which I have yet to actually spend any time on.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 02 Dec 2017 00:53:15 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/recurse-center-16-tealeaves-is-useful/</guid></item><item><title>Tip: Array.from</title><link>https://qubyte.codes/blog/tip-arrayfrom</link><description>&lt;p&gt;SPOILER ALERT: If you're doing the advent of code this year, you may not want to
read onward. This post &lt;em&gt;does not&lt;/em&gt; give any solutions away, but does contain
information about how I approached a part of the first challenge.&lt;/p&gt;
&lt;p&gt;Onward!&lt;/p&gt;
&lt;p&gt;Today I started doing the &lt;a href="https://adventofcode.com"&gt;2017 advent of code&lt;/a&gt; challenges (don't worry, I
won't give solutions away). The first challenge involves summing numbers in a
sequence. The sequence itself is too long to express as an integer, and that
wouldn't be particularly useful for the task anyway. The most convenient form
is probably an array of integers. The sequence is given as raw text, and the
quickest way to get it into JS is as a string.&lt;/p&gt;
&lt;p&gt;There are a few ways to do this which spring to mind. One might argue that you
can loop directly over a string anyway, but getting a list of integers avoids
parsing each character in the string more than once for these tasks, so let's
ignore that option.&lt;/p&gt;
&lt;p&gt;The first thing to come to mind was a loop:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; numbers = [];

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;let&lt;/span&gt; i = &lt;span class="hljs-number"&gt;0&lt;/span&gt;; i &amp;lt; sequence.&lt;span class="hljs-property"&gt;length&lt;/span&gt;; i++) {
  numbers.&lt;span class="hljs-title function_"&gt;push&lt;/span&gt;(&lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(sequence[i], &lt;span class="hljs-number"&gt;10&lt;/span&gt;));
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There's a slightly nicer to read version of this introduced by ES2015:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; numbers = [];

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; character &lt;span class="hljs-keyword"&gt;of&lt;/span&gt; sequence) {
  numbers.&lt;span class="hljs-title function_"&gt;push&lt;/span&gt;(&lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(character, &lt;span class="hljs-number"&gt;10&lt;/span&gt;));
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Both suffer from being a bit bulky though. ES2015 also introduced
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from"&gt;&lt;code&gt;Array.from&lt;/code&gt;&lt;/a&gt; and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator"&gt;spread operator (&lt;code&gt;...&lt;/code&gt;)&lt;/a&gt;, which offer a similar
way of creating an array when used in combination with &lt;code&gt;Array.prototype.map&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; numbers = [...sequence].&lt;span class="hljs-title function_"&gt;map&lt;/span&gt;(&lt;span class="hljs-function"&gt;&lt;span class="hljs-params"&gt;char&lt;/span&gt; =&amp;gt;&lt;/span&gt; &lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(char, &lt;span class="hljs-number"&gt;10&lt;/span&gt;));
&lt;span class="hljs-comment"&gt;// or&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; numbers = &lt;span class="hljs-title class_"&gt;Array&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;from&lt;/span&gt;(sequence).&lt;span class="hljs-title function_"&gt;map&lt;/span&gt;(&lt;span class="hljs-function"&gt;&lt;span class="hljs-params"&gt;char&lt;/span&gt; =&amp;gt;&lt;/span&gt; &lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(char, &lt;span class="hljs-number"&gt;10&lt;/span&gt;));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The first spreads characters from the sequence into an array, and maps these
characters to a fresh array of numbers. The second uses &lt;code&gt;Array.from&lt;/code&gt; to get an
array of characters from a string, and uses the same mapping to get an array
of integers.&lt;/p&gt;
&lt;p&gt;I prefer the latter of the two (it's a little easier for humans to parse). It
would be nice to avoid the explicit mapping though, right? The solution I
settled upon was to use the little-known second parameter to &lt;code&gt;Array.from&lt;/code&gt;. It
turns out you can include a function to map elements to be inserted into the
returned array:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; numbers = &lt;span class="hljs-title class_"&gt;Array&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;from&lt;/span&gt;(sequence, &lt;span class="hljs-function"&gt;&lt;span class="hljs-params"&gt;char&lt;/span&gt; =&amp;gt;&lt;/span&gt; &lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(char, &lt;span class="hljs-number"&gt;10&lt;/span&gt;));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which is my tip! In essence, don't do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;[...stuff].&lt;span class="hljs-title function_"&gt;map&lt;/span&gt;(func);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-title class_"&gt;Array&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;from&lt;/span&gt;(stuff).&lt;span class="hljs-title function_"&gt;map&lt;/span&gt;(func);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-title class_"&gt;Array&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;from&lt;/span&gt;(stuff, func);
&lt;/code&gt;&lt;/pre&gt;</description><author>Qubyte Codes</author><pubDate>Fri, 01 Dec 2017 22:00:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/tip-arrayfrom</guid></item><item><title>Becoming Your Future Self</title><link>https://www.codingvc.com/p/becoming-your-future-self</link><description>In my five years as a VC, I&amp;#8217;ve worked closely with the founders of 50+ companies.</description><author>Coding VC</author><pubDate>Fri, 01 Dec 2017 18:50:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/becoming-your-future-self</guid></item><item><title>OpenSSH ed25519 private key file format</title><link>https://peterlyons.com/problog/2017/12/openssh-ed25519-private-key-file-format/</link><description>&lt;p&gt;Today I finished understanding the openssh private key format for ed25519 keys. Yesterday's analysis had a few remaining mysteries that a fellow RCer helped me solve plus a pair of mistakes that threw off some fields. So here for the record is a "complete" byte-by-byte analysis of what's inside an openssh ed25519 private key (both with and without a passphrase). This was done with OpenSSH_7.5p1, LibreSSL 2.5.4 on macOS 10.13. I say "complete" in quotes because you could go one layer deeper into the actual key payloads but for our purposes those details don't have specific meaning.&lt;/p&gt;
&lt;p&gt;First, let's generate a test keypair (hit ENTER for no passphrase when prompted):&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;mkdir &amp;#x2f;tmp&amp;#x2f;test-keys
cd &amp;#x2f;tmp&amp;#x2f;test-keys
ssh-keygen -t ed25519 -f ssh-ed25519-private-key.pem
Generating public&amp;#x2f;private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ssh-ed25519-private-key.pem.
Your public key has been saved in ssh-ed25519-private-key.pem.pub.
The key fingerprint is:
SHA256:qXcj+K4QZHxJ712c&amp;#x2f;M1PPutkyxT&amp;#x2f;Hn+1RKBIHLlypY4 plyons@avi
The key&amp;#x27;s randomart image is:
+--[ED25519256]--+
|      . ..o      |
|   . . o + + o   |
|    + o o = * .  |
|   o . o B o . + |
|    .   S .   o.+|
|     . E .     +=|
|    . o o o   .**|
|     . o o .  =.O|
|      .oo     .*=|
+----[SHA256]-----+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let's get at those tasty bytes of payload as a hex dump:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;grep -v - ssh-ed25519-private-key.pem | base64 -D | xxd -p                  
6f70656e7373682d6b65792d763100000000046e6f6e65000000046e6f6e
650000000000000001000000330000000b7373682d656432353531390000
00203cfe2afb025f46582e502b97f7dfa5a08dea09f87abfa8d5bfcaabf2
9fbb369500000090a2224bbaa2224bba0000000b7373682d656432353531
39000000203cfe2afb025f46582e502b97f7dfa5a08dea09f87abfa8d5bf
caabf29fbb36950000004002a1965d1a2684d50d29f2be0efd8e2fae3c5b
b013d06f7818416333955271a53cfe2afb025f46582e502b97f7dfa5a08d
ea09f87abfa8d5bfcaabf29fbb36950000000a706c796f6e734061766901
0203
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK here's how it breaks down.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# ASCII magic &amp;quot;openssh-key-v1&amp;quot; plus null byte
6f70656e7373682d6b65792d7631 00
00000004 int length = 4
6e6f6e65 string cipher = none
00000004 int length = 4
6e6f6e65 string kdfname = none
00000000 int length = 0
# zero-length kdfoptions placeholder here
00000001 int number of public keys = 1
00000033 int length first public key = 51 (4 + 11 + 4 + 32)
0000000b int length = 11
7373682d65643235353139 string key type = ssh-ed25519
00000020 int length = 32
# public key payload 32 bytes
# probably encoding a point on the ed25519 curve
3cfe2afb025f46582e502b97f7dfa5a0
8dea09f87abfa8d5bfcaabf29fbb3695

00000090 int length = 144 size of remaining payload
# 8 + 4 + 11 + 4 + 32 + 4 + 64 + 4 + 10 + 3
a2224bbaa2224bba iv&amp;#x2f;salt? (Not sure about these 8 bytes)

# Here&amp;#x27;s a repeat of the public key (part of the private key pair)
0000000b int length = 11
7373682d656432353531 39 string key type = ssh-ed25519
00000020  int length = 32
# public key payload 32 bytes
# probably encoding a point on the ed25519 curve
3cfe2afb025f46582e502b97f7dfa5a0
8dea09f87abfa8d5bfcaabf29fbb3695

00000040 int length = 64
# 32 bytes private key payload 1
02a1965d1a2684d50d29f2be0efd8e2f
ae3c5bb013d06f7818416333955271a5
# 32 bytes is the public&amp;#x2f;point again
3cfe2afb025f46582e502b97f7dfa5a0
8dea09f87abfa8d5bfcaabf29fbb3695

0000000a int length = 10
706c796f6e7340617669 private key payload 2
010203 padding 3 bytes incrementing integers
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let's generate one and encrypt with a passphrase&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-keygen -t ed25519 -f ssh-ed25519-passphrase-private-key.pem
Generating public&amp;#x2f;private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ssh-ed25519-passphrase-private-key.pem.
Your public key has been saved in ssh-ed25519-passphrase-private-key.pem.pub.
The key fingerprint is:
SHA256:QfPM5uIVVM6yT5sXeCvSjETCcP5zmTH+Rt7wY&amp;#x2f;91Ik8 plyons@avi
The key&amp;#x27;s randomart image is:
+--[ED25519256]--+
|      . + ...    |
|       * * o     |
|        = O =    |
|         B = *   |
|        S B B =  |
|       . + O B * |
|        . o O Eo=|
|           . B..=|
|              . +|
+----[SHA256]-----+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the dump&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;grep -v - ssh-ed25519-passphrase-private-key.pem | base64 -D | xxd -p
6f70656e7373682d6b65792d7631000000000a6165733235362d63626300
0000066263727970740000001800000010d08f6b8fd17593f246db4ac6c4
5a11930000001000000001000000330000000b7373682d65643235353139
0000002062837be86c63712896b8e0e7543e367c3abd0c0b5ad3e764ea0e
4f8ddd7d00ef000000901e60c56ef30d0ff02e07b57bf14645076c32c86c
88ecad545ca28424e4739aff5895bebd6778e70b6c54b309b9fdb0c94102
bf8cef5b97d3d75636967e67e4b9c1ee72ae81074b0ce0f7e540e051d569
05da263af3e383342cc75b3145242abb75257586a119c9d3673dfb7eabe4
696350904e7c7af3cd77f28bea10374e15bc6536c2e1029438fdd3930bee
bbc5ac30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the annotated structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#ASCII magic &amp;quot;openssh-key-v1&amp;quot; plus null byte
6f70656e7373682d6b65792d7631 00
0000000a int length = 10
6165733235362d636263 string cipher = aes256-cbc
00000006 int length = 6
626372797074 string kdfname = bcrypt
00000018 int length = 24 (kdfoptions)
00000010 int length = 16
d08f6b8fd17593f246db4ac6c45a1193 salt&amp;#x2f;iv for bcrypt
00000010 int work factor = 16
00000001 int number of public keys = 1
00000033 int length = 51 public key 1 size (4 + 11 + 4 + 32)

# Public key 1
0000000b int length = 11
7373682d65643235353139 string key type = ssh-ed25519
00000020 int length = 32
# public key payload 32 bytes
# probably encoding a point on the ed25519 curve
62837be86c63712896b8e0e7543e367c
3abd0c0b5ad3e764ea0e4f8ddd7d00ef

00000090 int length = 144 encrypted aes256-cbc output (16x9)
1e60c56ef30d0ff02e07b57bf1464507
6c32c86c88ecad545ca28424e4739aff
5895bebd6778e70b6c54b309b9fdb0c9
4102bf8cef5b97d3d75636967e67e4b9
c1ee72ae81074b0ce0f7e540e051d569
05da263af3e383342cc75b3145242abb
75257586a119c9d3673dfb7eabe46963
50904e7c7af3cd77f28bea10374e15bc
6536c2e1029438fdd3930beebbc5ac30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So there you have it. You could dig even deeper into the keys themselves to extract the various specific numbers (usually they have 1-letter names from the math equations they belong to like e,n,p,q etc) but I didn't bother for this since for this key format all I want to know is that it's an ed25519 private key and whether or not it has a passphrase.&lt;/p&gt;
&lt;p&gt;Other bits I learned while pairing are that ed25519 is the name of a specific curve in elliptic curve cryptography and the numbers represent &lt;code&gt;((2^255) - 19)&lt;/code&gt; as a Mersenne prime (out of my depth here, could be wrong). Part of it is the x coordinate and then you can compute the y bit if you know the sign or something like that.&lt;/p&gt;
&lt;p&gt;Also in the openssh source code they explicitly error out if the number of keys field isn't 1 so only 1 key is supported.&lt;/p&gt;
&lt;p&gt;For further reading check out &lt;a href="https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/"&gt;How do Ed5519 keys work?&lt;/a&gt; by Brian Warner.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This post is technically my Recurse Center 15 post but it was suggested that this post would make a handy reference so I didn't want to muck up the clarity/SEO of the title.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 01 Dec 2017 18:46:17 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/12/openssh-ed25519-private-key-file-format/</guid></item><item><title>Java 9 Strings</title><link>https://studiofreya.org/java/java-9-strings/</link><description>&lt;p&gt;String in Java 9 is a data type just like integer and floating point, but it is used to represent text rather than numbers or a single character.&lt;/p&gt;
&lt;p&gt;String variable is comprised of a set of characters that can also contain spaces, numbers and special characters.&lt;/p&gt;
&lt;p&gt;For instance, the word “tennis” and the phrase “I play tennis” are an example of string variable. Even a number “5445” could be considered a string in Java, if specified correctly.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Thu, 30 Nov 2017 13:59:17 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/java/java-9-strings/</guid></item><item><title>A Gentle Introduction to Erasure Codes</title><link>https://www.akalin.com/intro-erasure-codes</link><description>&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;1. Overview&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;This article explains Reed-Solomon erasure codes and the problems
  they solve in gory detail, with the aim of providing enough
  background to understand how the &lt;a href="https://en.wikipedia.org/wiki/Parchive"&gt;PAR1
  and PAR2&lt;/a&gt; file formats work, the details of which will be covered in
  future articles.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m assuming that the reader is familiar with programming,
  but has not had much exposure to coding theory or linear
  algebra. Thus, I&amp;rsquo;ll review the basics and treat the results we
  need as a &amp;ldquo;black box&amp;rdquo;, stating them and moving
  on. However, I&amp;rsquo;ll give self-contained proofs of those results
  in a companion article.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s start with the problem we&amp;rsquo;re trying to
  solve! Let&amp;rsquo;s say you have \(n\) files of roughly the
  same size, and you want to guard against \(m\) of them being
  lost or corrupted. To do so, you generate \(m\)
  &lt;em&gt;parity files&lt;/em&gt;
  ahead of time, and if in the future you lose up to \(m\) of the data
  files, you can use an equal number of parity files to recover the
  lost data files.&lt;/p&gt;



&lt;figure&gt;
  &lt;div class="fig" id="fig1"&gt;
    &lt;div class="column"&gt;
      &lt;div&gt;
        &lt;div&gt;&lt;code&gt;cashcat0.jpg&lt;/code&gt;&lt;/div&gt;
        &lt;img src="intro-erasure-codes-files/cashcat0.jpg" /&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;div&gt;&lt;code&gt;cashcat1.jpg&lt;/code&gt;&lt;/div&gt;
        &lt;img src="intro-erasure-codes-files/cashcat1.jpg" /&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;div&gt;&lt;code&gt;cashcat2.jpg&lt;/code&gt;&lt;/div&gt;
        &lt;img src="intro-erasure-codes-files/cashcat2.jpg" /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="column"&gt;
      &lt;div&gt;\(\xmapsto{\mathtt{GenerateParityFiles}}\)&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="column"&gt;
      &lt;div&gt;
        &lt;div&gt;&lt;code&gt;cashcats.p00&lt;/code&gt;&lt;/div&gt;
        &lt;img src="intro-erasure-codes-files/cashcats.p00.png" /&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;div&gt;&lt;code&gt;cashcats.p01&lt;/code&gt;&lt;/div&gt;
        &lt;img src="intro-erasure-codes-files/cashcats.p01.jpg" /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;figcaption&gt;
    &lt;span class="figure-text"&gt;Figure 1&lt;/span&gt;&amp;ensp; Using
    parity codes to protect against the loss or corruption of
    up to two images (out of three) of &lt;a href="https://twitter.com/CatsAndMoney"&gt;cashcats&lt;/a&gt;.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;div class="fig" id="fig2"&gt;
    &lt;div class="column"&gt;
      &lt;img src="intro-erasure-codes-files/cashcat0-glitched.png" /&gt;
      &lt;img src="intro-erasure-codes-files/cashcat1.jpg" /&gt;
      &lt;img src="intro-erasure-codes-files/broken-image.png" /&gt;
      &lt;img src="intro-erasure-codes-files/cashcats.p00.png" /&gt;
      &lt;img src="intro-erasure-codes-files/cashcats.p01.jpg" /&gt;
    &lt;/div&gt;
    &lt;div class="column"&gt;
      &lt;div&gt;\(\xmapsto{\mathtt{ReconstructDataFiles}}\)&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="column"&gt;
      &lt;img src="intro-erasure-codes-files/cashcat0.jpg" /&gt;
      &lt;img src="intro-erasure-codes-files/cashcat1.jpg" /&gt;
      &lt;img src="intro-erasure-codes-files/cashcat2.jpg" /&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;figcaption&gt;
    &lt;span class="figure-text"&gt;Figure 2&lt;/span&gt;&amp;ensp; With a
    corrupted and a missing file, recovering the original
    cashcat images using the parity files from Figure&amp;nbsp;1.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Note that this works even if you lose some of the parity files
  also; as long as you have \(n\) files, whether they be data or
  parity files, you&amp;rsquo;ll be able to recover the original \(n\)
  data files. Compare making \(n\) parity files with simply making a
  copy of the \(n\) data files (for \(n &gt; 1\)). In the latter case, if
  you lose both a data file and its copy, that data file becomes
  unrecoverable! So parity files take the same amount of space but
  provide superior recovery capabilities.&lt;/p&gt;

&lt;p&gt;Now we can reduce the problem above to a byte-level problem
  as follows. Have &lt;code&gt;ComputeParityFiles&lt;/code&gt; pad all the
  data files so they&amp;rsquo;re the same size, and then for each
  byte position &lt;code&gt;i&lt;/code&gt; call a function &lt;code&gt;ComputeParityBytes&lt;/code&gt; on the &lt;code&gt;i&lt;/code&gt;th
  byte of each data file, and store the results into the &lt;code&gt;i&lt;/code&gt;th
  byte of each parity file. Also take a checksum or hash of
  each data file and store those (along with the original data
  file sizes) with the parity files. Then, &lt;code&gt;ReconstructDataFiles&lt;/code&gt;
  can detect corrupted files using the checksums/hashes and
  treat them as missing, and then for each byte position &lt;code&gt;i&lt;/code&gt; it
  can call a function &lt;code&gt;ReconstructDataBytes&lt;/code&gt; on the &lt;code&gt;i&lt;/code&gt;th
  byte of each good data and parity file to recover the &lt;code&gt;i&lt;/code&gt;th byte of the corrupted/missing data files.&lt;/p&gt;

&lt;p&gt;A byte error where we &lt;em&gt;know&lt;/em&gt; the position of the
  dropped/corrupted byte is called an &lt;em&gt;erasure&lt;/em&gt;. Then, the pair
  of functions &lt;code&gt;ComputeParityBytes&lt;/code&gt; and &lt;code&gt;ReconstructDataBytes&lt;/code&gt; which
  behave as described above implements what is called an &lt;a href="https://en.wikipedia.org/wiki/Erasure_code#Optimal_erasure_codes"&gt;&lt;em&gt;optimal erasure code&lt;/em&gt;&lt;/a&gt;;
  it&amp;rsquo;s an erasure code because it guards only against byte
  erasures, and not more general errors where we don&amp;rsquo;t know
  which data bytes have been corrupted, and it&amp;rsquo;s optimal because
  in general you need at least \(n\) known bytes to recover the \(n\)
  data bytes, and that bound is achieved.&lt;/p&gt;

&lt;div class="p"&gt;In detail, an optimal erasure code is composed of some
  set of possible \((n, m)\) pairs, and for each possible pair, a
  function

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ComputeParityBytes&amp;lt;n, m&amp;gt;(data: byte[n]) -&gt; (parity: byte[m])&lt;/code&gt;&lt;/pre&gt;

  that computes \(m\) parity bytes given \(n\) data bytes, and a
  function

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ReconstructDataBytes&amp;lt;n, m&amp;gt;(partialData: (byte?)[n], partialParity: (byte?)[m]) -&gt; ((data: byte[n]) | Error)&lt;/code&gt;&lt;/pre&gt;

  that takes in a partial list of data and parity bytes from an
  earlier call to &lt;code&gt;ComputeParity&lt;/code&gt;, and returns the full
  list of data bytes if there are at least \(n\) known data or parity
  bytes (i.e., there are no more than \(m\) omitted data or parity
  bytes), and an error otherwise.&lt;/div&gt;

&lt;p&gt;(In the above pseudocode, I&amp;rsquo;m using &lt;code&gt;T[n]&lt;/code&gt; to mean an array of &lt;code&gt;n&lt;/code&gt; objects of type &lt;code&gt;T&lt;/code&gt;,
  and &lt;code&gt;byte?&lt;/code&gt; to mean &lt;code&gt;byte | None&lt;/code&gt;. Also, I&amp;rsquo;ll omit the &lt;code&gt;-Bytes&amp;lt;n, m&amp;gt;&lt;/code&gt; suffix
  from now on.)&lt;/p&gt;

&lt;p&gt;By the end of this article, we&amp;rsquo;ll find out exactly how the
  following example works:&lt;/p&gt;

&lt;div class="interactive-example"&gt;
  &lt;h3&gt;Example 1: &lt;code&gt;ComputeParity&lt;/code&gt; and &lt;code&gt;ReconstructData&lt;/code&gt;&lt;/h3&gt;

  &lt;div class="interactive-example" id="computeParityDemo"&gt;
    &lt;h3&gt;&lt;code&gt;ComputeParity&lt;/code&gt;&lt;/h3&gt;
    Let

    &lt;span style="white-space: nowrap;"&gt;
      &lt;var&gt;d&lt;/var&gt; = [ da, db, 0d ]
    &lt;/span&gt;

    be the input data bytes and let

    &lt;span style="white-space: nowrap;"&gt;
      &lt;var&gt;m&lt;/var&gt; = 2
    &lt;/span&gt;

    be the desired parity byte count. Then the output parity bytes
    are

    &lt;span style="white-space: nowrap;"&gt;
      &lt;var&gt;p&lt;/var&gt; = [ &lt;span class="result"&gt;52&lt;/span&gt;, &lt;span class="result"&gt;0c&lt;/span&gt; ].
    &lt;/span&gt;
  &lt;/div&gt;
  

  &lt;br /&gt;

  &lt;div class="interactive-example" id="reconstructDataDemo"&gt;
    Let

    &lt;span style="white-space: nowrap;"&gt;
      &lt;var&gt;d&lt;/var&gt;&lt;sub&gt;partial&lt;/sub&gt; = [ ??, db, ?? ]
    &lt;/span&gt;

    be the input partial data bytes and

    &lt;span style="white-space: nowrap;"&gt;
      &lt;var&gt;p&lt;/var&gt;&lt;sub&gt;partial&lt;/sub&gt; = [ 52, 0c ]
    &lt;/span&gt;

    be the input partial parity bytes. Then the output data bytes are

    &lt;span style="white-space: nowrap;"&gt;
      &lt;var&gt;d&lt;/var&gt; = [ &lt;span class="result"&gt;da&lt;/span&gt;, &lt;span class="result"&gt;db&lt;/span&gt;, &lt;span class="result"&gt;0d&lt;/span&gt; ].
    &lt;/span&gt;
  &lt;/div&gt;
  
&lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;2. Erasure codes for \(m = 1\)&lt;/h2&gt;
&lt;/header&gt;

&lt;div class="p"&gt;The simplest erasure codes are when \(m = 1\). For example, define

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ComputeParitySum(data: byte[n]) {
  return [data[0] + &amp;hellip; + data[n-1]]
}&lt;/code&gt;&lt;/pre&gt;

  where we consider &lt;code&gt;byte&lt;/code&gt; to be an unsigned type such that
  addition and subtraction wrap around, i.e. byte arithmetic is done
  modulo \(256\). Then also define

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ReconstructDataSum(partialData: (byte?)[n], partialParity: (byte?)[1]) {
  if &lt;em&gt;there is more than one entry of partialData or partialParity set to None&lt;/em&gt; {
    return Error
  } else if &lt;em&gt;partialData has no entry set to None&lt;/em&gt; {
    return partialData
  }

  i := partialData.firstIndexOf(None);
  partialSum = partialData[0] + &amp;hellip; + partialData[i-1] + partialData[i+1] + &amp;hellip; + partialData[n-1]
  return partialData[0:i] ++ [partialParity[0] - partialSum] ++ partialData[i+1:n]
}&lt;/code&gt;&lt;/pre&gt;

  where &lt;code&gt;a[i:j]&lt;/code&gt; means the subarray of &lt;code&gt;a&lt;/code&gt; starting at &lt;code&gt;i&lt;/code&gt; and
  ending (without inclusion) at &lt;code&gt;j&lt;/code&gt;, and &lt;code&gt;++&lt;/code&gt; is array concatenation.&lt;/div&gt;

&lt;p&gt;This simple erasure code uses the fact that if you have the sum of
  a list of numbers, then you can recover a missing number by
  subtracting the sum of the other numbers from the total sum, and
  also that this works even if you do the arithmetic modulo \(256\).&lt;/p&gt;

&lt;div class="p"&gt;Another erasure code for \(m = 1\) uses &lt;a href="https://en.wikipedia.org/wiki/Exclusive_or#Bitwise_operation"&gt;bitwise exclusive
  or&lt;/a&gt; (denoted as xor, &lt;code&gt;^&lt;/code&gt;, or \(\oplus\)) instead
  of arithmetic modulo \(256\). Define

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ComputeParityXor(data: byte[n]) {
  return [data[0] &amp;oplus; &amp;hellip; &amp;oplus; data[n-1]]
}&lt;/code&gt;&lt;/pre&gt;

  and

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ReconstructDataXor(partialData: (byte?)[n], partialParity: (byte?)[1]) {
  if &lt;em&gt;there is more than one entry of partialData or partialParity set to None&lt;/em&gt; {
    return Error
  } else if &lt;em&gt;partialData has no entry set to None&lt;/em&gt; {
    return partialData
  }

  i := partialData.firstIndexOf(None);
  partialXor = partialData[0] &amp;oplus; &amp;hellip; &amp;oplus; partialData[i-1] &amp;oplus; partialData[i&amp;oplus;1] &amp;oplus; &amp;hellip; &amp;oplus; partialData[n-1]
  return partialData[0:i] ++ [partialParity[0] &amp;oplus; partialXor] ++ partialData[i+1:n]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This relies on the fact that \(a \oplus a = 0\), so given the xor
  of a list of bytes, you can recover a missing byte by xoring with
  all the known bytes.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;3. Erasure codes for \(m = 2\) (almost)&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Now coming up with an erasure code for \(m = 2\) is more involved,
  but we can get an inkling of how it could work by letting \(n = 3\)
  for simplicity, and also letting the output of &lt;code&gt;ComputeParity&lt;/code&gt; be
  non-negative integers, instead of just bytes (i.e., less than
  \(256\)). In that case, we can consider parity numbers that are
  weighted sums of the data bytes. For example, like in the \(m = 1\)
  case, we can have the first parity number be

  \[
    p_0 = d_0 + d_1 + d_2\text{,}
  \]

  (using \(d_i\) for data bytes and \(p_i\) for parity numbers)
  but for the second parity number, we can pick different weights, say

  \[
    p_1 = 1 \cdot d_0 + 2 \cdot d_1 + 3 \cdot d_2\text{.}
  \]

  We want to make sure that the weights for the second parity number
  are &amp;ldquo;sufficiently different&amp;rdquo; from that of the first
  parity number, which we&amp;rsquo;ll clarify later, but for example note
  that setting

  \[
    p_1 = 2 \cdot d_0 + 2 \cdot d_1 + 2 \cdot d_2
  \]

  can&amp;rsquo;t add any new information, since then \(p_1\) will
  always be equal to \(2 \cdot p_0\).&lt;/p&gt;

&lt;div class="p"&gt;So then our &lt;code&gt;ComputeParity&lt;/code&gt; function looks like

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ComputeParityWeighted(data: byte[3]) {
  return [
    int(data[0]) +     int(data[1]) +     int(data[2]),
    int(data[0]) + 2 * int(data[1]) + 3 * int(data[2]),
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="p"&gt;As for &lt;code&gt;ReconstructData&lt;/code&gt;, if we have two missing data bytes,
  say \(d_i\) and \(d_j\) for \(i &amp;lt; j\), and \(p_0\) and \(p_1\),
  we can rearrange the equations

  \[
    \begin{aligned}
      p_0 &amp;= d_0 + d_1 + d_2 \\
      p_1 &amp;= 1 \cdot d_0 + 2 \cdot d_1 + 3 \cdot d_2
    \end{aligned}
  \]

  to get all the unknowns on the left side, letting \(d_k\) be the known data byte:

  \[
    \begin{aligned}
      d_i + d_j &amp;= X = p_0 - d_k \\
      (i+1) \cdot d_i + (j+1) \cdot d_j &amp;= Y = p_1 - (k + 1) \cdot d_k\text{.}
    \end{aligned}
  \]

  We can then multiply the first equation by \(i + 1\) and
  subtract it from the second to cancel the \(d_i\) term and get

  \[
    d_j = (Y - (i + 1) \cdot X) / (j - i)\text{,}
  \]

  and then we can use the first equation to solve for \(d_i\):

  \[
    d_i = X - d_j = ((j + 1) \cdot X - Y) / (j - i)\text{.}
  \]

  Thus with these equations, we can implement &lt;code&gt;ReconstructData&lt;/code&gt;:

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ReconstructDataWeighted(partialData: (byte?)[3], partialParity: (int?)[2]) {
  &lt;em&gt;Handle all cases except when there are exactly two entries set to none in partialData.&lt;/em&gt;

  [i, j] := &lt;em&gt;indices of the unknown data bytes&lt;/em&gt;
  k := &lt;em&gt;index of the known data byte&lt;/em&gt;

  X := partialParity[0] - partialData[k]
  Y := partialParity[1] - (k + 1) * partialData[k];

  d_i := ((j + 1) * X - Y) / (j - i)
  d_j := (Y - (i + 1) * X) / (j - i)

  return &lt;em&gt;an array with d_i, d_j, and d[k] in the right order&lt;/em&gt;
}&lt;/code&gt;&lt;/pre&gt;

  (Generalizing this to larger values of \(n\) is straightforward;
  \(p_0\) will still have a weight of \(1\) for each data byte, and
  \(p_1\) will have a weight of \(i + 1\) for \(d_i\). \(X\) and \(Y\)
  will then have terms for all known bytes, and everything else
  proceeds the same after that.)&lt;/div&gt;

&lt;p&gt;Now what goes wrong if we just try to do everything modulo \(256\)?
  The most obvious difference from the \(m = 1\) case is that solving
  for \(d_i\) or \(d_j\) involves division, which works fine for
  non-negative integers as long as there&amp;rsquo;s no remainder, but it
  is not immediately clear how division can make sense modulo \(256\).&lt;/p&gt;

&lt;p&gt;One possible way to define division modulo \(256\)
  would be to first define the &lt;em&gt;multiplicative inverse&lt;/em&gt; modulo
  \(256\) of an integer \(0 \le x \lt 256\) as the integer \(0 \le y
  \lt 256\) such that \((x \cdot y) \bmod 256 = 1\), if it exists, and
  then define division by \(x\) modulo \(256\) to be multiplication by
  \(y\) modulo \(256\). But this immediately runs into problems; \(2\)
  has no multiplicative inverse modulo \(256\), and the same holds for
  any even number, so reconstruction will fail if, for example, we
  have the first and third data bytes missing, since then we&amp;rsquo;d
  be trying to divide by \(j - i = 2\).&lt;/p&gt;

&lt;p&gt;But for now, let&amp;rsquo;s leave aside the problem of generating
  parity bytes instead of parity numbers, and instead focus on how we
  can generalize the above for larger values of \(m\). To do so, we
  need to first review some linear algebra.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;4. Just enough linear algebra to get by&lt;sup&gt;&lt;a href="#fn1" id="r1"&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;In our \(n = 3, m = 2\) example in the previous section, the
  equations for the parity numbers have the form

  \[
    p = a_0 \cdot d_0 + a_1 \cdot d_1 + a_2 \cdot d_2
  \]

  for constants \(a_0\), \(a_1\), and \(a_2\). We call such a
  weighted sum of the \(d_i\)s a &lt;em&gt;linear combination&lt;/em&gt; of
  the \(d_i\)s, and we write this in a tabular form

  \[
    p =
    \begin{pmatrix}
      a_0 &amp; a_1 &amp; a_2
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}\text{,}
  \]

  where we define the multiplication of a
  &lt;em&gt;row vector&lt;/em&gt; and a &lt;em&gt;column vector&lt;/em&gt; by the
  equation above, generalized in the straightforward manner
  for any \(n\).&lt;/p&gt;

&lt;p&gt;Then since we have two parity numbers \(p_0\) and \(p_1\),
  each a linear combination of the \(d_i\)s, i.e.

  \[
    \begin{aligned}
      p_0 &amp;= a_{00} \cdot d_0 + a_{01} \cdot d_1 + a_{02} \cdot d_2 \\
      p_1 &amp;= a_{10} \cdot d_0 + a_{11} \cdot d_1 + a_{12} \cdot d_2\text{,}
    \end{aligned}
  \]

  we can write this in a single tabular form as

  \[
    \begin{bmatrix}
      p_0 \\ p_1
    \end{bmatrix}
    =
    \begin{pmatrix}
      a_{00} &amp; a_{01} &amp; a_{02} \\
      a_{10} &amp; a_{11} &amp; a_{12}
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}\text{,}
  \]

  where we define the multiplication of a &lt;em&gt;matrix&lt;/em&gt; and
  a column vector by the equations above.&lt;/p&gt;

&lt;p&gt;Now if we restrict parity numbers to be linear combinations of the
  data bytes, then we can identify a function
  &lt;code&gt;ComputeParity&lt;/code&gt; using some set of weights with the matrix
  formed from that set of weights as above. This holds in general: if
  a function is defined as a list of linear combinations of its
  inputs, then it can be represented using a matrix as above, and we
  call it a
  &lt;em&gt;linear function&lt;/em&gt;. Then we have a correspondence between
  linear functions that take \(n\) numbers to \(m\) numbers and
  matrices with \(m\) rows and \(n\) columns, which are denoted as \(m
  \times n\) matrices.&lt;/p&gt;

&lt;p&gt;As the first example of this correspondence, note that we denote
  the elements of the matrix above as \(a_{ij}\), where the first
  index is the row index and the second index is the column
  index. Looking back to the parity equations, we also see that the
  first index corresponds to the output arguments of &lt;code&gt;ComputeParity&lt;/code&gt;, and the second index corresponds to
  the input arguments.&lt;sup&gt;&lt;a href="#fn2" id="r2"&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The usefulness of the correspondence between linear functions and
  matrices is that we can store and manipulate a linear function by
  storing and manipulating its corresponding matrix of weights, which
  you wouldn&amp;rsquo;t be able to easily do for functions in
  general. For example, as we&amp;rsquo;ll see below, we&amp;rsquo;ll be able
  to compute the inverse of a linear function by matrix operations,
  which will be useful for &lt;code&gt;ReconstructData&lt;/code&gt;.&lt;/p&gt;

&lt;div class="p"&gt;First, let&amp;rsquo;s examine some simple matrix operations and their
  effects on the corresponding linear function:

  &lt;ul&gt;
    &lt;li&gt;&lt;em&gt;Deleting a row&lt;/em&gt; of a matrix corresponds to &lt;em&gt;deleting an output&lt;/em&gt; of a linear function.&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Swapping two rows&lt;/em&gt; of a matrix corresponds to &lt;em&gt;swapping two outputs&lt;/em&gt; of a linear function.&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Appending a row&lt;/em&gt; to a matrix corresponds to &lt;em&gt;adding an output&lt;/em&gt; to a linear function.&lt;/li&gt;
  &lt;/ul&gt;

  In general, matrix row operations correspond to manipulations of a
  linear function&amp;rsquo;s outputs.&lt;/div&gt;

&lt;div class="p"&gt;An important operation on functions is composition: if
  \(f\) takes \(k\) inputs to \(m\) outputs, and \(g\) takes
  \(m\) inputs to \(n\) outputs, then we can define \((g \circ
  f)(x_0, \dotsc, x_k) = g(f(x_0, \dotsc, x_k))\) which takes
  \(k\) inputs to \(n\) outputs. It turns out that the
  composition of two linear functions is again a linear
  function, and so there must be an operation which takes the
  corresponding \(m \times k\) matrix \(F\) and the \(n \times
  m\) matrix \(G\) and yields a \(n \times k\) matrix. This
  important operation, the bane of high-schoolers everywhere,
  is called &lt;a href="https://en.wikipedia.org/wiki/Matrix_multiplication"&gt;&lt;em&gt;matrix multiplication&lt;/em&gt;&lt;/a&gt;,
  denoted by \(F \cdot G\). If \(H = F \cdot G\), then the
  explicit formula for its elements is

  \[
    h_{ij} = \sum_{k=0}^{m-1} f_{ik} \cdot g_{kj}\text{,}
  \]

  which corresponds to the following code:

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;matrixMultiply(f: Matrix, g: Matrix) {
  if (f.columns != g.rows) {
    return Error
  }

  h := new Matrix(f.rows, g.columns)
  for i := 0 to f.rows - 1 {
    for j := 0 to g.columns - 1 {
      t := 0
      for k := 0 to f.columns - 1 {
        t += f[i, k] * g[k, j]
      }
      h[i, j] = t
    }
  }
  return h
}&lt;/code&gt;&lt;/pre&gt;

  You can convince yourself that the above formula and code is correct
  by trying to compose some small linear functions by hand.
&lt;/div&gt;

&lt;p&gt;A useful property of matrix multiplication is that it&amp;rsquo;s a
  generalization of the product of a row vector and a column vector,
  and the product of a matrix and a column vector as we defined above.&lt;/p&gt;

&lt;p&gt;I would be remiss if I didn&amp;rsquo;t talk about the consequences of
  defining matrix multiplication as the matrix of the composition of
  the corresponding linear functions. First, this immediately implies
  that you can only multiply matrices if the left matrix has the same
  number of rows as the number of columns of the right matrix, which
  corresponds to the fact that you can only compose functions if the
  left function takes the same number of inputs as the number of
  outputs of the right function. Furthermore, even if you have two \(n
  \times n\) matrices \(F\) and \(G\), unlike numbers, it is not true
  that \(F \cdot G = G \cdot F\), which corresponds to the fact that
  in general, for two functions that take \(n\) inputs to \(n\)
  outputs, it is not true that \(f \circ g = g \circ f\). If you
  learned matrix multiplication just from the formula above, then
  these facts are much less obvious!&lt;/p&gt;

&lt;p&gt;Finally, an important function is the &lt;a href="https://en.wikipedia.org/wiki/Identity_function"&gt;&lt;em&gt;identity function&lt;/em&gt;&lt;/a&gt;
  \(\mathrm{Id}_n\), which return its \(n\) inputs as its outputs. It
  corresponds to the &lt;a href="https://en.wikipedia.org/wiki/Identity_matrix"&gt;&lt;em&gt;identity matrix&lt;/em&gt;&lt;/a&gt;
  \[
  I_n =
  \begin{pmatrix}
    1 &amp; 0 &amp; \cdots &amp; 0 &amp; 0 \\
    0 &amp; 1 &amp; \cdots &amp; 0 &amp; 0 \\
    \vdots &amp; \vdots &amp; \ddots &amp; \vdots &amp; \vdots \\
    0 &amp; 0 &amp; \cdots &amp; 1 &amp; 0 \\
    0 &amp; 0 &amp; \cdots &amp; 0 &amp; 1
  \end{pmatrix}\text{.}
  \]&lt;/p&gt;

&lt;p&gt;For a linear function \(f\) that takes \(n\) inputs to \(n\)
  outputs, if there is a function \(g\) such that \(f \circ g =
  \mathrm{Id}_n\), then we call \(g\) the inverse of \(f\), and denote
  it as \(f^{-1}\). (It is also true that \(f^{-1} \circ f =
  \mathrm{Id}_n\), i.e. \((f^{-1})^{-1} = f\).) Not all linear
  functions taking \(n\) inputs to \(n\) outputs have inverses, but if
  the inverse exists, it is also linear (and unique, which is why we
  call it &lt;em&gt;the&lt;/em&gt; inverse). Therefore, we can define
  the &lt;em&gt;inverse&lt;/em&gt; of an \(n \times n\) (or &lt;em&gt;square&lt;/em&gt;)
  matrix \(M\) as the unique matrix \(M^{-1}\) such that \(M \cdot
  M^{-1} = M^{-1} \cdot M = I_n\), if it exists; also, if \(M\) has an
  inverse, we say that \(M\) is &lt;em&gt;invertible&lt;/em&gt;.&lt;/p&gt;

&lt;div class="interactive-example"&gt;
  &lt;h3&gt;Example 2: The matrix/linear function correspondence&lt;/h3&gt;

  &lt;div class="p"&gt;Let

  \[
    M = \begin{pmatrix} 1 &amp; 2 \\ 3 &amp; 4\end{pmatrix}\text{.}
  \]

    This corresponds to the linear function

    &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;f(x: rational[2]) {
  return [
    1 * x[0] + 2 * x[1],
    3 * x[0] + 4 * x[1],
  ]
}&lt;/code&gt;&lt;/pre&gt;

    where &lt;code&gt;rational&lt;/code&gt; is an arbitrary-precision rational
    number type.&lt;/div&gt;

  &lt;div class="p"&gt;\(M\) is invertible with inverse

    \[
    M^{-1} = \begin{pmatrix} -2 &amp; 1 \\ 3/2 &amp; -1/2\end{pmatrix}\text{.}
    \]

    This corresponds to the linear function

    &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;g(y: rational[2]) {
  return [
    -2 * x[0] + 1 * x[1],
    (3/2) * x[0] + (-1/2) * x[1],
  ]
}&lt;/code&gt;&lt;/pre&gt;

    so &lt;code&gt;g&lt;/code&gt; is the inverse function of &lt;code&gt;f&lt;/code&gt;. Indeed, &lt;code&gt;f([5, 6])&lt;/code&gt; is &lt;code&gt;[17, 39]&lt;/code&gt; and &lt;code&gt;g([17, 39])&lt;/code&gt; is &lt;code&gt;[5, 6]&lt;/code&gt;.&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So now we&amp;rsquo;ve reduced the problem of finding the inverse of a
  linear function taking \(n\) inputs to \(n\) outputs to finding the
  inverse of an \(n \times n\) matrix. Before we tackle the question
  of computing those inverses, let&amp;rsquo;s first recast our problem in
  the language of linear algebra and see why we need to find the
  inverse of a linear function.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;5. Erasure codes in general&lt;/h2&gt;
&lt;/header&gt;

&lt;div class="p"&gt;So, revisiting our \(n = 3, m = 2\) erasure code from
  above, we have the linear function

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;ComputeParityWeighted(data: byte[3]) {
  return [
    int(data[0]) +     int(data[1]) +     int(data[2]),
    int(data[0]) + 2 * int(data[1]) + 3 * int(data[2]),
  ]
}&lt;/code&gt;&lt;/pre&gt;

  which therefore corresponds to the &lt;em&gt;parity matrix&lt;/em&gt;

  \[
    P =
    \begin{pmatrix}
      1 &amp; 1 &amp; 1 \\
      1 &amp; 2 &amp; 3
    \end{pmatrix}\text{.}
  \]

  So in mathematical notation, &lt;code&gt;ComputeParityWeighted&lt;/code&gt; looks like:

  \[
    \begin{bmatrix}
      p_0 \\ p_1
    \end{bmatrix}
    =
    \mathtt{ComputeParityWeighted}(d_0, d_1, d_2) =
    \begin{pmatrix}
      1 &amp; 1 &amp; 1 \\
      1 &amp; 2 &amp; 3
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}\text{.}
  \]
&lt;/div&gt;

&lt;p&gt;So let&amp;rsquo;s now reimplement &lt;code&gt;ReconstructDataWeighted&lt;/code&gt; using linear algebra. First, append the rows of \(P\) to the identity matrix \(I_3\) to get the matrix equation

  \[
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2 \\ p_0 \\ p_1
    \end{bmatrix}
    =
    \begin{pmatrix}
      1 &amp; 0 &amp; 0 \\
      0 &amp; 1 &amp; 0 \\
      0 &amp; 0 &amp; 1 \\
      1 &amp; 1 &amp; 1 \\
      1 &amp; 2 &amp; 3
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}\text{,}
  \]

  which corresponds to a linear function that returns the input data bytes in addition to computing the parity numbers. Now let&amp;rsquo;s say we lose the data bytes \(d_0\) and \(d_2\). Then let&amp;rsquo;s remove the rows corresponding to those bytes:

  \[
    \begin{bmatrix}
      \xcancel{d_0} \\ d_1 \\ \xcancel{d_2} \\ p_0 \\ p_1
    \end{bmatrix}
    =
    \begin{pmatrix}
      \xcancel{1} &amp; \xcancel{0} &amp; \xcancel{0} \\
      0 &amp; 1 &amp; 0 \\
      \xcancel{0} &amp; \xcancel{0} &amp; \xcancel{1} \\
      1 &amp; 1 &amp; 1 \\
      1 &amp; 2 &amp; 3
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}\text{,}
  \]

  which turns into

  \[
    \begin{bmatrix}
      d_1 \\ p_0 \\ p_1
    \end{bmatrix} =
    \begin{pmatrix}
      0 &amp; 1 &amp; 0 \\
      1 &amp; 1 &amp; 1 \\
      1 &amp; 2 &amp; 3
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}\text{,}
  \]

  which corresponds to a linear function that maps the input data
  bytes to the non-lost data bytes and the parity bytes. This
  is the &lt;em&gt;inverse&lt;/em&gt; of the function we want, so we want
  to invert the \(3 \times 3\) matrix above, which we&amp;rsquo;ll
  call \(M\). That inverse is

  \[
    M^{-1} =
    \begin{pmatrix}
      -1/2 &amp; 3/2 &amp; -1/2 \\
      1 &amp; 0 &amp; 0 \\
      -1/2 &amp; -1/2 &amp; 1/2
    \end{pmatrix}\text{.}
  \]

  Multiplying both sides above by \(M^{-1}\), we get

  \[
    \begin{bmatrix}
      d_0 \\ d_1 \\ d_2
    \end{bmatrix}
    =
    \begin{pmatrix}
      -1/2 &amp; 3/2 &amp; -1/2 \\
      1 &amp; 0 &amp; 0 \\
      -1/2 &amp; -1/2 &amp; 1/2
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_1 \\ p_0 \\ p_1
    \end{bmatrix}\text{,}              
  \]

  which is exactly what we want: the original data bytes in
  terms of the known data bytes and the parity numbers!&lt;sup&gt;&lt;a href="#fn3" id="r3"&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Comparing this equation to the one we manually computed previously,
  they don&amp;rsquo;t look immediately similar, but some rearrangement
  will reveal that they indeed compute the same thing. As a sanity
  check, notice that the second row of \(M^{-1}\) means that the first
  input argument is mapped unchanged to the second output argument,
  which is exactly what we want for the known byte \(d_1\).&lt;/p&gt;

&lt;p&gt;Now what does this look like in general, i.e. for
  arbitrary \(n\) and \(m\)? First, we have to generate an
  \(m \times n\) parity matrix \(P\) whose rows have to be
  &amp;ldquo;sufficiently different&amp;rdquo; from each other,
  which we still have to clarify. Then &lt;code&gt;ComputeParity&lt;/code&gt; just multiplies \(P\) by \([d]\), the column matrix of input bytes, like so:

  \[
    \begin{bmatrix}
      p_0 \\ \vdots \\ p_{m-1}
    \end{bmatrix}
    =
    \mathtt{ComputeParity}(d_0, \dotsc, d_{n-1}) =
    \begin{pmatrix}
      p_0 \\
      \vdots \\
      p_{m-1}
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      d_0 \\ \vdots \\ d_{n-1}
    \end{bmatrix}\text{,}
  \]

  where the \(p_i\) are the rows of \(P\).&lt;/p&gt;

&lt;p&gt;As for &lt;code&gt;ReconstructData&lt;/code&gt;, we first append
  the rows of \(P\) to \(I_n\), whose rows we&amp;rsquo;ll denote as \(e_i\):

\[
  \begin{bmatrix}
    d_0 \\ \vdots \\ d_{n-1} \\
    p_0 \\ \vdots \\ p_{m-1}
  \end{bmatrix}
  =
  \begin{pmatrix}
    e_0 \\
    \vdots \\
    e_{n-1} \\
    p_0 \\
    \vdots \\
    p_{m-1}
  \end{pmatrix}
  \cdot
  \begin{bmatrix}
    d_0 \\ \vdots \\ d_{n-1}
  \end{bmatrix}\text{.}
\]

Now assume that the indices of the missing \(k \le m\) data
bytes are \(i_0, \dotsc, i_{k-1}\).
Then we remove the rows
corresponding to the missing data bytes, and keep some \(k\)
parity rows, e.g. \(p_0\) to \(p_{k-1}\). This yields the equation

\[
  \begin{bmatrix}
    d_{j_0} \\ \vdots \\ d_{j_{n-k-1}} \\
    p_0 \\ \vdots \\ p_{k-1}
  \end{bmatrix}
  =
  \begin{pmatrix}
    e_{j_0} \\
    \vdots \\
    e_{j_{n-k-1}} \\
    p_0 \\
    \vdots \\
    p_{k-1}
  \end{pmatrix}
  \cdot
  \begin{bmatrix}
    d_0 \\ \vdots \\ d_{n-1}
  \end{bmatrix}\text{,}
\]

where \(j_0, \dotsc, j_{m-k-1}\) are the indices of the
&lt;em&gt;present&lt;/em&gt; \(n - k\) data bytes. Call that \(n \times n\)
matrix \(M\), and compute its inverse \(M^{-1}\). If \(P\) was chosen correctly, \(M^{-1}\) should always exist, so if the inverse computation fails, raise an error. Therefore, &lt;code&gt;ReconstructData&lt;/code&gt; just multiplies \(M^{-1}\) by the column matrix of present data bytes and chosen parity numbers:

\[
  \begin{bmatrix}
    d_0 \\ \vdots \\ d_{n-1}
  \end{bmatrix}
  =
  \mathtt{ReconstructData}(d_{j_0}, \dotsc, d_{j_{n-k-1}}, p_0, \dotsc, p_{k-1})
  = M^{-1} \cdot
  \begin{bmatrix}
    d_{j_0} \\ \vdots \\ d_{j_{n-k-1}} \\
    p_0 \\ \vdots \\ p_{k-1}
  \end{bmatrix}\text{.}
\]
&lt;/p&gt;

&lt;p&gt;As an optimization, some rows of \(M^{-1}\) correspond to just
  shuffling around the known data bytes \(d_{j_*}\), so we can just
  remove those rows, compute the missing data bytes, and do the
  shuffling ourselves.&lt;/p&gt;

&lt;div class="p"&gt;So we now have outlines of implementations of both &lt;code&gt;ComputeParity&lt;/code&gt; and &lt;code&gt;ReconstructData&lt;/code&gt;,
  but we still have missing pieces. In particular,
  &lt;ol&gt;
    &lt;li&gt;How do we compute matrix inverses?&lt;/li&gt;
    &lt;li&gt;How do we generate &amp;ldquo;optimal&amp;rdquo; parity matrices so that \(M^{-1}\) always exists?&lt;/li&gt;
    &lt;li&gt;How do we compute parity bytes instead of parity numbers?&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

&lt;p&gt;So first, let&amp;rsquo;s see how to compute matrix inverses using row
  reduction.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;6. Finding matrix inverses using row reduction&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;We developed the theory of matrices by identifying them with linear
  functions of numbers. To show how to find matrix inverses, we have
  to look at them in a slightly different way by identifying matrix
  equations with systems of linear equations of numbers.&lt;/p&gt;

&lt;p&gt;For example, consider the matrix equation

  \[
    M \cdot x = y\text{,}
  \]

  where

  \[
    M =
    \begin{pmatrix}
      1 &amp; 2 \\
      3 &amp; 4
    \end{pmatrix}\text{,}
    \quad
    x =
    \begin{bmatrix}
      x_1 \\ x_2
    \end{bmatrix}
    \text{,} \quad \text{and }
    y =
    \begin{bmatrix}
      y_1 \\ y_2
    \end{bmatrix}\text{.}
  \]

  This expands to

  \[
    \begin{pmatrix}
      1 &amp; 2 \\
      3 &amp; 4
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      x_1 \\ x_2
    \end{bmatrix} =
    \begin{bmatrix}
      y_1 \\ y_2
    \end{bmatrix}\text{,}
  \]

  or

  \[
    \begin{aligned}
      y_1 &amp;= 1 \cdot x_1 + 2 \cdot x_2 \\
      y_2 &amp;= 3 \cdot x_1 + 4 \cdot x_2\text{,}
    \end{aligned}
  \]

  which is a linear system of equations of numbers. Letting \(M\) be
  any matrix, and \(x\) and \(y\) be appropriately-sized column
  matrices of variables, we can see that the matrix equation
  \(M \cdot x = y\) is shorthand for a system of linear equations of
  numbers.&lt;/p&gt;

&lt;p&gt;If we could find \(M^{-1}\), we could solve the matrix
  equation easily by multiplying both sides by it:

  \[
    \begin{aligned}
      M^{-1} \cdot (M \cdot x) &amp;= M^{-1} \cdot y \\
      x &amp;= M^{-1} \cdot y\text{,}
    \end{aligned}
  \]

  and therefore solve the linear system for \(x\) in terms of \(y\).
  Conversely, if we were able to solve the linear system for \(x\),
  we&amp;rsquo;d then be able to read off \(M^{-1}\) from the new linear
  system.&lt;/p&gt;

&lt;div class="p"&gt;But how do we solve a linear system? From the theory of linear systems of equations, we have a few tools at our disposal:
  &lt;ul&gt;
    &lt;li&gt;swapping two equations,&lt;/li&gt;
    &lt;li&gt;multiplying an equation by a number,&lt;/li&gt;
    &lt;li&gt;adding one equation to another, possibly multiplying
      the equation by a number before adding.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;All of these are valid transformations because they
  don&amp;rsquo;t change the solution set of the linear system.&lt;/p&gt;

&lt;p&gt;For example, in the equation above, the first step would be
  to subtract \(3\) times the first equation from the second
  equation to yield

  \[
  \begin{aligned}
    y_1 &amp;= x_1 + 2 \cdot x_2 \\
    y_2 - 3 \cdot y_1 &amp;= -2 \cdot x_2\text{.}
  \end{aligned}
  \]

  Then, add the second equation back to the first equation:

  \[
    \begin{aligned}
      y_2 - 2 \cdot y_1 &amp;= x_1 \\
      y_2 - 3 \cdot y_1 &amp;= -2 \cdot x_2\text{.}
    \end{aligned}
  \]

  Finally, divide the second equation by \(-2\):

  \[
    \begin{aligned}
      y_2 - 2 \cdot y_1 &amp;= x_1 \\
      (3/2) \cdot y_1 - (1/2) \cdot y_2 &amp;= x_2\text{.}
    \end{aligned}
  \]

  This is equivalent to the matrix equation

  \[
    \begin{pmatrix}
      -2 &amp; 1 \\ 3/2 &amp; -1/2
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      y_1 \\ y_2
    \end{bmatrix} =
    \begin{bmatrix}
      x_1 \\ x_2
    \end{bmatrix}\text{,}
  \]

  so

  \[
    M^{-1} = \begin{pmatrix}
      -2 &amp; 1 \\ 3/2 &amp; -1/2
    \end{pmatrix}\text{.}
  \]
&lt;/p&gt;

&lt;p&gt;So how do we translate the above process to an algorithm operating on matrices? First, express our matrix equation in a slightly
different form:

  \[
    M \cdot x = I \cdot y\text{.}
  \]

  Using the example above, this is

  \[
    \begin{pmatrix}
      1 &amp; 2 \\
      3 &amp; 4
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      x_1 \\ x_2
    \end{bmatrix}
    =
    \begin{pmatrix}
      1 &amp; 0 \\
      0 &amp; 1
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      y_1 \\ y_2
    \end{bmatrix}\text{.}
  \]

  Then, you can see that the first step above corresponds to subtracting \(-3\) times the first row from the second row to yield:

  \[
    \begin{pmatrix}
      1 &amp; 2 \\
      0 &amp; -2
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      x_1 \\ x_2
    \end{bmatrix}
    =
    \begin{pmatrix}
      1 &amp; 0 \\
      -3 &amp; 1
    \end{pmatrix}
    \cdot
    \begin{bmatrix}
      y_1 \\ y_2
    \end{bmatrix}\text{.}
  \]

  We don&amp;rsquo;t even need to keep writing the \(x\) and \(y\)
  column matrices; we can just write the &amp;ldquo;augmented&amp;rdquo; matrix.

  \[
    A =
    \left( \hskip -5pt
    \begin{array}{cc|cc}
      1 &amp; 2 &amp; 1 &amp; 0 \\
      0 &amp; -2 &amp; -3 &amp; 1
    \end{array}
    \hskip -5pt \right)
  \]
  and operate on it.&lt;/p&gt;

&lt;div class="p"&gt;Thus, the operations listed above on linear systems have corresponding operations on augmented matrices:
  &lt;ul&gt;
    &lt;li&gt;&lt;em&gt;swapping two equations&lt;/em&gt; corresponds to &lt;em&gt;swapping two rows&lt;/em&gt;;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;multiplying an equation by a number&lt;/em&gt; corresponds to &lt;em&gt;multiplying a row by a number&lt;/em&gt;; and&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;adding an equation to another&lt;/em&gt;, possibly multiplying the
      equation by a number before adding, corresponds to &lt;em&gt;adding a row to another row&lt;/em&gt;,
      possibly multiplying the row by a number before adding.&lt;/li&gt;
  &lt;/ul&gt;

Then, the goal is to use these &lt;em&gt;row operations&lt;/em&gt; to transform
  the initial augmented matrix, where the right side looks like the
  identity matrix, into one where the left side looks like the
  identity matrix. Then, translating the augmented matrix back into a
  matrix equation, that would give \(M^{-1}\) on the right side.&lt;sup&gt;&lt;a href="#fn4" id="r4"&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/div&gt;

&lt;div class="p"&gt;When doing this by hand, one usually works with the linear
  system itself, trying to see which variables can be easily
  eliminated so as to minimize arithmetic. However, to
  translate this to an algorithm, we&amp;rsquo;re more interested
  in a systematic way of doing this. Fortunately,
  there&amp;rsquo;s an easy two-step process:
  &lt;ol&gt;
    &lt;li&gt;Turn the left side of \(A\) into a &lt;em&gt;unit upper triangular matrix&lt;/em&gt;,
      which means that all the elements on the main diagonal are
      \(1\), and all elements below the main diagonal are \(0\),
      i.e. that \(a_{ii} = 1\) for all \(i\), and \(a_{ij} = 0\) for
      all \(j &gt; i\).&lt;/li&gt;
    &lt;li&gt;Then turn the left side of \(A\) into the identity matrix.&lt;/li&gt;
  &lt;/ol&gt;
  This algorithm is called &lt;a href="https://en.wikipedia.org/wiki/Row_reduction"&gt;row reduction&lt;/a&gt;. The
  first step can be further broken down:
  &lt;ol type="a"&gt;
    &lt;li&gt;For each column \(i\) of the left side in ascending order:
      &lt;ol type="i"&gt;
        &lt;li&gt;If \(a_{ii}\) is zero, look at the rows below the
          \(i\)th row for a row \(j &gt; i\) such that \(a_{ji} \ne
          0\), and swap rows \(i\) and \(j\). If no such row
          exists, return an error, as that means that \(A\) is
          non-invertible.&lt;/li&gt;
        &lt;li&gt;Divide the \(i\)th row by \(a_{ii}\), so that \(a_{ii}
          = 1\).&lt;/li&gt;
        &lt;li&gt;For each row \(j &gt; i\), subtract \(a_{ji}\) times the
          \(i\)th row from it, which will set \(a_{ji}\) to \(0\).&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
  The second step can be similarly broken down:
  &lt;ol type="a"&gt;
    &lt;li&gt;For each column \(i\) of the left side, in order:
      &lt;ol type="i"&gt;
        &lt;li&gt;For each row \(j &amp;lt; i\), subtract \(a_{ji}\) times the
          \(i\)th row from it, which will set \(a_{ji}\) to \(0\).&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

&lt;p&gt;Note that we&amp;rsquo;re assuming that all arithmetic is
  exact, i.e. we use a arbitrary-precision rational number
  type. If we use floating point numbers, we&amp;rsquo;d have to
  worry a lot more about the order in which we do operations
  and numerical stability.&lt;/p&gt;



&lt;div class="interactive-example" id="matrixInverseDemo"&gt;
  &lt;h3&gt;Example 3: Matrix inversion via row reduction&lt;/h3&gt;
  Let

  &lt;pre&gt;    / 0 2 2 \
M = | 3 4 5 |
    \ 6 6 7 /.&lt;/pre&gt;

  The initial augmented matrix &lt;var&gt;A&lt;/var&gt; is

  &lt;pre&gt;/ 0 2 2 | 1 0 0 \
| 3 4 5 | 0 1 0 |
\ 6 6 7 | 0 0 1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;00&lt;/sub&gt; to be non-zero, so swap rows &lt;span class="swap-row-a"&gt;0&lt;/span&gt; and &lt;span class="swap-row-b"&gt;1&lt;/span&gt;:

  &lt;pre&gt;/ &lt;span class="swap-row-a"&gt;0 2 2&lt;/span&gt; | &lt;span class="swap-row-a"&gt;1 0 0&lt;/span&gt; \     / &lt;span class="swap-row-b"&gt;3 4 5&lt;/span&gt; | &lt;span class="swap-row-b"&gt;0 1 0&lt;/span&gt; \
| &lt;span class="swap-row-b"&gt;3 4 5&lt;/span&gt; | &lt;span class="swap-row-b"&gt;0 1 0&lt;/span&gt; | --&gt; | &lt;span class="swap-row-a"&gt;0 2 2&lt;/span&gt; | &lt;span class="swap-row-a"&gt;1 0 0&lt;/span&gt; |
\ 6 6 7 | 0 0 1 /     \ 6 6 7 | 0 0 1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;00&lt;/sub&gt; to be 1, so divide row &lt;span class="divide-row"&gt;0&lt;/span&gt; by 3:

  &lt;pre&gt;/ &lt;span class="divide-row"&gt;3 4 5&lt;/span&gt; | &lt;span class="divide-row"&gt;0 1 0&lt;/span&gt; \     / &lt;span class="divide-row"&gt;1 4/3 5/3&lt;/span&gt; | &lt;span class="divide-row"&gt;0 1/3 0&lt;/span&gt; \
| 0 2 2 | 1 0 0 | --&gt; | 0  2   2  | 1  0  0 |
\ 6 6 7 | 0 0 1 /     \ 6  6   7  | 0  0  1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;20&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;0&lt;/span&gt; scaled by 6 from row &lt;span class="subtract-scaled-row-dest"&gt;2&lt;/span&gt;:

  &lt;pre&gt;/ &lt;span class="subtract-scaled-row-src"&gt;1 4/3 5/3&lt;/span&gt; | &lt;span class="subtract-scaled-row-src"&gt;0 1/3 0&lt;/span&gt; \     / 1 4/3 5/3 | 0 1/3 0 \
| 0  2   2  | 1  0  0 | --&gt; | 0  2   2  | 1  0  0 |
\ &lt;span class="subtract-scaled-row-dest"&gt;6  6   7&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;0  0  1&lt;/span&gt; /     \ &lt;span class="subtract-scaled-row-dest"&gt;0 -2  -3&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;0 -2  1&lt;/span&gt; /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;11&lt;/sub&gt; to be 1, so divide row &lt;span class="divide-row"&gt;1&lt;/span&gt; by 2:

  &lt;pre&gt;/ 1 4/3 5/3 |  0  1/3 0 \     / 1 4/3 5/3 |  0  1/3 0 \
| &lt;span class="divide-row"&gt;0  2   2 &lt;/span&gt; | &lt;span class="divide-row"&gt; 1   0  0&lt;/span&gt; | --&gt; | &lt;span class="divide-row"&gt;0  1   1 &lt;/span&gt; | &lt;span class="divide-row"&gt;1/2  0  0&lt;/span&gt; |
\ 0 -2  -3  |  0  -2  1 /     \ 0 -2  -3  |  0  -2  1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;21&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;1&lt;/span&gt; scaled by &amp;minus;2 from row &lt;span class="subtract-scaled-row-dest"&gt;2&lt;/span&gt;:

  &lt;pre&gt;/ 1 4/3 5/3 |  0  1/3 0 \     / 1 4/3 5/3 |  0  1/3 0 \
| &lt;span class="subtract-scaled-row-src"&gt;0  1   1&lt;/span&gt;  | &lt;span class="subtract-scaled-row-src"&gt;1/2  0  0&lt;/span&gt; | --&gt; | 0  1   1  | 1/2  0  0 |
\ &lt;span class="subtract-scaled-row-dest"&gt;0 -2  -3&lt;/span&gt;  |  &lt;span class="subtract-scaled-row-dest"&gt;0  -2  1&lt;/span&gt; /     \ &lt;span class="subtract-scaled-row-dest"&gt;0  0  -1&lt;/span&gt;  |  &lt;span class="subtract-scaled-row-dest"&gt;1  -2  1&lt;/span&gt; /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;22&lt;/sub&gt; to be 1, so divide row &lt;span class="divide-row"&gt;2&lt;/span&gt; by &amp;minus;1, which makes the left side of &lt;var&gt;A&lt;/var&gt; a
  unit upper triangular matrix:

  &lt;pre&gt;/ 1 4/3 5/3 |  0  1/3 0 \     / 1 4/3 5/3 |  0  1/3 0 \
| 0  1   1  | 1/2  0  0 | --&gt; | 0  1   1  | 1/2  0  0 |
\ &lt;span class="divide-row"&gt;0  0  -1 &lt;/span&gt; | &lt;span class="divide-row"&gt; 1  -2  1&lt;/span&gt; /     \ &lt;span class="divide-row"&gt;0  0   1 &lt;/span&gt; | &lt;span class="divide-row"&gt;-1   2 -1&lt;/span&gt; /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;12&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;2&lt;/span&gt; from row &lt;span class="subtract-scaled-row-dest"&gt;1&lt;/span&gt;:

  &lt;pre&gt;/ 1 4/3 5/3 |  0  1/3 0 \     / 1 4/3 5/3 |  0  1/3 0 \
| &lt;span class="subtract-scaled-row-dest"&gt;0  1   1&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;1/2  0  0&lt;/span&gt; | --&gt; | &lt;span class="subtract-scaled-row-dest"&gt;0  1   0&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;3/2 -2  1&lt;/span&gt; |
\ &lt;span class="subtract-scaled-row-src"&gt;0  0   1&lt;/span&gt;  | &lt;span class="subtract-scaled-row-src"&gt;-1   2 -1&lt;/span&gt; /     \ 0  0   1  | -1   2 -1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;02&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;2&lt;/span&gt; scaled by 5/3 from row &lt;span class="subtract-scaled-row-dest"&gt;0&lt;/span&gt;:

  &lt;pre&gt;/ &lt;span class="subtract-scaled-row-dest"&gt;1 4/3 5/3&lt;/span&gt; |  &lt;span class="subtract-scaled-row-dest"&gt;0  1/3 0&lt;/span&gt; \     / &lt;span class="subtract-scaled-row-dest"&gt;1 4/3  0&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;5/3 -3 5/3&lt;/span&gt; \
| 0  1   0  | 3/2 -2  1 | --&gt; | 0  1   0  | 3/2 -2  1  |
\ &lt;span class="subtract-scaled-row-src"&gt;0  0   1&lt;/span&gt;  | &lt;span class="subtract-scaled-row-src"&gt;-1   2 -1&lt;/span&gt; /     \ 0  0   1  | -1   2 -1  /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;01&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;1&lt;/span&gt; scaled by 4/3 from row &lt;span class="subtract-scaled-row-dest"&gt;0&lt;/span&gt;, which makes the left side of &lt;var&gt;A&lt;/var&gt; the identity matrix:

  &lt;pre&gt;/ &lt;span class="subtract-scaled-row-dest"&gt;1 4/3  0&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;5/3  -3 5/3&lt;/span&gt; \     / &lt;span class="subtract-scaled-row-dest"&gt;1  0   0&lt;/span&gt;  | &lt;span class="subtract-scaled-row-dest"&gt;-1/3 -1/3 1/3&lt;/span&gt; \
| &lt;span class="subtract-scaled-row-src"&gt;0  1   0&lt;/span&gt;  | &lt;span class="subtract-scaled-row-src"&gt;3/2 -2   1&lt;/span&gt;  | --&gt; | 0  1   0  |  3/2  -2   1  |
\ 0  0   1  | -1   2  -1  /     \ 0  0   1  |  -1    2  -1  /.&lt;/pre&gt;

  Since the left side of &lt;var&gt;A&lt;/var&gt; is the identity matrix, the right side of &lt;var&gt;A&lt;/var&gt; is &lt;var&gt;M&lt;/var&gt;&lt;sup&gt;-1&lt;/sup&gt;. Therefore,

  &lt;pre&gt;         / -1/3 -1/3 1/3 \
M^{-1} = |  3/2  -2   1  |
         \  -1    2  -1  /.&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now notice one thing: if \(M\) has a row that is proportional to
  another row, then row reduction would eventually zero out one of the
  rows, causing the algorithm to fail, and signaling that \(M\) is
  non-invertible. In fact, a stronger statement is true: \(M\) has a
  row that can be expressed as a linear combination of other rows of
  \(M\) exactly when \(M\) is non-invertible. Informally, this means
  that the linear function corresponding to \(M\) has one of its
  outputs redundant with the other outputs, so it is essentially a a
  linear function taking \(n\) inputs to fewer than \(n\) outputs, and
  such functions aren&amp;rsquo;t invertible.&lt;/p&gt;

&lt;p&gt;This gets us a partial explanation for what &amp;ldquo;sufficiently
  different&amp;rdquo; means for our parity functions. If one parity
  function is a linear combination of other parity functions, then it
  is redundant, and therefore not &amp;ldquo;sufficiently
  different&amp;rdquo;. Therefore, we want our parity matrix \(P\) to be
  such that no row can be expressed as a linear combination of other
  rows.&lt;/p&gt;

&lt;p&gt;However, this criterion for \(P\) isn&amp;rsquo;t quite enough
  to guarantee that all possible matrices \(M\) computed as
  part of &lt;code&gt;ReconstructData&lt;/code&gt; are invertible. For example,
  this criterion holds for the identity matrix \(I_n\), but if \(n &gt;
  1\) and you pick \(I_n\) as the parity matrix for \(n = m\), you can
  certainly end up with a constructed matrix \(M\) with repeated rows,
  since you&amp;rsquo;re starting by appending another copy of \(I_n\) on
  top of \(P = I_n\)! This explains in a different way why simply
  making a copy of the original data files makes for a poor erasure
  code, unless of course you only have one data file. We&amp;rsquo;re led
  to our next topic: what makes a parity matrix &amp;ldquo;optimal&amp;rdquo;?&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;7. Optimal parity matrices&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Recall from above that we form the square matrix

  \[
    M =
    \begin{pmatrix}
      e_{j_0} \\
      \vdots \\
      e_{j_{n-k-1}} \\
      p_0 \\
      \vdots \\
      p_{k-1}
    \end{pmatrix}
  \]

  by prepending some rows of the identity matrix to the first
  \(k\) rows of the parity matrix. We can generalize this a
  bit more, since we don&amp;rsquo;t have to take the first \(k\)
  rows, but instead can take any \(k\) rows of the parity
  matrix, whose indices we denote here as \(l_0, \dotsc, l_{k-1}\):

  \[
  M =
  \begin{pmatrix}
    e_{j_0} \\
    \vdots \\
    e_{j_{n-k-1}} \\
    p_{l_0} \\
    \vdots \\
    p_{l_{k-1}}
  \end{pmatrix}\text{.}
  \]

  So we want to construct \(P\) so that any such square matrix
  \(M\) formed from the rows of \(P\) is invertible. Therefore,
  we call a parity matrix \(P\) &lt;em&gt;optimal&lt;/em&gt; if it satisfies this
  criterion.&lt;/p&gt;

&lt;div class="p"&gt;Fortunately, there is a simpler criterion for optimal parity
  matrices. First, define a &lt;a href="https://en.wikipedia.org/wiki/Matrix_(mathematics)#Submatrix"&gt;&lt;em&gt;submatrix&lt;/em&gt;&lt;/a&gt;
  of a matrix \(P\) to be a matrix that you get by deleting
  any number of rows or columns, and call a matrix &lt;em&gt;non-empty&lt;/em&gt; if
  it has at least one row and one column. Then:

  &lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Theorem&amp;nbsp;1&lt;/span&gt;.)
    A parity matrix \(P\) is optimal exactly when any non-empty square
    submatrix of \(P\) is invertible.&lt;sup&gt;&lt;a href="#fn5" id="r5"&gt;[5]&lt;/a&gt;&lt;/sup&gt;&lt;/div&gt;

Note that this criterion is stronger than the one in the previous
  section, where we want a parity matrix \(P\) to have no row that can
  be expressed as a linear combination of other rows. That is, if any
  non-empty square submatrix of \(P\) is invertible, that means that
  no row can be expressed as a linear combination of other rows.&lt;sup&gt;&lt;a href="#fn6" id="r6"&gt;[6]&lt;/a&gt;&lt;/sup&gt; However, it is possible to have a matrix
  \(P\) where no row can be expressed as a linear combination of
  other rows, but which is not optimal. We&amp;rsquo;ve already seen an
  example above: \(I_n\) for \(n \gt 1\), and indeed,

  \[
    I_2 =
    \begin{pmatrix}
      1 &amp; 0 \\
      0 &amp; 1
    \end{pmatrix}\text{,}
  \]

  has the \(1 \times 1\) non-invertible submatrix
  \(\begin{pmatrix} 0 \end{pmatrix}\).&lt;/div&gt;

&lt;div class="interactive-example"&gt;
  &lt;h3&gt;Example 4: A optimal parity matrix for \(m = 2\)&lt;/h3&gt;
  &lt;p&gt;Recall the parity matrix

    \[
      P =
      \begin{pmatrix}
        1 &amp; 1 &amp; 1 \\
        1 &amp; 2 &amp; 3
      \end{pmatrix}
    \]

    that we were using for our \(n = 3, m = 2\) example. For any \(n\),
    this matrix looks like

    \[
      P =
      \begin{pmatrix}
        1 &amp; 1 &amp; \cdots &amp; 1 \\
        1 &amp; 2 &amp; \cdots &amp; n-1
      \end{pmatrix}\text{.}
    \]

    A \(1 \times 1\) matrix is invertible exactly when its single
    element is non-zero, so any \(1 \times 1\) submatrix of \(P\) is
    invertible. Any \(2 \times 2\) submatrix of \(P\) looks like

    \[
      A =
      \begin{pmatrix}
        1 &amp; 1 \\
        a &amp; b
      \end{pmatrix}
    \]

    for \(a \ne b\), which, using the &lt;a href="https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_2_.C3.97_2_matrices"&gt;formula for inverses of \(2 \times 2\) matrices&lt;/a&gt;, has inverse

    \[
      A^{-1} = \begin{pmatrix} b/(b-a) &amp; -1/(b-a) \\ -a/(b-a) &amp; 1/(b-a) \end{pmatrix}\text{.}

    \]
    These are all the possible square submatrices of \(P\), so
    therefore this \(P\) is a optimal parity matrix for \(m = 2\).&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Then, finally, we now have a complete definition of what makes a
list of parity functions &amp;ldquo;sufficiently different&amp;rdquo;; it is
exactly when the corresponding parity matrix is optimal as we&amp;rsquo;ve
defined it above.&lt;/p&gt;

&lt;p&gt;Now this leads us to the question: how do we find such optimal
matrices? Fortunately, there&amp;rsquo;s a whole class of matrices that
are optimal: the &lt;em&gt;Cauchy matrices&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let \(a_0, \dotsc, a_{m+n-1}\) be a sequence of distinct
  integers, meaning that no two \(a_i\) are equal, and let
  \(x_0, \dotsc, x_{m-1}\) be the first \(m\) integers of \(a_i\) with \(y_0, \dotsc, y_{n-1}\)
  the remaining integers. Then form the \(m \times n\)
  matrix \(A\) by setting its elements according to:

  \[
    a_{ij} = \frac{1}{x_i - y_j}\text{,}
  \]

  which is always defined since the denominator is never zero, by the distinctness of the \(a_i\). Then \(A\) is a &lt;em&gt;Cauchy matrix&lt;/em&gt;.&lt;/p&gt;

&lt;div class="p"&gt;What makes Cauchy matrices useful is the following theorem:

&lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Theorem&amp;nbsp;2&lt;/span&gt;.)
  Any non-empty square Cauchy matrix is invertible.&lt;/div&gt;

Combining this with the simple fact that any submatrix of a
  Cauchy matrix is also a Cauchy matrix, we get:

&lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Corollary&amp;nbsp;1&lt;/span&gt;.)
  Any non-empty square submatrix of a Cauchy matrix is
  invertible, and thus any Cauchy parity matrix is optimal.&lt;/div&gt;
&lt;/div&gt;

&lt;div class="interactive-example" id="cauchyMatrixDemo"&gt;
  &lt;h3&gt;Example 5: Cauchy matrices&lt;/h3&gt;
  Let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;x&lt;/var&gt; = [ 1, 2, 3 ]
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;y&lt;/var&gt; = [ -1, 4, 0 ].
  &lt;/span&gt;
  Then, the Cauchy matrix constructed from
  &lt;var&gt;x&lt;/var&gt; and &lt;var&gt;y&lt;/var&gt; is

  &lt;pre&gt;/ 1/2 -1/3  1  \
| 1/3 -1/2 1/2 |
\ 1/4  -1  1/3 /,&lt;/pre&gt;

  which has inverse

  &lt;pre&gt;/ -36/5 96/5 -36/5 \
| -3/10  9/5  -9/5 |
\  9/2  -9     3   /.&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Therefore, to generate a optimal parity matrix for any \((n,
  m)\), all we need to do is to generate an \(m \times n\)
  Cauchy matrix. We can pick any sequence of distinct \(m +
  n\) integers, so for simplicity let&amp;rsquo;s just use

  \[
    x_i = n + i \quad \text{and} \quad y_i = i\text{.}
  \]&lt;/p&gt;

&lt;div class="interactive-example"&gt;
  &lt;h3&gt;Example 6: Cauchy parity matrices for \(m = 2\)&lt;/h3&gt;
  &lt;p&gt;For \(n = 3, m = 2\), we have the sequences

    \[
      x_0 = 3, x_1 = 4 \quad \text{and} \quad y_0 = 0, y_1 = 1, y_2 = 2\text{,}
    \]

    so the corresponding Cauchy parity matrix is

    \[
      P = 
      \begin{pmatrix}
        1/3 &amp; 1/2 &amp; 1 \\
        1/4 &amp; 1/3 &amp; 1/2
      \end{pmatrix}\text{.}
    \]

    Similarly, for any \(n\),

    \[
      P =
      \begin{pmatrix}
        1/n &amp; \cdots &amp; 1/2 &amp; 1 \\
        1/{n + 1} &amp; \cdots &amp; 1/3 &amp; 1/2
      \end{pmatrix}\text{.}
    \]

    All entries of \(P\) are non-zero, so any \(1 \times 1\)
    submatrix of \(P\) is invertible. Any \(2 \times 2\) submatrix
    of \(P\) looks like

    \[
      A =
      \begin{pmatrix}
        1/a &amp; 1/b \\
        1/(a+1) &amp; 1/(b+1)
      \end{pmatrix}
    \]

    for \(a \ne b\), which, using the &lt;a href="https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_2_.C3.97_2_matrices"&gt;formula for inverses of \(2 \times 2\) matrices&lt;/a&gt;, has inverse

    \[
      A^{-1} =
      \begin{pmatrix}
        \frac{ab(a+1)}{b-a} &amp; -\frac{a(a+1)(b+1)}{b-a} \\
        -\frac{ab(b+1)}{b-a} &amp; \frac{b(a+1)(b+1)}{b-a}
      \end{pmatrix}\text{.}
    \]

    These are all the possible square submatrices of \(P\), so
    therefore this \(P\) is a optimal parity matrix for \(m = 2\).&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Note that our first parity matrix for \(n = 3, m = 2\)
  isn&amp;rsquo;t a Cauchy matrix, since no Cauchy matrix can have
  repeating elements in a single row. That means that there
  are other possible optimal parity matrices that aren&amp;rsquo;t
  Cauchy matrices.&lt;sup&gt;&lt;a href="#fn7" id="r7"&gt;[7]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Also, our previous parity matrices had integers, and
  Cauchy matrices have rational numbers (i.e.,
  fractions). This means that our parity numbers are now
  fractions. This isn&amp;rsquo;t a serious difference, though,
  since we&amp;rsquo;d have to deal with fractions when
  computing matrix inverses anyway. You could also change a
  parity matrix with fractions into one without by simply
  multiplying the entire matrix by some non-zero number that gets
  rid of all the fractions, which doesn&amp;rsquo;t change the
  optimality of the matrix. For example, we can multiply

  \[
    \begin{pmatrix}
      1/3 &amp; 1/2 &amp; 1 \\
      1/4 &amp; 1/3 &amp; 1/2
    \end{pmatrix}
  \]

  by \(12\) to get the equivalent parity matrix

  \[
    \begin{pmatrix}
      4 &amp; 6 &amp; 12 \\
      3 &amp; 4 &amp; 6
    \end{pmatrix}\text{.}
  \]
&lt;/p&gt;

&lt;p&gt;Now our only remaining missing piece is this: how do we
  compute parity bytes instead of parity numbers? Answering
  this would render the above discussion moot. However, to do
  so, we first have to take another look at how we&amp;rsquo;re
  doing linear algebra.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;8. Linear algebra over fields&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;We ultimately want our parity numbers to be parity bytes, which
  means that we want to work with matrices of bytes instead of
  matrices of rational numbers. In order to do that, we need to define
  an interface for matrix elements that preserves the operations and
  properties we care about, and then we have to figure out how to
  implement that interface using bytes.&lt;/p&gt;

&lt;p&gt;Looking at the rule for matrix multiplication, we need to be able
  to add and multiply matrix elements. Looking at how we do matrix
  inversion, we also need to be able to subtract and divide matrix
  elements. Finally, there are certain properties that hold for
  rational numbers that we implicitly assume when doing matrix
  operations, but that we have to make explicit for matrix elements.&lt;/p&gt;

&lt;div class="p"&gt;This leads us to the concept of a &lt;em&gt;field&lt;/em&gt;, which
  essentially defines the interface that matrix elements
  should implement. Here it is:

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;interface Field&amp;lt;T&amp;gt; {
  static Zero: T, One: T

  plus(b: T): T
  negate(): T

  times(b: T): T
  reciprocate(): T

  equals(b: T): bool

  minus(b: T) = this.plus(b.negate())
  dividedBy(b: T) = this.times(b.reciprocate())
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We need to be able to add and multiply field elements,
  which we&amp;rsquo;ll denote generically by \(\oplus\) and \(\otimes\). We
  also need to be able to take the negation (additive inverse) of an element \(x\),
  which we&amp;rsquo;ll denote by \(-x\), and the reciprocal (multiplicative inverse) of a
  non-zero element \(x\), which we&amp;rsquo;ll denote by
  \(x^{-1}\). Then we can define subtraction of field elements to be

  \[
    a \ominus b = a \oplus -b
  \]

  and division of field elements to be

  \[
    a \cldiv b = a \otimes b^{-1}\text{,}
  \]

  when \(b \ne 0\).&lt;/p&gt;

&lt;div class="p"&gt;Also, an implementation of &lt;code&gt;Field&lt;/code&gt; must satisfy further
properties, which are copied from the number laws you learn in school:

&lt;ul&gt;
  &lt;li&gt;Identities: \(a \oplus 0 = a \otimes 1 = a\).&lt;/li&gt;
  &lt;li&gt;Inverses: \(a \oplus -a = 0\), and for \(a \ne 0\), \(a
    \otimes a^{-1} = 1\).&lt;/li&gt;
  &lt;li&gt;Associativity: \((a \oplus b) \oplus c = a \oplus (b
    \oplus c)\), and \((a \otimes b) \otimes c = a \otimes (b
    \otimes c)\).&lt;/li&gt;
  &lt;li&gt;Commutativity: \(a \oplus b = b \oplus a\), and \(a \otimes
    b = b \otimes a\).&lt;/li&gt;
  &lt;li&gt;Distributivity: \(a \otimes (b \oplus c) = (a \otimes b) \oplus (a \otimes c)\).&lt;/li&gt;
&lt;/ul&gt;

Of the above, guaranteeing the existence of reciprocals of
  non-zero elements is usually the non-trivial part. Now the
  rational numbers satisfy all of the above, since

  \[
    (p/q)^{-1} = q/p\text{,}
  \]

  so we say that they &lt;em&gt;form a field&lt;/em&gt;. However, the integers
  &lt;em&gt;do not&lt;/em&gt; form a field, since for example \(2\) has no
  integer reciprocal; only \(1\) and \(-1\) have integer
  reciprocals. Furthermore, as we saw above, the integers
  modulo \(256\), i.e. the numbers from \(0\) to \(255\) with
  standard arithmetic operations modulo \(256\), do not form a
  field, as we saw earlier, since \((2 \cdot b) \bmod 256 \ne
  1\) for any \(b\).&lt;/div&gt;

&lt;div class="p"&gt;However, we can construct a field with \(257\) elements, using the
fact that \(257\) is a prime number, and the following theorem:

&lt;div class="theorem"&gt;(&lt;span class="theorem-name" id="theorem-3"&gt;Theorem&amp;nbsp;3&lt;/span&gt;.)
  Given a prime number \(p\), for every integer \(0 \lt a \lt p\),
  there is exactly one \(0 \lt b \lt p\) such that \((a \cdot b) \bmod
  p = 1\).&lt;/div&gt;

There are clever ways to find multiplcative inverses mod \(p\), but
  since \(257\) is so small, we can just brute-force it. So an
  implementation would look like:

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;class Field257Element : implements Field&amp;lt;Field257Element&amp;gt; {
  plus(b) { return (this + b) % 257 }
  negate() { return (257 - this) }
  times(b) { return (this * b) % 257 }
  reciprocate() {
    if (this == 0) { return Error }
    for i := 0 to 256 {
      if (this.times(b) == 1) { return i; }
    }
    return Error
  }
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class="interactive-example" id="field257Demo"&gt;
  &lt;h3&gt;Example 7: Field with 257 elements&lt;/h3&gt;
  Denote operations on the field with 257
  elements by a &lt;sub&gt;257&lt;/sub&gt; subscript, and let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; = 23
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;b&lt;/var&gt; = 54.
  &lt;/span&gt;
  Then
  &lt;ul&gt;
    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; +&lt;sub&gt;257&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = (23 + 54) mod 257 = &lt;span class="result"&gt;77&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &amp;minus;&lt;sub&gt;257&lt;/sub&gt;&lt;var&gt;b&lt;/var&gt; = (257 &amp;minus; 54) mod 257 = &lt;span class="result"&gt;203&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;minus;&lt;sub&gt;257&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = &lt;var&gt;a&lt;/var&gt; +&lt;sub&gt;257&lt;/sub&gt; &amp;minus;&lt;sub&gt;257&lt;/sub&gt;&lt;var&gt;b&lt;/var&gt; = (23 + 203) mod 257 = &lt;span class="result"&gt;226&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;times;&lt;sub&gt;257&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = (23 &amp;times; 54) mod 257 = &lt;span class="result"&gt;214&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        54 &amp;times;&lt;sub&gt;257&lt;/sub&gt; 119 = 1,
      &lt;/span&gt;
      so
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;b&lt;/var&gt;&lt;sup&gt;-1&lt;/sup&gt;&lt;sub&gt;257&lt;/sub&gt; = &lt;span class="result"&gt;119&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;divide;&lt;sub&gt;257&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = &lt;var&gt;a&lt;/var&gt; &amp;times;&lt;sub&gt;257&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt;&lt;sup&gt;-1&lt;/sup&gt;&lt;sub&gt;257&lt;/sub&gt; = (23 &amp;times; 119) mod 257 = &lt;span class="result"&gt;167&lt;/span&gt;,
      &lt;/span&gt;
      and indeed
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;b&lt;/var&gt; &amp;times;&lt;sub&gt;257&lt;/sub&gt; (&lt;var&gt;a&lt;/var&gt; &amp;divide;&lt;sub&gt;257&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt;) = (54 &amp;times; 167) mod 257 = 23 = &lt;var&gt;a&lt;/var&gt;.
      &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;


&lt;div class="p"&gt;So this gets us closer, since we can use &lt;code&gt;Field257Element&lt;/code&gt; instead
of a rational number type when implementing &lt;code&gt;ComputeParity&lt;/code&gt; and &lt;code&gt;ReconstructData&lt;/code&gt;,
and if we&amp;rsquo;ve abstracted our &lt;code&gt;Matrix&lt;/code&gt; type correctly, almost everything should just work. However, there &lt;em&gt;is&lt;/em&gt; one
thing we need to check: Are Cauchy parity matrices still
optimal if we use fields other than the rational numbers? Fortunately, the answer is yes:

&lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Theorem&amp;nbsp;1, general version&lt;/span&gt;.)
  A parity matrix \(P\) over any field is optimal exactly when any
  non-empty square submatrix of \(P\) is invertible.&lt;/div&gt;

&lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Theorem&amp;nbsp;2, general version&lt;/span&gt;.)
  Any non-empty square Cauchy matrix over any field is invertible.&lt;/div&gt;

&lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Corollary&amp;nbsp;1, general version&lt;/span&gt;.)
  Any square submatrix of a Cauchy matrix over any field is
  invertible, and thus any Cauchy parity matrix over any field is
  optimal.&lt;/div&gt;

However, note that to construct an \(m \times n\) Cauchy matrix, we
  need \(m + n\) distinct elements. So if we&amp;rsquo;re working with a
  field with \(257\) elements, then this imposes the condition that
  \(m + n \le 257\), i.e. using a finite field limits the number of
  data bytes and parity numbers you can have.&lt;/div&gt;

&lt;p&gt;Now the question remains: can we construct a field with \(256\)
  elements? As we saw above, we can&amp;rsquo;t do so the same way as we
  constructed the field with \(257\) elements. In fact, we need to
  start with defining different arithmetic operations on the
  integers. This brings us to the topic of
  &lt;em&gt;binary carry-less arithmetic&lt;/em&gt;.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;9. Binary carry-less arithmetic&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;The basic idea with binary carry-less (which I&amp;rsquo;ll henceforth
  shorten to &amp;ldquo;carry-less&amp;rdquo;) arithmetic is to express all
  integers in binary, then perform all arithmetic operations using
  binary arithmetic, except ignoring all the carries.&lt;sup&gt;&lt;a href="#fn8" id="r8"&gt;[8]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;How does this work with addition? Let&amp;rsquo;s denote binary
  carry-less add as \(\clplus\),&lt;sup&gt;&lt;a href="#fn9" id="r9"&gt;[9]&lt;/a&gt;&lt;/sup&gt; and let&amp;rsquo;s see how it behaves on single binary digits:

  \[
    \begin{aligned}
      0 \clplus 0 &amp;= 0 \\
      0 \clplus 1 &amp;= 1 \\
      1 \clplus 0 &amp;= 1 \\
      1 \clplus 1 &amp;= 0\text{.}
    \end{aligned}
  \]

  This is just the exclusive or operation on bits, so if we do
  carry-less addition on any two integers, it turns out to be
  nothing but xor! Since xor can also be denoted by \(\clplus\),
  we can conveniently think of \(\clplus\) as meaning both carry-less
  addition and xor.&lt;/p&gt;
        
&lt;div class="interactive-example" id="carrylessAddDemo"&gt;
  &lt;h3&gt;Example 8: Carry-less addition&lt;/h3&gt;
  Let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; = 23
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;b&lt;/var&gt; = 54.
  &lt;/span&gt;
  Then, with carry-less arithmetic,
  &lt;pre&gt;  a = 23 =  10111b
^ b = 54 = 110110b
           -------
           100001b&lt;/pre&gt;
  so
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; &amp;oplus; &lt;var&gt;b&lt;/var&gt; = 100001&lt;sub&gt;b&lt;/sub&gt; =
    &lt;span class="result"&gt;33&lt;/span&gt;.
  &lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;What about subtraction? Recall that \((a \clplus b) \clplus
  b = a\) for any \(a\) and \(b\). Therefore, every element
  \(b\) is its own (carry-less binary) additive inverse, which
  means that \(a \clminus b = a \clplus b\), i.e. carry-less
  subtraction is also just xor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Carry-less_product"&gt;Carry-less multiplication&lt;/a&gt;
  isn&amp;rsquo;t as simple, but recall that binary multiplication
  is just adding shifted copies of \(a\) based on which bits
  are set in \(b\) (or vice versa). To do carry-less
  multiplication, just ignore carries when adding the shifted
  copies again, i.e. xor shifted copies instead of adding
  them.&lt;/p&gt;

&lt;div class="interactive-example" id="carrylessMulDemo"&gt;
  &lt;h3&gt;Example 9: Carry-less multiplication&lt;/h3&gt;
  Let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; = 23
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;b&lt;/var&gt; = 54.
  &lt;/span&gt;
  Then, with carry-less arithmetic,
  &lt;pre&gt;   a = 23 =       10111b
^* b = 54 =      110110b
            ------------
                 10111
          ^     10111
          ^   10111
          ^  10111
            ------------
             1111100010b&lt;/pre&gt;
  so
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; &amp;otimes; &lt;var&gt;b&lt;/var&gt; = 1111100010&lt;sub&gt;b&lt;/sub&gt; =
    &lt;span class="result"&gt;994&lt;/span&gt;.
  &lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Finally, we can define carry-less division with remainder. Binary
  division with remainder is subtracting shifted copies of \(b\) from
  \(a\) until you get a remainder less than the divisor; then
  carry-less binary division with remainder is xor-ing shifted copies
  of \(b\) with \(a\) until you get a remainder. However,
  there&amp;rsquo;s a subtlety; with carry-less arithmetic, it&amp;rsquo;s not
  enough to stop when the remainder (for that step) is less than the
  divisor, because if the highest set bit of the remainder is the same
  as the highest set bit of the divisor, you can still xor with the
  divisor one more time to yield a smaller number (which then becomes
  the final remainder).&lt;/p&gt;

&lt;p&gt;Consider the example below, where we&amp;rsquo;re dividing \(55\) by
  \(19\). The first remainder is \(17\), which is less than \(19\),
  but still shares the same highest set bit, so we can xor one more
  time with \(19\) to get the remainder \(2\).&lt;/p&gt;

&lt;div class="interactive-example" id="carrylessDivDemo"&gt;
  &lt;h3&gt;Example 10: Carry-less division&lt;/h3&gt;
  Let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; = 55
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;b&lt;/var&gt; = 19.
  &lt;/span&gt;
  Then, with carry-less arithmetic,
  &lt;pre&gt;                     11b
                --------
b = 19 = 10011b )110111b = 55 = a
               ^ 10011
                 -----
                  10001
                ^ 10011
                  -----
                     10b&lt;/pre&gt;
  so
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; &amp;amp;odiv &lt;var&gt;b&lt;/var&gt; = 11&lt;sub&gt;b&lt;/sub&gt; =
    &lt;span class="result"&gt;3&lt;/span&gt;
  &lt;/span&gt;
  with remainder
  &lt;span style="white-space: nowrap;"&gt;
    10&lt;sub&gt;b&lt;/sub&gt; = &lt;span class="result"&gt;2&lt;/span&gt;.
  &lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This leads to an interesting difference between the carry-less
  modulo operation and the standard modulo operation. If you mod by a
  number \(n\), you get \(n\) possible remainders, from \(0\) to \(n -
  1\). However, if you clmod (carry-less mod) by a number \(2^k \le n
  \lt 2^{k+1}\), you get \(2^k\) possible remainders, from \(0\) to
  \(2^k-1\), since those are the numbers whose highest set bit is
  lower than the highest set bit of \(n\).&lt;/p&gt;

&lt;p&gt;In particular, if you clmod by a number \(256 \le n &amp;lt;
  512\), you always get \(256\) possible remainders. This is
  very close to what we want&amp;mdash;now the hope is to find &lt;em&gt;some&lt;/em&gt; \(256
  \le n &amp;lt; 512\) so that doing binary carry-less arithmetic clmod
  \(n\) yields a field, which will then be a field with \(256\)
  elements!&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;10. The finite field with \(256\) elements&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Since there are only a few numbers between \(256\) and \(512\), we
  can just try each one of them to see if clmod-ing by one of them
  yields a field. However, with a bit of math, we can gain more
  insight into which numbers will work.&lt;/p&gt;

&lt;p&gt;Recall the situation with the standard arithmetic
  operations: arithmetic mod \(p\) yields a field exactly when
  \(p\) is prime.&lt;sup&gt;&lt;a href="#fn10" id="r10"&gt;[10]&lt;/a&gt;&lt;/sup&gt; But recall
  the definition of a prime number: it is an integer greater than
  \(1\) whose positive divisors are only itself and \(1\). Stated
  another way, a prime number is an integer \(p \gt 1\) that cannot be
  expressed as \(p = a \cdot b\), for \(a, b \gt 1\).&lt;/p&gt;

&lt;p&gt;Thus, the concept of a prime number is determined by the
  multiplication operation, and therefore we can define a
  &amp;ldquo;carry-less&amp;rdquo; prime number to be an integer \( p \gt 1\)
  that cannot be expressed as \(p = a \clmul b\), for \(a, b \gt 1\).&lt;sup&gt;&lt;a href="#fn11" id="r11"&gt;[11]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class="p"&gt;The only question remaining is whether there is an equivalent of &lt;a href="#theorem-3"&gt;Theorem&amp;nbsp;3&lt;/a&gt; for
  carry-less arithmetic. And indeed there is:

&lt;div class="theorem"&gt;(&lt;span class="theorem-name"&gt;Theorem&amp;nbsp;4&lt;/span&gt;.)
  Given a carry-less prime number \(2^k \lt p \le 2^{k+1}\), for every
  integer \(0 \lt a \lt 2^k\), there is a exactly one \(0 \lt b \lt
  2^k\) such that \((a \clmul b) \bclmod p = 1\).&lt;/div&gt;

Now we just need to find a carry-less prime number \(256
  \le p &amp;lt; 512\). However, the set of prime numbers and the
  set of carry-less prime numbers are not necessarily related,
  so for example, even though \(257\) is a prime number, it is &lt;em&gt;not&lt;/em&gt; a
  carry-less prime number.&lt;/div&gt;

&lt;p&gt;It is easy enough to test each number \(256 \le n &amp;lt; 512\) for
  carry-less primality though; doing so, we find the lowest one,
  \(283\).&lt;sup&gt;&lt;a href="#fn12" id="r12"&gt;[12]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class="p"&gt;So finally, we have a field with \(256\) elements: the
  integers with binary carry-less arithmetic clmod \(283\). An
  implementation would look like:

  &lt;pre class="code-container"&gt;&lt;code class="language-javascript"&gt;class Field256Element : implements Field&amp;lt;Field256Element&amp;gt; {
  plus(b) { return this ^ b }
  negate() { return b }
  times(b) { return clmod(clmul(this, b), 283) }
  reciprocate() {
    if (this == 0) { return Error }
    for i := 0 to 255 {
      if (this.times(b) == 1) { return i; }
    }
    return Error
  }
  ...
}&lt;/code&gt;&lt;/pre&gt;

  Similarly to how we find reciprocals mod \(257\), we brute-force
  finding reciprocals clmod \(283\) also.&lt;/div&gt;

&lt;div class="interactive-example" id="field256Demo"&gt;
  &lt;h3&gt;Example 11: Field with 256 elements&lt;/h3&gt;
  Denote operations on the field with 256
  elements by a &lt;sub&gt;256&lt;/sub&gt; subscript, and let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;a&lt;/var&gt; = 23
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;b&lt;/var&gt; = 54.
  &lt;/span&gt;
  Then
  &lt;ul&gt;
    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;oplus;&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = 23 &amp;oplus; 54 = &lt;span class="result"&gt;33&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &amp;amp;ominus&lt;sub&gt;256&lt;/sub&gt;&lt;var&gt;b&lt;/var&gt; = &lt;var&gt;b&lt;/var&gt; = &lt;span class="result"&gt;54&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;amp;ominus&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = &lt;var&gt;a&lt;/var&gt; &amp;oplus;&lt;sub&gt;256&lt;/sub&gt; &amp;amp;ominus&lt;sub&gt;256&lt;/sub&gt;&lt;var&gt;b&lt;/var&gt; = &lt;var&gt;a&lt;/var&gt; &amp;oplus;&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = &lt;span class="result"&gt;33&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;otimes;&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = (23 &amp;otimes; 54) clmod 283 = &lt;span class="result"&gt;207&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        54 &amp;otimes;&lt;sub&gt;256&lt;/sub&gt; 102 = 1,
      &lt;/span&gt;
      so
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;b&lt;/var&gt;&lt;sup&gt;-1&lt;/sup&gt;&lt;sub&gt;256&lt;/sub&gt; = &lt;span class="result"&gt;102&lt;/span&gt;;
      &lt;/span&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;a&lt;/var&gt; &amp;oslash;&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt; = &lt;var&gt;a&lt;/var&gt; &amp;otimes;&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt;&lt;sup&gt;-1&lt;/sup&gt;&lt;sub&gt;256&lt;/sub&gt; = (23 &amp;otimes; 102) clmod 283 = &lt;span class="result"&gt;19&lt;/span&gt;,
      &lt;/span&gt;
      and indeed
      &lt;span style="white-space: nowrap;"&gt;
        &lt;var&gt;b&lt;/var&gt; &amp;otimes;&lt;sub&gt;256&lt;/sub&gt; (&lt;var&gt;a&lt;/var&gt; &amp;oslash;&lt;sub&gt;256&lt;/sub&gt; &lt;var&gt;b&lt;/var&gt;) = (54 &amp;times; 19) clmod 283 = 23 = &lt;var&gt;a&lt;/var&gt;.
      &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;11. The full algorithm&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Now we have all the pieces we need to construct erasure codes for
  any \((n, m)\) such that \(m + n \le 256\). First, we can compute an
  \(m \times n\) Cauchy parity matrix over the field with \(256\)
  elements. (Recall that this needs \(m + n\) distinct field elements,
  which is what imposes the condition \(m + n \le 256\).)&lt;/p&gt;

&lt;div class="interactive-example" id="cauchyMatrixDemoGeneral"&gt;
  &lt;h3&gt;Example 12: Cauchy matrices in general&lt;/h3&gt;
  Working over the field with 256 elements, let
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;x&lt;/var&gt; = [ 1, 2, 3 ]
  &lt;/span&gt;
  and
  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;y&lt;/var&gt; = [ 4, 5, 6 ].
  &lt;/span&gt;
  Then, the Cauchy matrix constructed from
  &lt;var&gt;x&lt;/var&gt; and &lt;var&gt;y&lt;/var&gt; is
  &lt;pre&gt;/  82 203 209 \
| 123 209 203 |
\ 209 123  82 /,&lt;/pre&gt;
  which has inverse
  &lt;pre&gt;/ 130  31 176 \
| 252 219  31 |
\ 108 252 130 /.&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Then we can implement matrix multiplication over arbitrary fields,
  and thus we can implement &lt;code&gt;ComputeParity&lt;/code&gt;.&lt;/p&gt;

&lt;div class="interactive-example" id="computeParityDetailDemo"&gt;
  &lt;h3&gt;Example 13: &lt;code&gt;ComputeParity&lt;/code&gt; in detail&lt;/h3&gt;
  Let

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;d&lt;/var&gt; = [ da, db, 0d ]
  &lt;/span&gt;

  be the input data bytes and let

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;m&lt;/var&gt; = 2
  &lt;/span&gt;

  be the desired parity byte count. Then, with the input byte
  count

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;n&lt;/var&gt; = 3,
  &lt;/span&gt;

  the

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;m&lt;/var&gt; &amp;times; &lt;var&gt;n&lt;/var&gt;
  &lt;/span&gt;

  Cauchy parity matrix computed using

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;x&lt;/var&gt;&lt;sub&gt;i&lt;/sub&gt; = &lt;var&gt;n&lt;/var&gt; + &lt;var&gt;i&lt;/var&gt;
  &lt;/span&gt;

  and

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;y&lt;/var&gt;&lt;sub&gt;i&lt;/sub&gt; = &lt;var&gt;i&lt;/var&gt;
  &lt;/span&gt;

  is
  &lt;pre&gt;/ f6 8d 01 \
\ cb 52 7b /.&lt;/pre&gt;
  Therefore, the parity bytes are computed as
  &lt;pre&gt;                _    _     _    _
/ f6 8d 01 \   |  da  |   |  52  |
\ cb 52 7b / * |  db  | = |_ 0c _|,
               |_ 0d _|&lt;/pre&gt;
  and thus the output parity bytes are

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;p&lt;/var&gt; = [ &lt;span class="result"&gt;52&lt;/span&gt;, &lt;span class="result"&gt;0c&lt;/span&gt; ].
  &lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Then we can implement matrix inversion using row reduction over
  arbitrary fields.&lt;/p&gt;

&lt;div class="interactive-example" id="matrixInverseDemoGeneral"&gt;
  &lt;h3&gt;Example 14: Matrix inversion via row reduction in general&lt;/h3&gt;
  Working over the field with 256 elements, let

  &lt;pre&gt;    / 0 2 2 \
M = | 3 4 5 |
    \ 6 6 7 /.&lt;/pre&gt;

  The initial augmented matrix &lt;var&gt;A&lt;/var&gt; is

  &lt;pre&gt;/ 0 2 2 | 1 0 0 \
| 3 4 5 | 0 1 0 |
\ 6 6 7 | 0 0 1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;00&lt;/sub&gt; to be non-zero, so swap rows &lt;span class="swap-row-a"&gt;0&lt;/span&gt; and &lt;span class="swap-row-b"&gt;1&lt;/span&gt;:

  &lt;pre&gt;/ &lt;span class="swap-row-a"&gt;0 2 2&lt;/span&gt; | &lt;span class="swap-row-a"&gt;1 0 0&lt;/span&gt; \     / &lt;span class="swap-row-b"&gt;3 4 5&lt;/span&gt; | &lt;span class="swap-row-b"&gt;0 1 0&lt;/span&gt; \
| &lt;span class="swap-row-b"&gt;3 4 5&lt;/span&gt; | &lt;span class="swap-row-b"&gt;0 1 0&lt;/span&gt; | --&gt; | &lt;span class="swap-row-a"&gt;0 2 2&lt;/span&gt; | &lt;span class="swap-row-a"&gt;1 0 0&lt;/span&gt; |
\ 6 6 7 | 0 0 1 /     \ 6 6 7 | 0 0 1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;00&lt;/sub&gt; to be 1, so divide row &lt;span class="divide-row"&gt;0&lt;/span&gt; by 3:

  &lt;pre&gt;/ &lt;span class="divide-row"&gt;3 4 5&lt;/span&gt; | &lt;span class="divide-row"&gt;0 1 0&lt;/span&gt; \     / &lt;span class="divide-row"&gt;1 245 3&lt;/span&gt; | &lt;span class="divide-row"&gt;0 246 0&lt;/span&gt; \
| 0 2 2 | 1 0 0 | --&gt; | 0  2  2 | 1  0  0 |
\ 6 6 7 | 0 0 1 /     \ 6  6  7 | 0  0  1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;20&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;0&lt;/span&gt; scaled by 6 from row &lt;span class="subtract-scaled-row-dest"&gt;2&lt;/span&gt;:

  &lt;pre&gt;/ &lt;span class="subtract-scaled-row-src"&gt;1 245 3&lt;/span&gt; | &lt;span class="subtract-scaled-row-src"&gt;0 246 0&lt;/span&gt; \     / 1 245  3 | 0 246 0 \
| 0  2  2 | 1  0  0 | --&gt; | 0  2   2 | 1  0  0 |
\ &lt;span class="subtract-scaled-row-dest"&gt;6  6  7&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt;0  0  1&lt;/span&gt; /     \ &lt;span class="subtract-scaled-row-dest"&gt;0  14 13&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt;0  2  1&lt;/span&gt; /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;11&lt;/sub&gt; to be 1, so divide row &lt;span class="divide-row"&gt;1&lt;/span&gt; by 2:

  &lt;pre&gt;/ 1 245  3 | 0 246 0 \     / 1 245  3 |  0  246 0 \
| &lt;span class="divide-row"&gt;0  2   2&lt;/span&gt; | &lt;span class="divide-row"&gt;1  0  0&lt;/span&gt; | --&gt; | &lt;span class="divide-row"&gt;0  1   1&lt;/span&gt; | &lt;span class="divide-row"&gt;141  0  0&lt;/span&gt; |
\ 0 14  13 | 0  2  1 /     \ 0 14  13 |  0   2  1 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;21&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;1&lt;/span&gt; scaled by 14 from row &lt;span class="subtract-scaled-row-dest"&gt;2&lt;/span&gt;:

  &lt;pre&gt;/ 1 245  3 |  0  246 0 \     / 1 245  3 |  0  246 0 \
| &lt;span class="subtract-scaled-row-src"&gt;0  1   1&lt;/span&gt; | &lt;span class="subtract-scaled-row-src"&gt;141  0  0&lt;/span&gt; | --&gt; | 0  1   1 | 141  0  0 |
\ &lt;span class="subtract-scaled-row-dest"&gt;0 14  13&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt; 0   2  1&lt;/span&gt; /     \ &lt;span class="subtract-scaled-row-dest"&gt;0  0   3&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt; 7   2  1&lt;/span&gt; /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;22&lt;/sub&gt; to be 1, so divide row &lt;span class="divide-row"&gt;2&lt;/span&gt; by 3, which makes the left side of &lt;var&gt;A&lt;/var&gt; a
  unit upper triangular matrix:

  &lt;pre&gt;/ 1 245  3 |  0  246 0 \     / 1 245  3 |  0  246  0  \
| 0  1   1 | 141  0  0 | --&gt; | 0  1   1 | 141  0   0  |
\ &lt;span class="divide-row"&gt;0  0   3&lt;/span&gt; |  &lt;span class="divide-row"&gt;7   2  1&lt;/span&gt; /     \ &lt;span class="divide-row"&gt;0  0   1&lt;/span&gt; | &lt;span class="divide-row"&gt;244 247 246&lt;/span&gt; /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;12&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;2&lt;/span&gt; from row &lt;span class="subtract-scaled-row-dest"&gt;1&lt;/span&gt;:

  &lt;pre&gt;/ 1 245  3 |  0  246  0  \     / 1 245  3 |  0  246  0  \
| &lt;span class="subtract-scaled-row-dest"&gt;0  1   1&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt;141  0   0 &lt;/span&gt; | --&gt; | &lt;span class="subtract-scaled-row-dest"&gt;0  1   0&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt;121 247 246&lt;/span&gt; |
\ &lt;span class="subtract-scaled-row-src"&gt;0  0   1&lt;/span&gt; | &lt;span class="subtract-scaled-row-src"&gt;244 247 246&lt;/span&gt; /     \ 0  0   1 | 244 247 246 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;02&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;2&lt;/span&gt; scaled by 3 from row &lt;span class="subtract-scaled-row-dest"&gt;0&lt;/span&gt;:

  &lt;pre&gt;/ &lt;span class="subtract-scaled-row-dest"&gt;1 245  3&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt; 0  246  0 &lt;/span&gt; \     / &lt;span class="subtract-scaled-row-dest"&gt;1 245  0&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt; 7  244  1 &lt;/span&gt; \
| 0  1   0 | 121 247 246 | --&gt; | 0  1   0 | 121 247 246 |
\ &lt;span class="subtract-scaled-row-src"&gt;0  0   1&lt;/span&gt; | &lt;span class="subtract-scaled-row-src"&gt;244 247 246&lt;/span&gt; /     \ 0  0   1 | 244 247 246 /.&lt;/pre&gt;

  We need &lt;var&gt;A&lt;/var&gt;&lt;sub&gt;01&lt;/sub&gt; to be 0, so subtract row &lt;span class="subtract-scaled-row-src"&gt;1&lt;/span&gt; scaled by 245 from row &lt;span class="subtract-scaled-row-dest"&gt;0&lt;/span&gt;, which makes the left side of &lt;var&gt;A&lt;/var&gt; the identity matrix:

  &lt;pre&gt;/ &lt;span class="subtract-scaled-row-dest"&gt;1 245  0&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt; 7  244  1 &lt;/span&gt; \     / &lt;span class="subtract-scaled-row-dest"&gt;1 0 0&lt;/span&gt; | &lt;span class="subtract-scaled-row-dest"&gt; 82  82  82&lt;/span&gt; \
| &lt;span class="subtract-scaled-row-src"&gt;0  1   0&lt;/span&gt; | &lt;span class="subtract-scaled-row-src"&gt;121 247 246&lt;/span&gt; | --&gt; | 0 1 0 | 121 247 246 |
\ 0  0   1 | 244 247 246 /     \ 0 0 1 | 244 247 246 /.&lt;/pre&gt;

  Since the left side of &lt;var&gt;A&lt;/var&gt; is the identity matrix, the right side of &lt;var&gt;A&lt;/var&gt; is &lt;var&gt;M&lt;/var&gt;&lt;sup&gt;-1&lt;/sup&gt;. Therefore,

  &lt;pre&gt;         /  82  82  82 \
M^{-1} = | 121 247 246 |
         \ 244 247 246 /.&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally, we can use that to implement &lt;code&gt;ReconstructData&lt;/code&gt;.&lt;/p&gt;

&lt;div class="interactive-example" id="reconstructDataDetailDemo"&gt;
  &lt;h3&gt;Example 15: &lt;code&gt;ReconstructData&lt;/code&gt; in detail&lt;/h3&gt;
  Let

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;d&lt;/var&gt;&lt;sub&gt;partial&lt;/sub&gt; = [ ??, db, ?? ]
  &lt;/span&gt;

  be the input partial data bytes and

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;p&lt;/var&gt;&lt;sub&gt;partial&lt;/sub&gt; = [ 52, 0c ]
  &lt;/span&gt;

  be the input partial parity bytes. Then, with the data byte
  count

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;n&lt;/var&gt; = 3
  &lt;/span&gt;

  and the parity byte count

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;m&lt;/var&gt; = 2,
  &lt;/span&gt;

  and appending the rows of the

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;m&lt;/var&gt; &amp;times; &lt;var&gt;n&lt;/var&gt;
  &lt;/span&gt;

  Cauchy parity matrix to the

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;n&lt;/var&gt; &amp;times; &lt;var&gt;n&lt;/var&gt;
  &lt;/span&gt;

  identity matrix, we get

  &lt;pre&gt;/ X01X X00X X00X \
|  00   01   00  |
| X00X X00X X01X |
|  f6   8d   01  |
\  cb   52   7b  /,&lt;/pre&gt;

  where the rows corresponding to the unknown data and parity
  bytes are crossed out. Taking the first &lt;var&gt;n&lt;/var&gt; rows that
  aren&amp;rsquo;t crossed out, we get the square matrix

  &lt;pre&gt;/ 00 01 00 \
| f6 8d 01 |
\ cb 52 7b /&lt;/pre&gt;

  which has inverse

  &lt;pre&gt;/ 01 d0 d6 \
| 01 00 00 |
\ 7b b8 bb /.&lt;/pre&gt;

  Therefore, the data bytes are reconstructed from the first
  &lt;var&gt;n&lt;/var&gt; known data and parity bytes as

  &lt;pre&gt;                _    _     _    _
/ 01 d0 d6 \   |  db  |   |  da  |
| 01 00 00 | * |  52  | = |  db  |
\ 7b b8 bb /   |_ 0c _|   |_ 0d _|,&lt;/pre&gt;

  and thus the output data bytes are

  &lt;span style="white-space: nowrap;"&gt;
    &lt;var&gt;d&lt;/var&gt; = [ &lt;span class="result"&gt;da&lt;/span&gt;, &lt;span class="result"&gt;db&lt;/span&gt;, &lt;span class="result"&gt;0d&lt;/span&gt; ].
  &lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;And we&amp;rsquo;re done!&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;12. Further reading&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Next time we&amp;rsquo;ll talk about the PAR1 file format, which is a
  practical implementation of an erasure code very similar to the one
  described above, and the various challenges to make it perform well
  on sets of large files.&lt;/p&gt;

&lt;p&gt;Also, for those of you interested in the mathematical details,
  I&amp;rsquo;ll also write a companion article. (This article is already
  quite long!)&lt;/p&gt;

&lt;p&gt;I gave &lt;a href="./magic-erasure-codes"&gt;a 15-minute
  presentation&lt;/a&gt; for &lt;a href="https://wafflejs.com"&gt;WaffleJS&lt;/a&gt; covering
  the same topics as this article but at a higher-level and more
  informally.&lt;/p&gt;

&lt;p&gt;I got the idea for explaining the finite field with \(256\)
  elements in terms of binary carry-less arithmetic from &lt;a href="http://www.zlib.net/crc_v3.txt"&gt;A
  Painless Guide to CRC Error Detection Algorithms&lt;/a&gt;, which is an
  excellent document in its own right.&lt;/p&gt;

&lt;p&gt;Most sources below use Vandermonde matrices, which I plan to cover
  in the next article on PAR1, instead of Cauchy matrices. Cauchy
  matrices are more foolproof, which is why I started with
  them. templexxx, whose Go implementation I cite below, &lt;a href="http://www.templex.xyz/blog/101/cauchy.html"&gt;feels the same way&lt;/a&gt;. (His
  blog post is in Chinese, but using &lt;a href="https://translate.google.com/"&gt;Google Translate&lt;/a&gt; or
  a similar service translates it well enough to English.)&lt;/p&gt;

&lt;p&gt;I started learning about erasure codes from &lt;a href="https://web.eecs.utk.edu/~plank/"&gt;James
  Plank&amp;rsquo;s&lt;/a&gt; papers. See &lt;a href="https://web.eecs.utk.edu/~plank/plank/papers/CS-96-332.pdf"&gt;A Tutorial on Reed-Solomon Coding for Fault-Tolerance in RAID-like systems&lt;/a&gt;, but also make sure to read the very important &lt;a href="https://web.eecs.utk.edu/~plank/plank/papers/CS-03-504.pdf"&gt;correction&lt;/a&gt; to it! &lt;a href="http://web.eecs.utk.edu/~plank/plank/papers/CS-05-569.pdf"&gt;Optimizing
  Cauchy Reed-Solomon Codes for Fault-Tolerant Storage Applications&lt;/a&gt; covers
  Cauchy matrices, although in a slightly different context. The first
  part of Plank&amp;rsquo;s &lt;a href="http://web.eecs.utk.edu/~plank/plank/classes/cs560/560/notes/Erasure/2004-ICL.pdf"&gt;All About Erasure Codes&lt;/a&gt; slides
  also contains a good overview of the encoding/decoding process,
  including a nifty color-coded matrix diagram.&lt;/p&gt;

&lt;p&gt;As for implementations, &lt;a href="https://github.com/klauspost/reedsolomon"&gt;klauspost&lt;/a&gt; and &lt;a href="https://github.com/templexxx/reedsolomon"&gt;templexxx&lt;/a&gt; have
  good ones written in Go. They were in turn inspired by &lt;a href="https://github.com/Backblaze/JavaReedSolomon"&gt;Backblaze&amp;rsquo;s Java implementation&lt;/a&gt;. &lt;a href="https://www.backblaze.com/blog/reed-solomon/"&gt;Backblaze&amp;rsquo;s
  accompanying blog post&lt;/a&gt; is also a good overview of the topic. The
  toy JS implementation powering the demos on this page are also
  available on &lt;a href="https://github.com/akalin/intro-erasure-codes"&gt;my GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://people.cs.clemson.edu/~westall/851/rs-code.pdf"&gt;An Introduction to Galois Fields and Reed-Solomon Coding&lt;/a&gt;&lt;sup&gt;&lt;a href="#fn13" id="r13"&gt;[13]&lt;/a&gt;&lt;/sup&gt; covers
  much of the same material as I do, albeit assuming slightly more
  mathematical background.&lt;/p&gt;

&lt;p&gt;Going further afield, &lt;a href="https://research.swtch.com/field"&gt;Russ Cox&lt;/a&gt;, &lt;a href="https://jeremykun.com/2015/03/23/the-codes-of-solomon-reed-and-muller/"&gt;Jeremy Kun&lt;/a&gt;, and &lt;a href="https://www.nayuki.io/page/reed-solomon-error-correcting-code-decoder"&gt;Nayuki&lt;/a&gt;
  also wrote about finite fields and Reed-Solomon codes.&lt;/p&gt;
&lt;/section&gt;

&lt;hr /&gt;

&lt;p class="thanks"&gt;Thanks to Ying-zong Huang, Ryan Hitchman, Charles
  Ellis, and Josh Gao for comments/corrections/discussion.&lt;/p&gt;

&lt;p&gt;Like this post? Subscribe to
  &lt;!-- The image is 256x256, the center of the dot is 189 pixels from the
     top, and the radius of the dot is 24. Therefore, the dot is 43/256 =
     0.16796875 of the image height above the bottom.--&gt;
&lt;a href="feed/atom"&gt;my feed &lt;img alt="RSS icon" src="feed-icon.svg" /&gt;&lt;/a&gt;

  or follow me on
  &lt;a href="https://twitter.com/fakalin"&gt;Twitter &lt;img alt="Twitter icon" src="twitter-icon.svg" /&gt;&lt;/a&gt;.&lt;/p&gt;


&lt;section class="footnotes"&gt;
&lt;header&gt;
  &lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;/header&gt;

&lt;p id="fn1"&gt;[1] This discussion of linear algebra is necessarily
  abbreviated for our purposes. For a more general but still basic
  treatment, see &lt;a href="https://www.khanacademy.org/math/linear-algebra/matrix-transformations"&gt;Khan Academy&lt;/a&gt;. &lt;a href="#r1"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn2"&gt;[2] Here and throughout this document, I index vectors and
  matrices starting with \(0\), to better match array indices in
  code. Most math texts index vectors and matrices starting at \(1\). &lt;a href="#r2"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn3"&gt;[3] Now would be a good time to talk about the conventions
  I and other texts use. Following &lt;a href="https://web.eecs.utk.edu/~plank/plank/papers/CS-96-332.pdf"&gt;Plank&lt;/a&gt;,
  I use \(n\) for the data byte count and \(m\) for the parity
  byte count, and I represent arrays and vectors as &lt;em&gt;column vectors&lt;/em&gt;, where multiplication with a matrix is done with the column vector on the &lt;em&gt;right&lt;/em&gt;,
  which is the standard in most of math. However, in coding theory,
  \(k\) is used for the data byte count, which they call the &lt;em&gt;message length&lt;/em&gt;, and \(n\) is used for the sum of the data and parity byte counts, which they call the &lt;em&gt;codeword length&lt;/em&gt;. Furthermore,
  contrary to the rest of math, coding theory treats arrays and
  vectors as &lt;em&gt;row vectors&lt;/em&gt;, where multiplication with a matrix
  is done with the row vector on the &lt;em&gt;left&lt;/em&gt;, and the matrix used would be
  the transpose of the matrix that would be used with a column
  vector. &lt;a href="#r3"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn4"&gt;[4] Khan Academy has a &lt;a href="https://www.khanacademy.org/math/algebra-home/alg-matrices/alg-determinants-and-inverses-of-large-matrices/v/inverting-matrices-part-3"&gt;video stepping through an example&lt;/a&gt; for a \(3 \times 3\) matrix. &lt;a href="#r4"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn5"&gt;[5] People with experience in coding theory might
  recognize that a parity matrix \(P\) being optimal is equivalent to
  the corresponding erasure code being &lt;a href="https://en.wikipedia.org/wiki/Singleton_bound#MDS_codes"&gt;MDS&lt;/a&gt;. &lt;a href="#r5"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn6"&gt;[6] An equivalent statement which is easier to see is that
  if a row could be expressed as a linear combination of other rows,
  then one would be able to construct a non-empty square submatrix of
  \(P\) with those rows, which would then be non-invertible. &lt;a href="#r6"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn7"&gt;[7] It is instead a (transposed) &lt;a href="https://en.wikipedia.org/wiki/Vandermonde_matrix"&gt;&lt;em&gt;Vandermonde matrix&lt;/em&gt;&lt;/a&gt;,
  which we&amp;rsquo;ll cover when we talk about the PAR1 file format in a
  follow-up article. &lt;a href="#r7"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn8"&gt;[8] People with experience in abstract algebra might
  recognize this as &lt;a href="https://en.wikipedia.org/wiki/Finite_field_arithmetic#Effective_polynomial_representation"&gt;arithmetic over \(\mathbb{F}_2[x]\)&lt;/a&gt;,
  the polynomials with coefficients in the finite field with
  \(2\) elements. &lt;a href="#r8"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn9"&gt;[9] Our use of \(\clplus\), \(\clminus\), \(\clmul\), and
  \(\cldiv\) to denote carry-less arithmetic clashes with our use of
  the same symbols to denote generic field operations. However,
  we&amp;rsquo;ll never need to talk about both at the same time, so
  whichever one we mean should be obvious in context. &lt;a href="#r9"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn10"&gt;[10] This is a slightly stronger statement than &lt;a href="#theorem-3"&gt;Theorem&amp;nbsp;3&lt;/a&gt;. &lt;a href="#r10"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn11"&gt;[11] People with experience in abstract algebra might recognize carry-less primes as &lt;a href="https://en.wikipedia.org/wiki/Irreducible_element"&gt;irreducible
  elements&lt;/a&gt; of \(\mathbb{F}_2[x]\). &lt;a href="#r11"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn12"&gt;[12] Coincidentally, \(283\) is also a regular prime
  number. Using another carry-less prime number \(256 \le p \lt 512\)
  would also yield a field with \(256\) elements, but is important to
  consistently use the same carry-less modulus; different carry-less
  moduli lead to fields with \(256\) elements that are &lt;em&gt;isomorphic&lt;/em&gt;, but not identical.&lt;/p&gt;

&lt;p&gt;Borrowing &lt;a href="https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Polynomial_representations"&gt;notation from CRCs&lt;/a&gt;,
  the carry-less modulus is sometimes represented as a hexadecimal
  number with the leading digit (which is always \(1\)) omitted. For
  example, \(283\) would be represented as \(\mathtt{0x1b}\), and we can say
  that we&amp;rsquo;re using the field with \(256\) elements &lt;em&gt;defined
  by&lt;/em&gt;
  \(\mathtt{0x1b}\). &lt;a href="#r12"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;p id="fn13"&gt;[13] &lt;em&gt;Galois field&lt;/em&gt; is just another name for finite field. &lt;a href="#r13"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;</description><author>Fred Akalin</author><pubDate>Thu, 30 Nov 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.akalin.com/intro-erasure-codes</guid></item><item><title>OKRs and 4DX</title><link>https://blog.harterrt.com/okrs_and_4dx.html</link><description>&lt;p&gt;I feel like I'm swimming in acronyms these days.&lt;/p&gt;
&lt;p&gt;Earlier this year,
my team started using Objectives and Key Results (OKRs) for our planning.
It's been a learning process.
I had some prior experience with OKRs at Google,
but I've never felt like I was fully taking advantage of the …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 30 Nov 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/okrs_and_4dx.html</guid></item><item><title>Recurse Center 14: OpenSSH key files</title><link>https://peterlyons.com/problog/2017/11/recurse-center-14-openssh-key-files/</link><description>&lt;p&gt;So today (my 15th day of RC sabbatical) was where the rubber was supposed to hit the road. I was working on actually digging into the meaty bits of the OpenSSH private key PEM files and starting to peek into the base64 encoded data.&lt;/p&gt;
&lt;p&gt;I did some research this morning and futzed around with both bash pipelines and rust code to start to understand how these files work.&lt;/p&gt;
&lt;p&gt;First fun thing I found was looking at the raw data inside a PEM-encoded private key with this pipeline:&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;# strip out the header&amp;#x2f;footer lines (they have dashes)
grep -v - .&amp;#x2f;local&amp;#x2f;test_files&amp;#x2f;test-ssh-ed25519-2-passphrase.privatekey |
  # Decode the base64, this handles newlines no problem
  base64 -D |
  # dump that as hex
  hexdump
0000000 6f 70 65 6e 73 73 68 2d 6b 65 79 2d 76 31 00 00
0000010 00 00 0a 61 65 73 32 35 36 2d 63 62 63 00 00 00
0000020 06 62 63 72 79 70 74 00 00 00 18 00 00 00 10 d9
0000030 3b fe b4 54 93 c8 05 a7 77 21 7d 1c a5 69 1d 00
0000040 00 00 10 00 00 00 01 00 00 00 33 00 00 00 0b 73
0000050 73 68 2d 65 64 32 35 35 31 39 00 00 00 20 2e 40
0000060 78 7a 53 e2 89 d8 8f 54 9d 4b a3 3e 56 58 85 c7
0000070 1d 52 2e 7d 78 4e 9b e3 a5 89 1b 61 79 2a 00 00
0000080 00 90 68 c8 c3 da e6 6b cd d2 2f 4a 74 ad e9 7b
0000090 75 6a a6 8f d1 6d 24 86 fa 1e b1 77 25 0c e3 fa
00000a0 30 6d da 7c 72 11 be ac 98 0e b0 7b 7d 85 87 aa
00000b0 d1 49 c7 97 0a b4 5f 6e 61 5d 10 7c cd 55 c5 38
00000c0 45 e8 4c b8 2d 23 67 7b 23 18 97 06 7a 9d 0d bc
00000d0 69 d1 88 73 ba 34 8e 39 4e 50 01 cc 36 a7 c8 8b
00000e0 58 57 e9 c5 f4 b0 eb 79 ab 1b e6 64 a0 78 59 a6
00000f0 2b 05 03 00 57 bb 7b d4 19 ed 62 98 b1 db 4e 51
0000100 27 8e b7 7e f8 e2 42 d0 18 01 99 b6 c2 30 ad 9c
0000110 33 9e                                          
0000112
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After some futzing I was sure I had the right data and extracted some telltale ASCII strings indicating I was definitely on the right track.&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;# remove the PEM header&amp;#x2f;footer dash lines
grep -v - .&amp;#x2f;local&amp;#x2f;test_files&amp;#x2f;test-ssh-ed25519-2-passphrase.privatekey |
  # Decode the base64
  base64 -D |
  # find stuff that looks like ASCII words
  strings

openssh-key-v1
aes256-cbc
bcrypt
ssh-ed25519
(some gobbledygook omitted)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bingo! Now that I know some key words to look for, let me make a handy reference from ASCII to hex for these words.&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;for word in openssh-key-v1 aes256-cbc bcrypt ssh-ed25519 none
do
  echo -n &amp;quot;${word}: &amp;quot;
  echo -n &amp;quot;${word}&amp;quot; |
  hexdump |
  head -1 |
  cut -d &amp;quot; &amp;quot; -f 2-
done

openssh-key-v1: 6f 70 65 6e 73 73 68 2d 6b 65 79 2d 76 31
aes256-cbc: 61 65 73 32 35 36 2d 63 62 63
bcrypt: 62 63 72 79 70 74
ssh-ed25519: 73 73 68 2d 65 64 32 35 35 31 39
none: 6e 6f 6e 65
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nice! OK so I've been studying that and got some RC help with the openssh C source that generates it. Here's what I discovered about the byte-by-byte details of this openssh private key file.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;14 bytes magic ASCII "openssh-key-v1"
&lt;ul&gt;
&lt;li&gt;We can see our hex: &lt;code&gt;6f 70 65 6e 73 73 68 2d 6b 65 79 2d 76 31&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;1 NULL (zero) byte terminating that string
&lt;ul&gt;
&lt;li&gt;This is a bit weird because there's a mix of null-terminated C strings and length-prefixed string structs, but that's what it is&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4 byte length for next string&lt;/li&gt;
&lt;li&gt;N bytes string cipher name
&lt;ul&gt;
&lt;li&gt;"none" for no passphrase (cleartext), otherwise "aes256-cbc"&lt;/li&gt;
&lt;li&gt;We can see in our hex aes256-cbc &lt;code&gt;61 65 73 32 35 36 2d 63 62 63&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4 byte length for next string&lt;/li&gt;
&lt;li&gt;N bytes string kdfname (kdf means Key Derivation Function)
&lt;ul&gt;
&lt;li&gt;We can see in our hex bcrypt &lt;code&gt;62 63 72 79 70 74&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4 byte length for next string&lt;/li&gt;
&lt;li&gt;N bytes kdfoptions&lt;/li&gt;
&lt;li&gt;4 byte integer number of public keys in this file&lt;/li&gt;
&lt;li&gt;one string for each public key&lt;/li&gt;
&lt;li&gt;then an encrypted and padded blob for the private keys&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Part of the struggle researching this is AFAICT there's no clear, googlable name for this file format. It's just the bespoke openssh-key-v1 format but nobody calls it that and there's no file extension.&lt;/p&gt;
&lt;p&gt;So mostly I think I'm actually coding a command line tool in rust that will be useful to me now. I'm excited to keep pushing forward tomorrow.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 30 Nov 2017 03:05:34 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-14-openssh-key-files/</guid></item><item><title>Beginner interaction design with Principle</title><link>https://daniel.do/article/beginner-interaction-design-with-principle</link><description>I was able to pick up this powerful motion design tool in about 10 minutes and you can too!</description><author>Daniel Immke</author><pubDate>Thu, 30 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/beginner-interaction-design-with-principle</guid></item><item><title>Advanced Oracle Troubleshooting seminar in 2018!</title><link>https://tanelpoder.com/2017/11/29/advanced-oracle-troubleshooting-seminar-in-2018/</link><description>&lt;p&gt;A lot of people have asked me to do another run of my &lt;a href="https://tanelpoder.com/files/AOT30_description.pdf" rel="noopener" target="_blank"&gt;Oracle Troubleshooting training&lt;/a&gt; or at least get access to previous recordings – so I decided to geek out over the holiday period, update the material with latest stuff and run one more AOT class in &lt;strong&gt;2018&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;The online training will take place on &lt;strong&gt;29 January – 2 February 2018&lt;/strong&gt; (Part 1) &amp;amp; &lt;strong&gt;26 February – 2 March 2018&lt;/strong&gt; (Part 2).&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Thu, 30 Nov 2017 00:24:06 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/2017/11/29/advanced-oracle-troubleshooting-seminar-in-2018/</guid></item><item><title>Observations from Costa Rica, 2017</title><link>https://faingezicht.com/articles/2017/11/29/cr/</link><description>Every time I come back home to visit my family I notice how differently things run here in Costa Rica than in the US. There are some blaringly obvious contrasts, while others are details so subtle that it took me 7 years abroad to even consider. On this trip, I hung out with a lot of non-Costa Ricans (from the US and elsewhere) who came for my brother's wedding, so they kept asking me about peculiarities as they noticed them on their own. Seeing other people point out things that seemed odd to them made me become more aware myself. Here are a few of these observations:

* Unlike in the US, retail in Costa Rica is thriving. The first shopping malls here started popping up in the early 90s, and the gold rush &lt;a href="http://www.elfinancierocr.com/economia-y-politica/costa-rica-vive-fuerte-auge-de-centros-comerciales/2H6JN534QZGFXHUWGMBEK2FQFQ/story/"&gt;has not stopped&lt;/a&gt;. With rising standards of living, and a &lt;a href="https://tradingeconomics.com/costa-rica/gdp-per-capita"&gt;growing economy&lt;/a&gt; came purchasing power and the desire to buy into big name brands. People are eager to let go of their cash for generic status symbols. Compare this to the US and the rise of artisanal/bespoke/craft goods over homogeneous retail (see also Venkatesh Rao's &lt;a href="https://www.ribbonfarm.com/2017/08/17/the-premium-mediocre-life-of-maya-millennial/"&gt;Premium Mediocre&lt;/a&gt;). Interestingly, the Costa Rican retail boom is fully physical - ecommerce is nearly non-existent and people love going to the malls to do their shopping. Some possible explanations: while broadband penetration is high relative to our neighbors it is still &lt;a href="https://en.wikipedia.org/wiki/List_of_countries_by_number_of_broadband_Internet_subscriptions"&gt;pretty low&lt;/a&gt;, there is no robust logistics infrastructure (think UPS), and no company has tried to kickstart online shopping here. This is a large business opportunity that's up for grabs.

* The ways that Costa Ricans use the apps on their smartphones are very different from the US. Everyone here uses Waze. &lt;a href="https://www.washingtonpost.com/news/innovations/wp/2014/10/27/why-waze-is-so-incredibly-popular-in-costa-rica/?utm_term=.e93d1668e698"&gt;Everyone&lt;/a&gt;. It is well known that our streets have no names and that people get around &lt;a href="https://www.wsj.com/articles/SB10001424052702304870304577489094121477570"&gt;by reference points&lt;/a&gt;, but this time around I saw a lot of billboards and signs with variations of Waze's smiling car logo, and URLs to the Waze "pin" for a given store. Similarly, businesses use WhatsApp to communicate directly with their clients. We heard at least two ads on the radio prompting listeners to get in touch via WhatsApp. For example, when we rented a car to go to the beach the clerk insisted that we WhatsApp him copies of our documents, instead of sending them via email. And yet, everyone uses Uber to get around (hi, Alan!).

* The press in Costa Rica is quite yellow, and there is little interest in long-form, in-depth local content, so the market doesn't supply it. We have no equivalent of the New Yorker or the Atlantic. There are opportunities for investigative journalism, with lots of cool stories waiting for someone to write. The stories are amazing, and the kind that the public in the US would be interested in. Hannah and I spent a few days in &lt;a href="/photos/2017/11/29/limon/"&gt;Puerto Viejo&lt;/a&gt;, and we talked a lot about the Afro-Caribbean culture and how different it feels from San José. For historic reasons, there is a much higher concentration of black people there than elsewhere in the country. People in the US would read about that. Everyone rides bikes there, which is unusual in the rest of the country, and we think may be due to an entrepreneur deciding to heavily market it to tourists. People in the US would read about that. We noticed thousands of dead puffer fish laying on the beach, and when we asked around, no one knew the real reason why (I could only find &lt;a href="http://www.ticotimes.net/2013/10/04/natural-causes-likely-to-blame-for-mass-fish-deaths-on-costa-rica-s-caribbean-coast"&gt;one article&lt;/a&gt; on it, and it was fairly weak). People in the US would read about that. We went to a restaurant owned by a guy who was a community activist, became a representative in the Costa Rica legislature, and is deeply tied to the town's development. People in the US would read about that. Notice that all these ideas come from 3 days on the Caribbean coast, a place I had never been to before. It sometimes takes an outsider to see there is a story to be told. I can imagine a study abroad program where journalism schools send people to live in Costa Rica for a summer and churn these out, arbitraging journalism.

* A while back I had told Hannah that I find the number of American flags in cars, stores, and streets in the US kind of crazy, and that this kind of noisy nationalism bothers me. Turns out there are also flags all over Costa Rica, I just didn't really notice them until my girlfriend decided to start pointing out every one we passed. This was an odd realization of the power of indoctrination: I see the American flags plastered all over NYC, Chicago, or San Francisco as loud and obnoxious, but fail to notice the equivalent in Costa Rica.

The longer I am away, the more I start to understand these subtle differences and catch the details that I totally ignored before. Coming back home makes me see my birthplace with new eyes. It is its own version of having a beginner's mind.

What are some other oddities that you've noticed in your trips abroad? Let me know &lt;a href="https://www.twitter.com/avyfain"&gt;on Twitter&lt;/a&gt;.

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: by me, also posted on &lt;a href="/photos/2017/11/29/limon/"&gt;Puerto Viejo&lt;/a&gt;.&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Wed, 29 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/11/29/cr/</guid></item><item><title>Puerto Viejo</title><link>https://faingezicht.com/photos/2017/11/29/limon/</link><description>I was just in Costa Rica for my brother's wedding. The trip was amazing, but somehow I only ended up taking photos when we went to the beach. It was my first time in the Caribbean side of the country, and we had a lot of fun.

You can read some more in-depth commentary on the cultural aspect of my trip and some of the realizations I had during it &lt;a href="/articles/2017/11/29/cr/"&gt;here&lt;/a&gt;.</description><author>Avy Faingezicht</author><pubDate>Wed, 29 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/11/29/limon/</guid></item><item><title>Recurse Center 13: ssh private key PEM files</title><link>https://peterlyons.com/problog/2017/11/recurse-center-13-ssh-private-key-pem-files/</link><description>&lt;p&gt;Today I used the rust &lt;code&gt;pem&lt;/code&gt; crate to check whether a given file was or was not parseable as PEM encoded. PEM stands for Privacy Enhanced Mail. I learned that most ssh private keys are stored as PEM files and there are ED25519, ECDSA, RSA, and DSA types (maybe more but those are the ones I'm familiar with and read about a bit in the openssh source code). Still not clear on whether the public keys are in SSLEAY format or not. Also did some pairing and showed another RCer the rust &lt;code&gt;?&lt;/code&gt; operator.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 29 Nov 2017 00:48:55 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-13-ssh-private-key-pem-files/</guid></item><item><title>rust custom Display and sorting</title><link>https://peterlyons.com/problog/2017/11/rust-custom-display-and-sorting/</link><description>&lt;p&gt;So as an exercise I wanted to make a rust struct with custom order and blog the process. I did this in my tealeaves project to get some data to group/sort by severity (errors then warnings then infos) and it worked nicely but it was mostly the derived implementations and I wanted to review. So let's make a basic Person struct (very similar to the example in the official rust docs, but we'll get fancier).&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;struct Person {
    name: String,
}

fn main() {
    println!(&amp;quot;{}&amp;quot;, Person { name: &amp;quot;Sheena&amp;quot;.to_string() });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;"No can do!" says the compiler:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error[E0277]: the trait bound `Person: std::fmt::Display` is not satisfied
 --&amp;gt; src&amp;#x2f;main.rs:6:20
  |
6 |     println!(&amp;quot;{}&amp;quot;, Person { name: &amp;quot;Sheena&amp;quot;.to_string() });
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Person` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
  |
  = help: the trait `std::fmt::Display` is not implemented for `Person`
  = note: required by `std::fmt::Display::fmt`

error: aborting due to previous error
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK, let's make Person displayable.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;use std::fmt;

struct Person {
    name: String,
}

impl fmt::Display for Person {
    fn fmt(&amp;amp;self, f: &amp;amp;mut fmt::Formatter) -&amp;gt; fmt::Result {
        write!(f, &amp;quot;{}&amp;quot;, self.name)
    }
}

fn main() {
    println!(&amp;quot;{}&amp;quot;, Person { name: &amp;quot;Sheena&amp;quot;.to_string() });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We run that and it prints "Sheena". Pretty neat!&lt;/p&gt;
&lt;p&gt;OK but now I wanted to make my Person struct sortable by age. As is often the case in rust, one part of this was way harder than in most languages and another part was also way harder than in other languages :-p.&lt;/p&gt;
&lt;p&gt;First, we need a way to compute a person's age based on their birthday, so I extended my Person struct to also store a &lt;code&gt;born&lt;/code&gt; property, but in order to model that as a calendar date, we need the &lt;code&gt;chrono&lt;/code&gt; crate and a while reading the docs to figure out what type we should use. After my research, I decided &lt;code&gt;chrono::NaiveDate&lt;/code&gt; would be viable.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate chrono;
use chrono::NaiveDate;
use std::fmt;

struct Person {
    name: String,
    born: NaiveDate,

}

impl fmt::Display for Person {
    fn fmt(&amp;amp;self, f: &amp;amp;mut fmt::Formatter) -&amp;gt; fmt::Result {
        write!(f, &amp;quot;{}&amp;quot;, self.name)
    }
}

fn main() {
    println!(&amp;quot;{}&amp;quot;, Person { name: &amp;quot;Sheena&amp;quot;.to_string(), born: NaiveDate::from_ymd(1970, 1, 17) });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK now I wanted a more concise way to define instances of Person, so I added a constructor function.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate chrono;
use chrono::NaiveDate;
use std::fmt;

struct Person {
    name: String,
    born: NaiveDate,
}

impl Person {
    pub fn new(name: String, year: i32, month: u32, day: u32) -&amp;gt; Self {
        Person {
            name,
            born: NaiveDate::from_ymd(year, month, day),
        }
    }
}

impl fmt::Display for Person {
    fn fmt(&amp;amp;self, f: &amp;amp;mut fmt::Formatter) -&amp;gt; fmt::Result {
        write!(f, &amp;quot;{}&amp;quot;, self.name)
    }
}

fn main() {
    println!(&amp;quot;{}&amp;quot;, Person::new(&amp;quot;Sheena&amp;quot;.to_string(), 1970, 1, 17));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next let's write an &lt;code&gt;age&lt;/code&gt; function so we can see how old a person is at this moment. Again I had to read the docs for a long time, and there may be a better way to do this, but my basic approach ended up being get a Duration between now and their birthday, convert that to a number of days, and divide by 365 to get something approximately yearish. While we're at it we'll update our Display trait to print their age.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate chrono;
use chrono::NaiveDate;
use chrono::Local;
use std::fmt;

struct Person {
    name: String,
    born: NaiveDate,
}

impl Person {
    pub fn new(name: String, year: i32, month: u32, day: u32) -&amp;gt; Self {
        Person {
            name,
            born: NaiveDate::from_ymd(year, month, day),
        }
    }

    pub fn age(&amp;amp;self) -&amp;gt; i64 {
        NaiveDate::signed_duration_since(Local::today().naive_local(), self.born).num_days() &amp;#x2f; 365
    }
}

impl fmt::Display for Person {
    fn fmt(&amp;amp;self, f: &amp;amp;mut fmt::Formatter) -&amp;gt; fmt::Result {
        write!(f, &amp;quot;{} (age: {})&amp;quot;, self.name, self.age())
    }
}

fn main() {
    println!(&amp;quot;{}&amp;quot;, Person::new(&amp;quot;Sheena&amp;quot;.to_string(), 1970, 1, 17));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK now to make them sortable by age we need 4 total traits: &lt;code&gt;Eq, PartialEq, Ord, and PartialOrd&lt;/code&gt;. &lt;code&gt;Eq&lt;/code&gt; we can derive satisfactorily. The other three are mostly  boilerplate we copy from the rust documentation and adjust to sort people based on their &lt;code&gt;born&lt;/code&gt; attribute with youngest first.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate chrono;
use chrono::{NaiveDate, Local};
use std::{cmp, fmt};

#[derive(Eq)]
struct Person {
    name: String,
    born: NaiveDate,
}

impl Person {
    pub fn new(name: String, year: i32, month: u32, day: u32) -&amp;gt; Self {
        Person {
            name,
            born: NaiveDate::from_ymd(year, month, day),
        }
    }

    pub fn age(&amp;amp;self) -&amp;gt; i64 {
        NaiveDate::signed_duration_since(Local::today().naive_local(), self.born).num_days() &amp;#x2f; 365
    }
}

impl PartialOrd for Person {
    fn partial_cmp(&amp;amp;self, other: &amp;amp;Person) -&amp;gt; Option&amp;lt;cmp::Ordering&amp;gt; {
        Some(other.cmp(self))
    }
}

impl Ord for Person {
    fn cmp(&amp;amp;self, other: &amp;amp;Person) -&amp;gt; cmp::Ordering {
        self.born.cmp(&amp;amp;other.born)
    }
}

impl PartialEq for Person {
    fn eq(&amp;amp;self, other: &amp;amp;Person) -&amp;gt; bool {
        self.born == other.born
    }
}

impl fmt::Display for Person {
    fn fmt(&amp;amp;self, f: &amp;amp;mut fmt::Formatter) -&amp;gt; fmt::Result {
        write!(f, &amp;quot;{} (age: {})&amp;quot;, self.name, self.age())
    }
}

fn main() {
    let mut people = vec![];
    people.push(Person::new(&amp;quot;Imogen Heap&amp;quot;.to_string(), 1977, 12, 9));
    people.push(Person::new(&amp;quot;Fatboy Slim&amp;quot;.to_string(), 1963, 7, 31));
    people.push(Person::new(&amp;quot;Weird Al&amp;quot;.to_string(), 1959, 10, 23));
    people.push(Person::new(&amp;quot;Zoë Keating&amp;quot;.to_string(), 1972, 2, 2));
    people.sort();
    for person in people.iter() {
        println!(&amp;quot;{}&amp;quot;, person);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now we run this and we see a nice display format for people and they are sorted youngest first:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Imogen Heap (age: 39)
Zoë Keating (age: 45)
Fatboy Slim (age: 54)
Weird Al (age: 58)
&lt;/code&gt;&lt;/pre&gt;</description><author>Pete's Points</author><pubDate>Tue, 28 Nov 2017 23:16:34 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/rust-custom-display-and-sorting/</guid></item><item><title>The Poor Man's 3D Camera</title><link>https://etodd.io/2017/11/28/poor-mans-3d-camera/</link><description>&lt;p&gt;Each of us have our own giants to face. This is a story about one of my giants. Something I never imagined could make a grown man cry, until it did.&lt;/p&gt;

&lt;p&gt;A 3D camera.&lt;/p&gt;

&lt;p&gt;No one can face your giants for you. This is a story, not a walkthrough. Expect no useful information. For that I recommend &lt;a href="https://www.youtube.com/watch?v=C7307qRmlMI"&gt;50 Game Camera Mistakes&lt;/a&gt; by thatgamecompany's John Nesky. His job title is literally "camera designer".&lt;/p&gt;</description><author>Evan Todd</author><pubDate>Tue, 28 Nov 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://etodd.io/2017/11/28/poor-mans-3d-camera/</guid></item><item><title>Firefox 57 CPU usage is insane</title><link>https://muffinman.io/blog/firefox-57-cpu-usage-is-insane/</link><description>&lt;article class="article"&gt;&lt;p&gt;This is a sad rant :(&lt;/p&gt;
&lt;p&gt;I love Firefox (and Mozilla too) and have never switched to
&lt;span class="sidenote__text" tabindex="0"&gt;Chrome&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Although I use Chrome for development.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
But few days ago I switched to Opera, because new Firefox&amp;#x27;s (aka Quantum)
CPU usage is insane.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Firefox CPU usage" height="402" src="./ff.jpg" width="1312" /&gt;&lt;/figure&gt;
&lt;p&gt;Disabling extensions didn&amp;#x27;t help, it just hogs all available resources.
MacOS is giving me &amp;quot;Service Battery&amp;quot; warning when Firefox is running.
And battery last about four times(!) shorter.&lt;/p&gt;
&lt;p&gt;So I checked my options, and decided to go with Opera.
One of my favorite features in Firefox, tabs on the side,
is not supported in Chrome and Safari, so only decent browser left was Opera.&lt;/p&gt;
&lt;p&gt;Opera has &lt;a href="https://addons.opera.com/en/extensions/details/tree-tabs/?display=en"&gt;Tree Tabs&lt;/a&gt; extension,
which is not as good as &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/tree-style-tab/"&gt;Tree Style Tab&lt;/a&gt;
but it is good enough. I&amp;#x27;m getting used to it, and so far so good.
Although I do hope Firefox will resolve CPU issues.&lt;/p&gt;
&lt;p&gt;If they haven&amp;#x27;t hyped it so much, I probably wouldn&amp;#x27;t be writing this.
But they raised my expectations, how much faster and better it is, how they finally
caught up... and it is bad, like really bad.
I&amp;#x27;ve tried both beta and developer editions some time ago,
and fans were going crazy, CPU usage was going through the roof, battery drainage...
But I hoped that it will get resolved before they release a stable version.&lt;/p&gt;
&lt;p&gt;I&amp;#x27;m really sad, but if they don&amp;#x27;t fix this I won&amp;#x27;t be switching back to Firefox.
Still, I&amp;#x27;m going to continue supporting and donating to Mozilla.
On the plus side, &lt;a href="https://developer.mozilla.org/en-US/"&gt;MDN&lt;/a&gt; is one of the best sites
for web development resources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 02. Decemeber 2017&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It seems that guys from Mozilla are
&lt;a href="https://www.reddit.com/r/firefox/comments/7g6k9n/firefox_quantum_is_eating_your_cpu_help_us_debug/"&gt;aware of it&lt;/a&gt;
and that they are trying to fix it. Hooray!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 04. December 2018&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, even today with version 63.0.3 issue doesn&amp;#x27;t seem to be resolved. I&amp;#x27;m sticking with Opera, but I switched to &lt;a href="https://addons.opera.com/en/extensions/details/simple-vertical-tabs/"&gt;Simple Vertical Tabs&lt;/a&gt; extension.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 26. September 2019&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/blog/back-to-firefox/"&gt;It is fixed!&lt;/a&gt;&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Tue, 28 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/firefox-57-cpu-usage-is-insane/</guid></item><item><title>Recurse Center 12: AsRef</title><link>https://peterlyons.com/problog/2017/11/recurse-center-12-asref/</link><description>&lt;p&gt;I spent a long time today trying to understand how the &lt;code&gt;AsRef&lt;/code&gt; trait works. I failed.&lt;/p&gt;
&lt;p&gt;I was able to split my tealeaves project code out into a handful of files and more strongly model the filesystem checks as Enums in the type system. If you are printing filesystem permission octals, don't forget the &lt;code&gt;{:o}&lt;/code&gt; format string.&lt;/p&gt;
&lt;p&gt;I find if I battle the compiler too long or just in general struggle to understand something, it drains me really quickly. No dopamine hits from little victories. This is one of the reasons I like unit testing - lots of little frequent victories and most of the time no time debugging weird production issues whilst praying for the sweet kiss of death.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Tue, 28 Nov 2017 01:10:25 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-12-asref/</guid></item><item><title>Software Interview Questions</title><link>http://www.nuke24.net/plog/25.html</link><description>Some kid was assigned to ask people who worked in the software industry
			questions about it and I ended up being the one to answer them.</description><author>TOGoS's Project Log</author><pubDate>Mon, 27 Nov 2017 22:58:11 GMT</pubDate><guid isPermaLink="true">http://www.nuke24.net/plog/25.html</guid></item><item><title>Running .NET on the Raspberry Pi</title><link>https://daniellittle.dev/running-mono-on-the-raspberry-pi</link><description>I recently got my hands on an older Raspberry Pi, which was a great excuse to see if I could get .NET running on it! If you're interested in…</description><author>Daniel Little Dev</author><pubDate>Mon, 27 Nov 2017 06:59:57 GMT</pubDate><guid isPermaLink="true">https://daniellittle.dev/running-mono-on-the-raspberry-pi</guid></item><item><title>Blog redesign</title><link>https://muffinman.io/blog/redesign-again/</link><description>&lt;article class="article"&gt;&lt;p&gt;Muffin Man is back! This time with new visual identity.&lt;/p&gt;
&lt;p&gt;This was long overdue, but new design took me
&lt;span class="sidenote__text" tabindex="0"&gt;more than I wanted to.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Mostly because of the &lt;a href="/blog/trillion-ideas/"&gt;trillion&lt;/a&gt; things I'm working on.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
Now I can get back to writing.&lt;/p&gt;
&lt;p&gt;Alogn with the new design, some other things got updated too,
hopefully making content easier to browse. To name a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Archive is now one page with category accordion (every category used to have a dedicated page)&lt;/li&gt;
&lt;li&gt;You can now find related posts under each post (instead of the latest ones)&lt;/li&gt;
&lt;li&gt;Search results are now navigable using arrows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I ditched custom Jekyll plugins to be able to use GitHub to automatically build the whole thing.
Some of them got rewritten to Liquid.&lt;/p&gt;
&lt;p&gt;Hope you like it!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 27 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/redesign-again/</guid></item><item><title>Adding Blog Here</title><link>https://benovermyer.com/blog/2017/11/adding-blog-here/</link><description>&lt;p&gt;I'm starting to use Hugo for blogging now. I might move all of the content currently on &lt;a href="https://pathfinder.space" rel="external"&gt;Pathfinder&lt;/a&gt; over to here, if it works as well as I hope it does.&lt;/p&gt;
&lt;p&gt;Also, I'm now hosting this site on Netlify, instead of deploying it myself to a VPS. This makes things much easier from a content management perspective.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Mon, 27 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2017/11/adding-blog-here/</guid></item><item><title>Google Code-in 2017</title><link>https://kyrofa.com/posts/google-code-in-2017/</link><description>Tomorrow, it begins. The culmination of weeks of research, documentation, and preparation by multiple open-source projects, just waiting to start hacking away with students. Tomorrow, students aged 13-17 can begin participating in Google Code-in 2017.
Ubuntu is one of the mentoring organizations, with several of my colleagues and me as mentors. Just in case you haven&amp;rsquo;t heard of it, Ubuntu is an open-source operating system for servers, desktops, and embedded devices.</description><author>kyrofa's blog</author><pubDate>Mon, 27 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/google-code-in-2017/</guid></item><item><title>Red-letter theology</title><link>https://honza.pokorny.ca/2017/11/red-letter-theology/</link><description>&lt;p&gt;Several weeks ago, I had a few friends over to our house to watch Les Lanphere&amp;rsquo;s
excellent &lt;a href="https://www.kickstarter.com/projects/calvinist/calvinist-documentary-film"&gt;Calvinist&lt;/a&gt; documentary.  I assumed this would be their first
exposure to Reformed theology, so I expected some lively discussion.  About half
way through the movie, we had to pause to answer a simple clarification
question.  Once that was done, one of the guys volunteered an interesting
observation.  He said: &amp;ldquo;I hope they show some quotes from Jesus, too.  So far
it&amp;rsquo;s just been Paul in Romans and Ephesians.  I wonder what Jesus has to say
about that.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This little comment has been on my mind ever since.  The traditional typography
of Bibles on the North American usually includes words of Christ in red.  Having
grown up in Europe, I didn&amp;rsquo;t encounter this until I came to Canada about ten
years ago.  The motivation behind this typographic design is to give reverence
to the words of Christ because when he speaks, God himself speaks.
Unfortunately, what this leads to is that people treat other parts of the Bible
as less important.  If it&amp;rsquo;s not red, it&amp;rsquo;s as if you don&amp;rsquo;t really have to believe
it.  This is a really bad way of reading the Bible and doing theology in
general.&lt;/p&gt;
&lt;p&gt;A small typographic detail can make a huge difference in how we think about what
we&amp;rsquo;re reading.  It might be helpful for us to stop and think about the features
of our Bibles to see how all the references, footnotes, verse numbers, section
headings, verse-by-verse layouts affect our reading and understanding of the
text of Scripture.&lt;/p&gt;
&lt;p&gt;Related: &lt;a href="https://byfaithweunderstand.com/bible-typography-manifesto/"&gt;Bible Typography Manifesto&lt;/a&gt;&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Sun, 26 Nov 2017 19:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/11/red-letter-theology/</guid></item><item><title>Twitter Plays Zork: @DemocraticZork</title><link>https://thomashunter.name/posts/2017-11-26-twitter-plays-zork-democraticzork</link><author>Thomas Hunter II</author><pubDate>Sun, 26 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-11-26-twitter-plays-zork-democraticzork</guid></item><item><title>Ready Player One</title><link>https://nindalf.com/posts/ready-player-one/</link><description>Ready Player One is a fast-paced book filled with 80s references, but falls short with one-dimensional characters and a lack of new ideas.</description><author>Krishna's blog</author><pubDate>Sun, 26 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/ready-player-one/</guid></item><item><title>THE big question about the Internet of Things is...</title><link>https://stop.zona-m.net/2017/11/the-big-question-about-the-internet-of-things-is.../</link><description>&lt;p&gt;There has recently been a MIT workshop on &amp;ldquo;Low-Latency Wireless Random-Access&amp;rdquo; which, from a report I&amp;rsquo;ve just seen, may have been focused on the wrong questions about the Internet of Things.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 25 Nov 2017 06:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/11/the-big-question-about-the-internet-of-things-is.../</guid></item><item><title>Comparing editions of the Institutes</title><link>https://honza.pokorny.ca/2017/11/comparing-editions-of-the-institutes/</link><description>&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/calvin.png" /&gt;
&lt;/figure&gt;

&lt;p&gt;The way I see it, you have three options when selection an edition of John
Calvin&amp;rsquo;s Institutes of the Christian Religion.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The final edition of 1559 translated by Henry Beveridge, published in 1867.&lt;/li&gt;
&lt;li&gt;The final edition of 1559 translated by Ford Lewis Battles, published in 1960.&lt;/li&gt;
&lt;li&gt;The French edition of 1541 translated by Robert White, published in 2014.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="beveridge"&gt;Beveridge&lt;/h2&gt;
&lt;p&gt;With &lt;em&gt;Beveridge&lt;/em&gt;, you get the full text of the &lt;em&gt;Institutes&lt;/em&gt;.  The language is
somewhat archaic and a bit convoluted sometimes.  It&amp;rsquo;s a lot easier to read than
the Puritans.  This translation is in the public domain, so you can read it for
&lt;a href="http://www.ccel.org/ccel/calvin/institutes.i.html"&gt;free online&lt;/a&gt;, and printed editions are relatively cheap.&lt;/p&gt;
&lt;p&gt;Book 1, Chapter 1, Section 2&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;On the other hand, it is evident that man never attains to a true
self-knowledge until he have previously contemplated the face of God, and
come down after such contemplation to look into himself. For (such is our
innate pride) we always seem to ourselves just, and upright, and wise, and
holy, until we are convinced, by clear evidence, of our injustice, vileness,
folly, and impurity. Convinced, however, we are not, if we look to ourselves
only, and not to the Lord also—he being the only standard by the application
of which this conviction can be produced. For, since we are all naturally
prone to hypocrisy, any empty semblance of righteousness is quite enough to
satisfy us instead of righteousness itself. And since nothing appears within
us or around us that is not tainted with very great impurity, so long as we
keep our mind within the confines of human pollution, anything which is in
some small degree less defiled delights us as if it were most pure: just as
an eye, to which nothing but black had been previously presented, deems an
object of a whitish, or even of a brownish hue, to be perfectly white. No,
the bodily sense may furnish a still stronger illustration of the extent to
which we are deluded in estimating the powers of the mind.&lt;/p&gt;
&lt;p&gt;If, at mid-day, we either look down to the ground, or on the surrounding
objects which lie open to our view, we think ourselves endued with a very
strong and piercing eyesight; but when we look up to the sun, and gaze at it
unveiled, the sight which did excellently well for the earth is instantly so
dazzled and confounded by the refulgence, as to oblige us to confess that
our acuteness in discerning terrestrial objects is mere dimness when applied
to the sun. Thus, too, it happens in estimating our spiritual qualities. So
long as we do not look beyond the earth, we are quite pleased with our own
righteousness, wisdom, and virtue; we address ourselves in the most
flattering terms, and seem only less than demigods.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="battles"&gt;Battles&lt;/h2&gt;
&lt;p&gt;With &lt;em&gt;Battles&lt;/em&gt;, you get the full text in its final form.  This is the academic
reference edition.  If you are going to write a paper or a book, and you want to
quote Calvin, use this.  The language is much more modern than &lt;em&gt;Beveridge&lt;/em&gt; but
still a bit technical at times.  The biggest downside of this edition is that it
comes in two volumes and it&amp;rsquo;s very expensive.&lt;/p&gt;
&lt;p&gt;Book 1, Chapter 1, Section 2&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Again, it is certain that man never achieves a clear knowledge of himself
unless he has first looked upon God&amp;rsquo;s face, and then descends from
contemplating him to scrutinize himself.  For we always seem to ourselves
righteous and upright and wise and holy&amp;mdash;this pride is innate in all of
us&amp;mdash;unless by clear proofs we stand convinced of our own unrighteousness,
foulness, folly, and impurity.  Moreover, we are not thus convinced if we
look merely to ourselves and not also to the Lord, who is the sole standard
by which this judgment must be measured.  For, because all of us are
inclined by nature to hypocrisy, a kind of empty image of righteousness in
place of righteousness itself abundantly satisfies us.  And because nothing
appears within or around us that has not been contaminated by great
immorality, what is a little less vile pleases us as a thing most pure&amp;mdash;so
long as we confine our minds within the limits of human corruption.  Just
so, an eye to which nothing is shown but black objects judges something
dirty white or even rather darkly mottle to be whiteness itself.  Indeed, we
can discern still more clearly from the bodily senses how much we are
deluded in estimating the powers of the soul.&lt;/p&gt;
&lt;p&gt;For if in broad daylight we either look down upon the ground or survey
whatever meets our view round about, we seem to ourselves endowed with the
strongest and keenest sight; yet when we look up to the sun and gaze
straight at it, that power of sight which was particularly strong on earth
is at once blunted and confused by a great brilliance, and thus we are
compelled to admin that our keenness in looking upon things earthly is sheer
dullness when it comes to the sun.  So it happens in estimating our
spiritual goods.  As long as we do not look beyond the earth, being quite
content with our own righteousness, wisdom and virtue, we flatter ourselves
most sweetly, and fancy ourselves all bug demigods.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="white"&gt;White&lt;/h2&gt;
&lt;p&gt;With &lt;em&gt;White&lt;/em&gt;, you get an earlier version of the &lt;em&gt;Institutes&lt;/em&gt;.  It&amp;rsquo;s missing
some sections from the final, but not much.  This is translated from the French
edition which is known for its lively prose.  The biggest draw for this edition
is its recency, only 2014. The language is very modern and flows nicely.  The
printed edition costs a bit more than &lt;em&gt;Beverage&lt;/em&gt; but still a lot less than
&lt;em&gt;Battles&lt;/em&gt;.  This edition will serve hobbyists well.  The newness of the
language will provide you with higher likelihood of finishing.&lt;/p&gt;
&lt;p&gt;Book 1, Chapter 1, Section 2&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Conversely, we observe that no one ever attains clear knowledge of self unless
he has first gazed upon the face of the Lord, and then turns back to look upon
himself. Deeply rooted in all of us is an arrogance which persuades us that we
are righteous, truthful, wise and holy. Only clear evidence that we are
unrighteous, deceitful, foolish and vile will convince us of the contrary. We
feel no such conviction if all we do is look upon ourselves and not also upon
the Lord. He is the one and only standard with which our judgment must
accord. But because hypocrisy is something to which we are all naturally prone,
we are quite content with an empty show of righteousness rather than with its
reality. And because there is nothing around us which is not greatly defiled,
whatever is a little less grubby appears to us as purity itself, as long as we
confine our attention to the limits of our own—debased—humanity. It is like the
eye which, used to seeing only objects that are dark, judges things which are
vaguely white or even semi-grey to be the whitest there is.  An analogy based on
physical sight will help us better understand how badly we misjudge our soul’s
powers.&lt;/p&gt;
&lt;p&gt;If in broad daylight we look down at the ground or attend to things which are
round about us, we have no trouble believing our sight is extremely sharp and
keen. When, however, we look straight up at the sun, the power that served us so
well on earth is dazed and dazzled by so intense a light, forcing us to admit
that our ability clearly to see earthly objects is weak and feeble when it comes
to gazing at the sun. This is how it is when we try to estimate our spiritual
strengths. As long as we do not look beyond earth’s horizons, we are perfectly
content with our own righteousness, wisdom and power.  We flatter and
congratulate ourselves, and are not far from thinking we are demigods!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, let me quote J.I. Packer on the subject of English translations
of Calvin&amp;rsquo;s &lt;em&gt;Institutes&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No English translation fully matches Calvin&amp;rsquo;s Latin; that of the Elizabethan,
Thomas Norton, perhaps gets closest; Beveridge gives us Calvin&amp;rsquo;s feistiness but
not always his precision; Battles gives us the precision but not always the
punchiness, and fleetness of foot; Allen is smooth and clear, but low-key.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;David W. Hall and Peter A. Lillback, eds. &lt;em&gt;A Theological Guide to Calvin’s Institutes: Essays and Analysis.
The Calvin 500 Series.&lt;/em&gt; (Phillipsburg, N.J: P&amp;amp;R Pub, 2008), x&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Fri, 24 Nov 2017 19:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/11/comparing-editions-of-the-institutes/</guid></item><item><title>Bio</title><link>https://johnj.com/bio/</link><description>&lt;p&gt;
I grew up&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-1" id="footnote-reference-1"&gt;1&lt;/a&gt;&lt;/sup&gt;[some old pictures of me]]] in
Madison, Wisconsin and studied art and physics at the University of
Wisconsin — Madison, receiving my doctorate in physics there in 1996
under &lt;a href="https://wipac.wisc.edu/people/faculty/francis-halzen"&gt;Prof. Francis Halzen&lt;/a&gt;.  I also worked for a year at CERN in
Geneva, Switzerland, under &lt;a href="https://en.wikipedia.org/wiki/Sau_Lan_Wu"&gt;Prof. Sau Lan Wu&lt;/a&gt; on the &lt;a href="https://en.wikipedia.org/wiki/ALEPH_experiment"&gt;ALEPH&lt;/a&gt; experiment.&lt;/p&gt;
&lt;p&gt;
My doctoral work and postdoc focused on &lt;a href="https://en.wikipedia.org/wiki/Antarctic_Muon_And_Neutrino_Detector_Array"&gt;the AMANDA neutrino detector&lt;/a&gt;
constructed at the Geographic South Pole, and the subsequent, much
larger &lt;a href="https://en.wikipedia.org/wiki/IceCube_Neutrino_Observatory"&gt;IceCube Neutrino Observatory&lt;/a&gt;.  My physics career is described
in more depth in &lt;a href="./vita.html"&gt;my Curriculum Vitae&lt;/a&gt;; the IceCube project is described
quite engagingly and at length by &lt;a href="https://en.wikipedia.org/wiki/Mark_Bowen_(writer)"&gt;Mark Bowen&lt;/a&gt; in his book, &lt;a href="https://www.amazon.com/Telescope-Ice-Inventing-Astronomy-South/dp/1137280085"&gt;The
Telescope in the Ice: Inventing a New Astronomy at the South Pole&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
While in graduate school I also studied painting, drawing and
printmaking in the UW-Madison graduate art program, mostly with &lt;a href="https://www.juxtapoz.com/news/printmaking-and-beyond-with-jack-damer/"&gt;Jack
Damer&lt;/a&gt;, Richard Long and &lt;a href="https://www.youtube.com/watch?v=-EXq1dEUP4s"&gt;David H. Becker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
In the 21st century I have been a &lt;a href="./tech.html"&gt;software engineer&lt;/a&gt; and painter. I
travelled to the Geographic South Pole ten times for AMANDA and
IceCube, going at first as a physicist, and then as a software
consultant (&lt;a href="./southpole-blog.html"&gt;blog posts here&lt;/a&gt;).  Some of my early paintings were
described in William Fox's book, &lt;a href="https://www.amazon.com/Terra-Antarctica-Looking-Emptiest-Continent/dp/1593761481"&gt;Terra Antarctica: Looking Into the
Emptiest Continent&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Since 2015 I have maintained a regular studio practice focusing on
figurative art based on observation and imagination.  This effort has
involved some re-training, mostly in the form of workshops at the
Palette and Chisel Academy of Fine Art with &lt;a href="http://cargocollective.com/andrewsconklin"&gt;Andrew S. Conklin&lt;/a&gt;, &lt;a href="http://steven-assael-mr8x.squarespace.com/work"&gt;Stephen
Assael&lt;/a&gt;, and Larry Paulsen.  My exhibition history is &lt;a href="./exhibitions.html"&gt;here&lt;/a&gt;, while
recent work and work in progress are shown on &lt;a href="https://www.instagram.com/eigenhombre/"&gt;my Instagram&lt;/a&gt; and &lt;a href="https://toomanysketchbooks.tumblr.com/"&gt;Tumblr&lt;/a&gt;
feeds.&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr class="footnotes-separatator" /&gt;
&lt;div class="footnote-definitions"&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-1"&gt;&lt;a href="#footnote-reference-1"&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;Just for fun, here are [[./more-pix-of-me.html&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Fri, 24 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/bio/</guid></item><item><title>Links - November 24, 2017</title><link>https://faingezicht.com/links/2017/11/24/links/</link><description>This was in drafts for a while, so posting without comments.</description><author>Avy Faingezicht</author><pubDate>Fri, 24 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/11/24/links/</guid></item><item><title>Quick fix: MongoDB fails when saving Decimal fields</title><link>https://nicolaiarocci.com/quick-fix-mongodb-fails-when-saving-decimal-fields/</link><description>&lt;p&gt;So today I was trying to store some decimal fields on a MongoDB 3.4
instance and I kept failing, miserably.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://www.mongodb.com/products/compass"&gt;Compass&lt;/a&gt; I was getting a somewhat obscure &amp;ldquo;connection lost&amp;rdquo; message on
every save attempt. Upgrading to Mongo 3.4.10 (I was on 3.4.4) improved things,
as the error message was now hinting at the &lt;code&gt;setFeatureCompatibilityVersion&lt;/code&gt;
setting which, apparently, was preventing some features to be made available.&lt;/p&gt;
&lt;p&gt;Now that made sense, as this specific database had been upgraded all
the way from up Mongo 2.6. A &lt;a href="https://docs.mongodb.com/master/reference/command/setFeatureCompatibilityVersion/#dbcmd.setFeatureCompatibilityVersion"&gt;quick lookup&lt;/a&gt; revealed that, when upgrading to
3.4, &lt;code&gt;setFeatureCompatibilityVersion&lt;/code&gt; is automatically set to &lt;code&gt;&amp;quot;3.2&amp;quot;&lt;/code&gt;. As we
all know, support for Decimal type only comes with Mongo 3.4.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 23 Nov 2017 12:05:28 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/quick-fix-mongodb-fails-when-saving-decimal-fields/</guid></item><item><title>Blog CD Pipeline with AWS CodePipeline</title><link>https://skife.org/b3/aws-code-services-for-blog/</link><description>&lt;p&gt;Jumped out of order from &lt;a href="https://skife.org/b3/knock-knock-still-on/"&gt;my earlier checklist&lt;/a&gt; and set up some automagic build and deploy. I'd wanted an excuse to try out &lt;a href="https://aws.amazon.com/codepipeline/" rel="external"&gt;CodePipeline&lt;/a&gt;, so this was it!&lt;/p&gt;
&lt;p&gt;So, how does this blog work? It is deployed to an S3 bucket (&lt;a href="https://skife.org/" rel="external"&gt;skife.org&lt;/a&gt;) with CloudFront in front of it. CloudFront is set up to use the free SNI certs to provide TLS. Previously, I pushed manually via &lt;a href="https://github.com/s3tools/s3cmd" rel="external"&gt;s3cmd&lt;/a&gt;, which worked well with some incantation fiddling.&lt;/p&gt;
&lt;p&gt;I won't write a full CodeBuild and CodeDeploy tutorial, Amazon has that well covered, but a couple bits were funny to work out, so will talk about those.&lt;/p&gt;
&lt;p&gt;First, CodePipeline needs to trigger things. This is important as CodeBuild has no mechanism (which I could find) to only care about particular branches. CodeBuild really just does builds (kind of). Conceptually, do everything through CodePipeline and other stuff is just steps which react to the pipeline.&lt;/p&gt;
&lt;p&gt;Given this is a static site, the build step just builds a tarball:&lt;/p&gt;
&lt;pre class="giallo" style="color: #24292E; background-color: #FFFFFF;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;version&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style="color: #005CC5;"&gt; 0.2&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;phases&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;  install&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;    commands&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; wget https://github.com/gohugoio/hugo/releases/download/v0.31/hugo_0.31_Linux-64bit.deb&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; dpkg -i ./hugo_0.31_Linux-64bit.deb&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;  build&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;    commands&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; hugo&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; tar -C public -cvzf skife.org.tgz .&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;artifacts&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;  files&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;    -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; skife.org.tgz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing fancy here, but having the artifact for CodePipeline to pass around is important.&lt;/p&gt;
&lt;p&gt;My first pass just had the deploy at the end of the build, but I want to be able to insert some basic tests before I deploy new versions. Just things like link verification, HTML5 validation, and maybe running stuff like &lt;a href="https://developers.google.com/web/tools/lighthouse/" rel="external"&gt;Lighthouse&lt;/a&gt; against a test instance before letting it out. The test part :-) Because of this, I wanted to seperate build from deploy. It turns out "deploy by copying into an S3 bucket" is not a thing &lt;a href="https://aws.amazon.com/codedeploy/" rel="external"&gt;CodeDeploy&lt;/a&gt; has any concept for.&lt;/p&gt;
&lt;p&gt;So my "deploy" is just another CodeBuild build:&lt;/p&gt;
&lt;pre class="giallo" style="color: #24292E; background-color: #FFFFFF;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;version&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style="color: #005CC5;"&gt; 0.2&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;phases&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;  build&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #22863A;"&gt;    commands&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; tar -xf skife.org.tgz&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; rm skife.org.tgz&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;      -&lt;/span&gt;&lt;span style="color: #032F62;"&gt; aws s3 sync . s3://skife.org --acl public-read --cache-control public,max-age=600&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can feed one build to another, it doesn't mind. When I configured the second build I had to set it up with an output artifact or CodePipeline wouldn't let me add it. After I saved the CodePipeline changes, I could go back and remove that output. The other decent path is probably to set up a Lambda function that takes apart the tarball and copies things over... but this build approach seems simpler.&lt;/p&gt;
&lt;p&gt;I tried to put a cloudfront invalidation into the last step as well, but the version of the aws cli on the build image is old and it is not supported. I'll sort that out later. Once I do, will change max-age to max-age=31536000 or so and add something like:&lt;/p&gt;
&lt;pre class="giallo" style="color: #24292E; background-color: #FFFFFF;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;-&lt;/span&gt;&lt;span style="color: #032F62;"&gt; aws cloudfront create-invalidation --distribution-id E1DTTO3T6ZPN9M --paths / /index.html /404.html /archive.html /index.xml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the build commands, and voila!&lt;/p&gt;</description><author>Brian's Waste of Time</author><pubDate>Thu, 23 Nov 2017 03:09:31 GMT</pubDate><guid isPermaLink="true">https://skife.org/b3/aws-code-services-for-blog/</guid></item><item><title>Six Easy Pieces</title><link>https://nindalf.com/posts/six-easy-pieces/</link><description>Six Easy Pieces by Richard Feynman is a fun read that provides an intuitive grasp of physics concepts, but falls short of teaching techniques.</description><author>Krishna's blog</author><pubDate>Thu, 23 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/six-easy-pieces/</guid></item><item><title>Notes from Priceonomics' 2017 Content Marketing Conference</title><link>https://www.codingvc.com/p/notes-from-priceonomics-2017-content-marketing-conference</link><description>I&amp;#8217;ve been a fan of Priceonomics for a long time.</description><author>Coding VC</author><pubDate>Wed, 22 Nov 2017 07:06:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/notes-from-priceonomics-2017-content-marketing-conference</guid></item><item><title>QEFs, Eigenvalues, and Normals</title><link>https://mattkeeter.com/blog/2017-11-22-eigen</link><description/><author>Matt Keeter</author><pubDate>Wed, 22 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2017-11-22-eigen</guid></item><item><title>Recurse Center 11: rsfs rust associated types</title><link>https://peterlyons.com/problog/2017/11/recurse-center-11-rsfs-rust-associated-types/</link><description>&lt;p&gt;So I'm working on a tool that will interact heavily with the filesystem. This has always presented a unit testing problem both from a test speed perspective but as well as the perspective of simulating unusual errors.&lt;/p&gt;
&lt;p&gt;Yesterday I shopped on crates.io and found the &lt;code&gt;filesystem&lt;/code&gt; crate which looked to be built exactly to what I needed. However, I quickly discovered it was missing some key things like exposing a file's size without having to read it and getting detailed permissions.&lt;/p&gt;
&lt;p&gt;Today I shopped again and found &lt;code&gt;rsfs&lt;/code&gt; which had the detailed unix stuff I needed. In theory I want to be able to use the real filesystem when my tool is run for real and a throw-away in-memory filesystem for unit tests (including being able to simulate rare error cases). In my mind this meant passing in some abstract filesystem interface to the guts of my module as a function argument. So I set out to learn the basics of the &lt;code&gt;rsfs&lt;/code&gt; crate.&lt;/p&gt;
&lt;p&gt;Here's the first thing that prints out the permissions mode in octal of a real file that exists on my filesystem.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate rsfs;
use rsfs::GenFS; &amp;#x2f;&amp;#x2f; trait gives us .metadata()
use rsfs::Metadata; &amp;#x2f;&amp;#x2f; trait gives us .permissions()
use rsfs::unix_ext::PermissionsExt; &amp;#x2f;&amp;#x2f; trait gives us .mode()

fn main() {
    let fs  = rsfs::disk::FS;
    let meta = fs.metadata(&amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;).unwrap();
    let perms = meta.permissions();
    let mode = perms.mode();
    println!(&amp;quot;{:o}&amp;quot;, mode);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target&amp;#x2f;debug&amp;#x2f;fstool`
644

$ chmod 755 &amp;#x2f;tmp&amp;#x2f;foo.txt

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target&amp;#x2f;debug&amp;#x2f;fstool`
755
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK, so far so good. Now, can we simulate that with an in-memory filesystem?&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate rsfs;
use rsfs::GenFS; &amp;#x2f;&amp;#x2f; trait gives us .metadata()
use rsfs::Metadata; &amp;#x2f;&amp;#x2f; trait gives us .permissions()
use rsfs::unix_ext::PermissionsExt; &amp;#x2f;&amp;#x2f; trait gives us .mode()

fn main() {
    let fs  = rsfs::mem::unix::FS::new();
    fs.create_dir_all(&amp;quot;&amp;#x2f;tmp&amp;quot;).unwrap();
    fs.create_file(&amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;).unwrap();
    let meta = fs.metadata(&amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;).unwrap();
    let perms = meta.permissions();
    let mode = perms.mode();
    println!(&amp;quot;{:o}&amp;quot;, mode);
}

&amp;#x2f;&amp;#x2f; fn main_disk() {
&amp;#x2f;&amp;#x2f;     let fs  = rsfs::disk::FS;
&amp;#x2f;&amp;#x2f;     let meta = fs.metadata(&amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;).unwrap();
&amp;#x2f;&amp;#x2f;     let perms = meta.permissions();
&amp;#x2f;&amp;#x2f;     let mode = perms.mode();
&amp;#x2f;&amp;#x2f;     println!(&amp;quot;{:o}&amp;quot;, mode);
&amp;#x2f;&amp;#x2f; }
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;$ cargo run
   Compiling fstool v0.1.0 (file:&amp;#x2f;&amp;#x2f;&amp;#x2f;private&amp;#x2f;tmp&amp;#x2f;x)
    Finished dev [unoptimized + debuginfo] target(s) in 1.11 secs
     Running `target&amp;#x2f;debug&amp;#x2f;fstool`
666
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yup, looks acceptable.&lt;/p&gt;
&lt;p&gt;OK let's try to extract a helper function that works on either. My first thought would be the filesystem argument would be of type &lt;code&gt;rsfs::GenFS&lt;/code&gt; which is the "generic filesystem" trait whose whole purpose is to be agnostic about which specific filesystem implementation is used.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate rsfs;
use rsfs::GenFS; &amp;#x2f;&amp;#x2f; trait gives us .metadata()
use rsfs::Metadata; &amp;#x2f;&amp;#x2f; trait gives us .permissions()
use rsfs::unix_ext::PermissionsExt; &amp;#x2f;&amp;#x2f; trait gives us .mode()

fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
    let meta = fs.metadata(path).unwrap();
    let perms = meta.permissions();
    let mode = perms.mode();
    mode
}

fn main() {
    let mem = rsfs::mem::unix::FS::new();
    mem.create_dir_all(&amp;quot;&amp;#x2f;tmp&amp;quot;).unwrap();
    mem.create_file(&amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;).unwrap();

    let disk = rsfs::disk::FS;

    println!(&amp;quot;{:o}&amp;quot;, get_mode(mem, &amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;));
    println!(&amp;quot;{:o}&amp;quot;, get_mode(disk, &amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;$ cargo run
   Compiling fstool v0.1.0 (file:&amp;#x2f;&amp;#x2f;&amp;#x2f;private&amp;#x2f;tmp&amp;#x2f;x)
error[E0191]: the value of the associated type `DirBuilder` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `DirBuilder` value

error[E0191]: the value of the associated type `Permissions` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `Permissions` value

error[E0191]: the value of the associated type `ReadDir` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `ReadDir` value

error[E0191]: the value of the associated type `Metadata` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `Metadata` value

error[E0191]: the value of the associated type `OpenOptions` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `OpenOptions` value

error[E0191]: the value of the associated type `DirEntry` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `DirEntry` value

error[E0191]: the value of the associated type `File` (from the trait `rsfs::GenFS`) must be specified
 --&amp;gt; src&amp;#x2f;main.rs:6:18
  |
6 | fn get_mode(fs: &amp;amp;GenFS, path: &amp;amp;str) -&amp;gt; u32 {
  |                  ^^^^^ missing associated type `File` value

error: aborting due to 7 previous errors

error: Could not compile `fstool`.

To learn more, run the command again with --verbose.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Damn, the compiler sure is mad about a bunch of associated types. OK let's try to specify the associated types, at least for the bits we think we really need.&lt;/p&gt;
&lt;p&gt;We tried many variants and sadly I can't really walk you through the whole sequence of compiler error, code change, rinse repeat, but it was probably 19 iterations. We knew that basically when we called &lt;code&gt;.metadata().permissions()&lt;/code&gt; we needed to tell the type system "Hey, use PermissionsExt there because that has the .mode() function we need and don't just give me back Permissions because there's no .mode() function there". But because that's nested underneath the Metadata associated type, we had to first say, OK for Metadata, we want a Permissions associated type that has all the combined functionality of both Permissions and PermissionsExt, which looks like &lt;code&gt;Permissions + PermissionExt&lt;/code&gt; in trait sublanguage.&lt;/p&gt;
&lt;p&gt;However, the syntax here doesn't let us write it exactly that way. We get an error &lt;code&gt;the trait rsfs::Permissions cannot be made into an object&lt;/code&gt;. At this point I'm basically 2 levels below my depth here but a fellower RCer was pairing with me and knew that we basically needed to define that combination of associated types as &lt;code&gt;P&lt;/code&gt; and then explain to the typesystem to use it both for our &lt;code&gt;Metadata&lt;/code&gt; associated type and our &lt;code&gt;GenFS&lt;/code&gt; type. That ultimately ends up looking like the next snippet. Even though the compiler initially complained about needing ALL the associated types specified, I think because we are only actually using APIs related to permissions, we got away with only specifying the associated types necessary for the API calls we actually use in our code.&lt;/p&gt;
&lt;pre class="language-rust "&gt;&lt;code class="language-rust"&gt;extern crate rsfs;
use rsfs::GenFS; &amp;#x2f;&amp;#x2f; trait gives us .metadata()
use rsfs::Metadata; &amp;#x2f;&amp;#x2f; trait gives us .permissions()
use rsfs::unix_ext::PermissionsExt; &amp;#x2f;&amp;#x2f; trait gives us .mode()
use rsfs::Permissions;

fn get_mode&amp;lt;P: Permissions + PermissionsExt,
            M: Metadata&amp;lt;Permissions = P&amp;gt;,
            F: GenFS&amp;lt;Permissions = P, Metadata = M&amp;gt;&amp;gt;
    (fs: &amp;amp;F,
     path: &amp;amp;str)
     -&amp;gt; u32 {
    let meta = fs.metadata(path).unwrap();
    let perms = meta.permissions();
    let mode = perms.mode();
    mode
}

fn main() {
    let mem = rsfs::mem::unix::FS::new();
    mem.create_dir_all(&amp;quot;&amp;#x2f;tmp&amp;quot;).unwrap();
    mem.create_file(&amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;).unwrap();

    let disk = rsfs::disk::FS;

    println!(&amp;quot;{:o}&amp;quot;, get_mode(&amp;amp;mem, &amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;));
    println!(&amp;quot;{:o}&amp;quot;, get_mode(&amp;amp;disk, &amp;quot;&amp;#x2f;tmp&amp;#x2f;foo.txt&amp;quot;));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;$ cargo run
   Compiling fstool v0.1.0 (file:&amp;#x2f;&amp;#x2f;&amp;#x2f;private&amp;#x2f;tmp&amp;#x2f;x)
    Finished dev [unoptimized + debuginfo] target(s) in 1.5 secs
     Running `target&amp;#x2f;debug&amp;#x2f;fstool`
666
755
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Success! We now have a business logic function that works identically on both an in-memory filesystem and the real filesystem. This is pretty exciting for me especially since the rsfs crate docs indicate you can synthesize error cases, which lights up my "100% code coverage" light bulb.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 22 Nov 2017 01:01:17 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-11-rsfs-rust-associated-types/</guid></item><item><title>Avoiding The Infosec Extinction Part 1.</title><link>https://blog.eutopian.io/avoiding-the-infosec-extinction-part-1./</link><description>800 words, 3 1/2 minutes.
Making Your 1st Decision This is the first of a short series of posts about the Cyber Security market. This market is interesting now because I believe it&amp;rsquo;s at a juncture where we can choose one of two possible futures. We being the product builders, investors, and customers. The choice being whether to align ourselves with reality or fantasy.
Plenty of markets perpetuate a degree of fantasy.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 21 Nov 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/avoiding-the-infosec-extinction-part-1./</guid></item><item><title>Recurse Center 10: filesystem palindrome</title><link>https://peterlyons.com/problog/2017/11/recurse-center-10-filesystem-palindrome/</link><description>&lt;p&gt;This morning I worked on my "tealeaves" crypto diagnostic library. Just the basics of statting files but some interesting type system modeling and grokking what &lt;code&gt;#[derive(PartialOrd)]&lt;/code&gt; does for enums and structs. I basically got rust to handle printing errors then warnings then OK messages via the sorting mechanisms.&lt;/p&gt;
&lt;p&gt;I found a could-be-awesome crate called &lt;code&gt;filesystem&lt;/code&gt; which gives a consistent interface for both an in-memory filesystem for fast unit tests as well as the real filesystem for production code. It's something I've always wanted. However, at the moment the API is not quite rich enough for what I want to do so I'm not sure it will work unless I enhance it.&lt;/p&gt;
&lt;p&gt;Late in the day a group of us did a polyglot pairing exercise where we paired up to do some basic exercises in a programming language neither of us knew. I paired with JB in clojure and we implemented a program to find the longest palindrome in a sentence. I learned a bunch of stuff about clojure and it was a fun exercise.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Tue, 21 Nov 2017 02:05:33 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-10-filesystem-palindrome/</guid></item><item><title>How to Make a Churn Model in R</title><link>https://lukesingham.com/how-to-make-a-churn-model-in-r/</link><description>&lt;p&gt;The following post details how to make a churn model in R. It was part of an interview process for which a take home assignment was one of the stages. The company stated this should take 2hrs, which is entirely unrealistic. To minimise the time cost, my analysis is very succinct and short on the exploratory analysis and amount of models compared. The churn model got me to the final stage, however little in the way of feedback was offered. There is considerable debate in the tech industry as to whether take home exams are a fair assessment or even a reasonable ask on an individual. My assessment is that this is a lazy way to interview and a very high cost on the interviewee. If you really want to work for a particular company, then sure you might be prepared to do what it takes. I doubt I will do another take home assignment.&lt;/p&gt;
&lt;p&gt;The analysis was done in &lt;a href="http://rmarkdown.rstudio.com/"&gt;Rmarkdown&lt;/a&gt; and the output copied into this blog post following &lt;a href="https://notes.innovea.tech/how-to-write-latex-formula-in-ghosts-post/"&gt;these helpful pointers&lt;/a&gt;. If you would like to play with the data and full unabridged code please visit &lt;a href="https://github.com/ucg8j/how-to-make-churn-model-in-R"&gt;this github repo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="aim"&gt;Aim &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#aim"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Please create a model that predicts which businesses are likely to churn at the start of 2015 based on the &lt;code&gt;vertical&lt;/code&gt; and &lt;code&gt;incorporation_date&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We have an inkling that a dropoff in the number of mandates added might be an advance indicator of someone churning. Please can you assess whether this might be true, and if you think it is useful, incorporate it into your model from part (1).&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Load packages&lt;/span&gt;&lt;br /&gt;suppressPackageStartupMessages&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;data.table&lt;span class="token punctuation"&gt;)&lt;/span&gt;   &lt;span class="token comment"&gt;# Fast I/O&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;dplyr&lt;span class="token punctuation"&gt;)&lt;/span&gt;        &lt;span class="token comment"&gt;# Data munging&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;tidyr&lt;span class="token punctuation"&gt;)&lt;/span&gt;        &lt;span class="token comment"&gt;# Data munging&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;lubridate&lt;span class="token punctuation"&gt;)&lt;/span&gt;    &lt;span class="token comment"&gt;# Makes dates easy&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;plotly&lt;span class="token punctuation"&gt;)&lt;/span&gt;       &lt;span class="token comment"&gt;# Interactive charts&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;magrittr&lt;span class="token punctuation"&gt;)&lt;/span&gt;     &lt;span class="token comment"&gt;# pipe operators&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;caret&lt;span class="token punctuation"&gt;)&lt;/span&gt;        &lt;span class="token comment"&gt;# Handy ML functions&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;rpart&lt;span class="token punctuation"&gt;)&lt;/span&gt;        &lt;span class="token comment"&gt;# Decision Trees&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;rpart.plot&lt;span class="token punctuation"&gt;)&lt;/span&gt;   &lt;span class="token comment"&gt;# Pretty tree plots&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;ROCR&lt;span class="token punctuation"&gt;)&lt;/span&gt;         &lt;span class="token comment"&gt;# ML evaluation&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;e1071&lt;span class="token punctuation"&gt;)&lt;/span&gt;        &lt;span class="token comment"&gt;# Misc stat fns&lt;/span&gt;&lt;br /&gt;    library&lt;span class="token punctuation"&gt;(&lt;/span&gt;randomForest&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token comment"&gt;# rf&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;set.seed&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;42&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Read data and drop row number column&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; fread&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"monthly_data_(2)_(2).csv"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; drop &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Have a glimpse of the data&lt;/span&gt;&lt;br /&gt;glimpse&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;## Observations: 902&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Variables: 27&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ company_id          &amp;lt;int&gt; 4, 5, 6, 7, 8, 10, 11, 12, 13, 14...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-01-01_payments &amp;lt;dbl&gt; 8, 0, 2, 3, 0, 0, 0, 0, 0, 0, 4, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-02-01_payments &amp;lt;dbl&gt; 4, 0, 2, 3, 0, 0, 0, 2, 0, 11, 1,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-03-01_payments &amp;lt;dbl&gt; 7, 39, 1, 1, 6, 0, 0, 0, 8, 0, 1,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-04-01_payments &amp;lt;dbl&gt; 7, 0, 3, 7, 50, 1, 0, 0, 2, 0, 0,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-05-01_payments &amp;lt;dbl&gt; 1, 54, 1, 4, 119, 0, 1, 0, 0, 0, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-06-01_payments &amp;lt;dbl&gt; 2, 0, 2, 1, 151, 3, 0, 0, 0, 0, 2...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-07-01_payments &amp;lt;dbl&gt; 2, 0, 2, 7, 182, 0, 0, 0, 3, 0, 0...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-08-01_payments &amp;lt;dbl&gt; 4, 22, 1, 2, 167, 0, 0, 0, 2, 0, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-09-01_payments &amp;lt;dbl&gt; 3, 0, 1, 5, 180, 0, 0, 0, 0, 9, 5...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-10-01_payments &amp;lt;dbl&gt; 5, 0, 2, 8, 157, 1, 0, 0, 0, 2, 1...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-11-01_payments &amp;lt;dbl&gt; 5, 0, 1, 2, 105, 0, 0, 0, 0, 0, 0...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-12-01_payments &amp;lt;dbl&gt; 9, 0, 3, 8, 57, 0, 0, 0, 0, 0, 0,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-01-01_mandates &amp;lt;dbl&gt; 0, 4, 0, 0, 0, 4, 4, 0, 0, 22, 0,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-02-01_mandates &amp;lt;dbl&gt; 0, 31, 1, 0, 2, 3, 8, 0, 0, 20, 1...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-03-01_mandates &amp;lt;dbl&gt; 0, 24, 0, 0, 0, 5, 19, 0, 0, 11, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-04-01_mandates &amp;lt;dbl&gt; 53, 18, 0, 1, 0, 0, 0, 0, 1, 11, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-05-01_mandates &amp;lt;dbl&gt; 0, 8, 0, 0, 0, 0, 0, 0, 1, 15, 0,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-06-01_mandates &amp;lt;dbl&gt; 0, 7, 0, 0, 0, 0, 0, 0, 0, 13, 5,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-07-01_mandates &amp;lt;dbl&gt; 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 16...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-08-01_mandates &amp;lt;dbl&gt; 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 8,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-09-01_mandates &amp;lt;dbl&gt; 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 2,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-10-01_mandates &amp;lt;dbl&gt; 0, 0, 0, 0, 1, 0, 0, 0, 0, 16, 1,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-11-01_mandates &amp;lt;dbl&gt; 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ 2014-12-01_mandates &amp;lt;dbl&gt; 0, 0, 0, 3, 0, 0, 0, 0, 0, 11, 0,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ vertical            &amp;lt;chr&gt; "gym/fitness", "freelance d...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ incorporation_date  &amp;lt;chr&gt; "2003-09-25", "2008-10-22", ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="data-munging"&gt;Data Munging &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#data-munging"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some data munging needs to occur for our binary classifiers to make use of the data within. This includes handling dates.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Reshape data and create new columns&lt;/span&gt;&lt;br /&gt;df &lt;span class="token percent-operator operator"&gt;%&amp;lt;&gt;%&lt;/span&gt;&lt;br /&gt;    gather&lt;span class="token punctuation"&gt;(&lt;/span&gt;key &lt;span class="token operator"&gt;=&lt;/span&gt; date&lt;span class="token punctuation"&gt;,&lt;/span&gt; value &lt;span class="token operator"&gt;=&lt;/span&gt; quantity&lt;span class="token punctuation"&gt;,&lt;/span&gt; starts_with&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"20"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    separate&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;,&lt;/span&gt; c&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"date"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;span class="token string"&gt;"paymentMandate"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"_"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    spread&lt;span class="token punctuation"&gt;(&lt;/span&gt;paymentMandate&lt;span class="token punctuation"&gt;,&lt;/span&gt; quantity&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    mutate&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;      incorporation_date &lt;span class="token operator"&gt;=&lt;/span&gt; as.Date&lt;span class="token punctuation"&gt;(&lt;/span&gt;incorporation_date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;      date &lt;span class="token operator"&gt;=&lt;/span&gt; as.Date&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;      incorporation_time &lt;span class="token operator"&gt;=&lt;/span&gt; round&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;        as.numeric&lt;span class="token punctuation"&gt;(&lt;/span&gt;difftime&lt;span class="token punctuation"&gt;(&lt;/span&gt;as.Date&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"2014-12-01"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        as.Date&lt;span class="token punctuation"&gt;(&lt;/span&gt;incorporation_date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        unit&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;"weeks"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt; &lt;span class="token number"&gt;52.25&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        digits &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    arrange&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# What does the new data look like?&lt;/span&gt;&lt;br /&gt;glimpse&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;## Observations: 10,824&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Variables: 7&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ company_id         &amp;lt;int&gt; 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14,...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ vertical           &amp;lt;chr&gt; "gym/fitness", "gym/fitness", "freelance de...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ incorporation_date &amp;lt;date&gt; 2013-05-30, 2003-09-25, 2008-10-22, 2005-0...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ date               &amp;lt;date&gt; 2014-01-01, 2014-01-01, 2014-01-01, 2014-0...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ mandates           &amp;lt;dbl&gt; 1, 0, 0, 0, 4, 0, 0, 0, 4, 4, 0, 0, 22, 0, ...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ payments           &amp;lt;dbl&gt; 0, 1, 6, 8, 0, 2, 3, 0, 0, 0, 0, 0, 0, 4, 4...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## $ incorporation_time &amp;lt;dbl&gt; 1.5, 11.2, 6.1, 9.4, 1.2, 9.1, 4.0, 2.9, 1....&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="what-is-churn"&gt;What is Churn &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#what-is-churn"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For the purposes of this project I have defined ‘churn’ as zero mandates and payments for the first instance of that after the last mandate/payment made.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Create binary 'churn' column&lt;/span&gt;&lt;br /&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;churn &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# For use in for loop - upper bound of data&lt;/span&gt;&lt;br /&gt;max.date &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; max&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Mark all companies as churned in the month immediately their last activity&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;for&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;company &lt;span class="token keyword"&gt;in&lt;/span&gt; unique&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;company_id&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Subset data to company&lt;/span&gt;&lt;br /&gt;    df.sub &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; subset&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;,&lt;/span&gt; df&lt;span class="token operator"&gt;$&lt;/span&gt;company_id &lt;span class="token operator"&gt;==&lt;/span&gt; company&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Index of last positive mandate OR payment&lt;/span&gt;&lt;br /&gt;    last.pos.idx &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; tail&lt;span class="token punctuation"&gt;(&lt;/span&gt;which&lt;span class="token punctuation"&gt;(&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;mandates &lt;span class="token operator"&gt;!=&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;payments &lt;span class="token operator"&gt;!=&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Get date of last activity&lt;/span&gt;&lt;br /&gt;    last.activity.date &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;date&lt;span class="token punctuation"&gt;[&lt;/span&gt;last.pos.idx&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# If less than max.date of dataset mark churn ELSE do nothing i.e. positive at end of period&lt;/span&gt;&lt;br /&gt;    &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;last.activity.date &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; max.date&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="token comment"&gt;# Get churn date (last positive month plus 1mth)&lt;/span&gt;&lt;br /&gt;        churn.date &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; last.activity.date &lt;span class="token percent-operator operator"&gt;%m+%&lt;/span&gt; months&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="token comment"&gt;# Mark month of churn as 1&lt;/span&gt;&lt;br /&gt;        df&lt;span class="token punctuation"&gt;[&lt;/span&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;date &lt;span class="token operator"&gt;==&lt;/span&gt; churn.date &lt;span class="token operator"&gt;&amp;amp;&lt;/span&gt; df&lt;span class="token operator"&gt;$&lt;/span&gt;company_id &lt;span class="token operator"&gt;==&lt;/span&gt; company&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token operator"&gt;$&lt;/span&gt;churn &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;br /&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Multiple rows per company, filter for last month or churn month values...&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Get churners&lt;/span&gt;&lt;br /&gt;df &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt; filter&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;-&gt;&lt;/span&gt; churners&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Get max date row of remainers (non-churners)&lt;/span&gt;&lt;br /&gt;df &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    filter&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&lt;/span&gt; &lt;span class="token operator"&gt;!&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;company_id &lt;span class="token percent-operator operator"&gt;%in%&lt;/span&gt; churners&lt;span class="token operator"&gt;$&lt;/span&gt;company_id&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&lt;/span&gt; date &lt;span class="token operator"&gt;==&lt;/span&gt; max&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;-&gt;&lt;/span&gt; remainers&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Combine and variables coded ready for modelling&lt;/span&gt;&lt;br /&gt;churners &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    rbind&lt;span class="token punctuation"&gt;(&lt;/span&gt;remainers&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    mutate&lt;span class="token punctuation"&gt;(&lt;/span&gt;vertical &lt;span class="token operator"&gt;=&lt;/span&gt; as.factor&lt;span class="token punctuation"&gt;(&lt;/span&gt;vertical&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;           churn    &lt;span class="token operator"&gt;=&lt;/span&gt; as.factor&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;-&gt;&lt;/span&gt; model.df&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="churns-over-the-year"&gt;Churns over the year &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#churns-over-the-year"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Plot churners&lt;/span&gt;&lt;br /&gt;model.df &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    filter&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    group_by&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    summarise&lt;span class="token punctuation"&gt;(&lt;/span&gt;n &lt;span class="token operator"&gt;=&lt;/span&gt; n&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    plot_ly&lt;span class="token punctuation"&gt;(&lt;/span&gt; x &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token operator"&gt;~&lt;/span&gt;date&lt;span class="token punctuation"&gt;,&lt;/span&gt; y &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token operator"&gt;~&lt;/span&gt;n&lt;span class="token punctuation"&gt;,&lt;/span&gt; type &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'scatter'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; mode &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'lines'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/11/churns-over-year.png" /&gt;&lt;/p&gt;
&lt;p&gt;Could do more on exploratory but this is the easiest to cut back for this report.&lt;/p&gt;
&lt;h3 id="balance-of-the-data"&gt;Balance of the data &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#balance-of-the-data"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The proportion of churn is 32.04%. Representing an imbalanced dataset. Accuracy is an inappropriate measure (I could get 67.96% accuracy predicting no businesses leave), so I will focus on recall and precision.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Loyal vs Churn&lt;/span&gt;&lt;br /&gt;table&lt;span class="token punctuation"&gt;(&lt;/span&gt;model.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0   1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 613 289&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="model"&gt;Model &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#model"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Survival models and binary classifiers are common approaches to ‘Churn’ models. I will approach the model using the latter, though if I had more time I would investigate other classifiers and a survival model. I will limit the range of models to a logistic, a decision tree and an ensemble.&lt;/p&gt;
&lt;h3 id="split-data"&gt;Split Data &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#split-data"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# 80/20 train test split&lt;/span&gt;&lt;br /&gt;index    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; createDataPartition&lt;span class="token punctuation"&gt;(&lt;/span&gt;model.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;,&lt;/span&gt; p &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;0.8&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; list &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;FALSE&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;train.df &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; model.df&lt;span class="token punctuation"&gt;[&lt;/span&gt;index&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;test.df  &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; model.df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token operator"&gt;-&lt;/span&gt;index&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Check balance of the training split&lt;/span&gt;&lt;br /&gt;table&lt;span class="token punctuation"&gt;(&lt;/span&gt;train.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0   1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 491 232&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Check balance of the test split&lt;/span&gt;&lt;br /&gt;table&lt;span class="token punctuation"&gt;(&lt;/span&gt;test.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0   1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 122  57&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="logistic"&gt;Logistic &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#logistic"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Run model&lt;/span&gt;&lt;br /&gt;Logistic.model &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; glm&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;~&lt;/span&gt; incorporation_time &lt;span class="token operator"&gt;+&lt;/span&gt; vertical&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                      data   &lt;span class="token operator"&gt;=&lt;/span&gt; train.df&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                      family &lt;span class="token operator"&gt;=&lt;/span&gt; binomial&lt;span class="token punctuation"&gt;(&lt;/span&gt;link &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'logit'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predict&lt;/span&gt;&lt;br /&gt;log.pred &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;Logistic.model&lt;span class="token punctuation"&gt;,&lt;/span&gt; newdata &lt;span class="token operator"&gt;=&lt;/span&gt; test.df&lt;span class="token punctuation"&gt;,&lt;/span&gt; type &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'response'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Convert probs to binary&lt;/span&gt;&lt;br /&gt;log.pred &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; as.factor&lt;span class="token punctuation"&gt;(&lt;/span&gt;ifelse&lt;span class="token punctuation"&gt;(&lt;/span&gt;log.pred &lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token number"&gt;0.5&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Evaluation Metrics&lt;/span&gt;&lt;br /&gt;log.result    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; confusionMatrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;data &lt;span class="token operator"&gt;=&lt;/span&gt; log.pred&lt;span class="token punctuation"&gt;,&lt;/span&gt; test.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;log.precision &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; log.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Pos Pred Value'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;log.recall    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; log.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Sensitivity'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;log.F1        &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; log.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'F1'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="decision-tree"&gt;Decision Tree &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#decision-tree"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Train model&lt;/span&gt;&lt;br /&gt;tree.model &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; rpart&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;~&lt;/span&gt; incorporation_time &lt;span class="token operator"&gt;+&lt;/span&gt; vertical&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                    data &lt;span class="token operator"&gt;=&lt;/span&gt; train.df&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                    method &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;"class"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                    control &lt;span class="token operator"&gt;=&lt;/span&gt; rpart.control&lt;span class="token punctuation"&gt;(&lt;/span&gt;xval &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Plot&lt;/span&gt;&lt;br /&gt;rpart.plot&lt;span class="token punctuation"&gt;(&lt;/span&gt;tree.model&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/11/decision-tree.png" /&gt;&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Evaluation metrics&lt;/span&gt;&lt;br /&gt;tree.pred      &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;tree.model&lt;span class="token punctuation"&gt;,&lt;/span&gt; newdata &lt;span class="token operator"&gt;=&lt;/span&gt; test.df&lt;span class="token punctuation"&gt;,&lt;/span&gt; type &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;"class"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree.result    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; confusionMatrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;data &lt;span class="token operator"&gt;=&lt;/span&gt; tree.pred&lt;span class="token punctuation"&gt;,&lt;/span&gt; test.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree.precision &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; tree.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Pos Pred Value'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;tree.recall    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; tree.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Sensitivity'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;tree.F1        &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; tree.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'F1'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="random-forest-(ensemble)"&gt;Random Forest (Ensemble) &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#random-forest-(ensemble)"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Train model&lt;/span&gt;&lt;br /&gt;forest.model &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; randomForest&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;~&lt;/span&gt; incorporation_time &lt;span class="token operator"&gt;+&lt;/span&gt; vertical&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                       data &lt;span class="token operator"&gt;=&lt;/span&gt; train.df&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                       ntree&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;200&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                       type&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;"classification"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# See error reduction with number of trees ( not much gained beyond ~25 trees)&lt;/span&gt;&lt;br /&gt;plot&lt;span class="token punctuation"&gt;(&lt;/span&gt;forest.model&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/11/random-forest-error-reduction.png" /&gt;&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Look at the variable Importance from the random forest&lt;/span&gt;&lt;br /&gt;varImpPlot&lt;span class="token punctuation"&gt;(&lt;/span&gt;forest.model&lt;span class="token punctuation"&gt;,&lt;/span&gt; sort &lt;span class="token operator"&gt;=&lt;/span&gt; T&lt;span class="token punctuation"&gt;,&lt;/span&gt; main&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;"Variable Importance"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/11/random-forest-variable-importance.png" /&gt;&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Evaluation metrics&lt;/span&gt;&lt;br /&gt;forest.pred      &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;forest.model&lt;span class="token punctuation"&gt;,&lt;/span&gt; newdata &lt;span class="token operator"&gt;=&lt;/span&gt; test.df&lt;span class="token punctuation"&gt;,&lt;/span&gt; type &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;"class"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;forest.result    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; confusionMatrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;data &lt;span class="token operator"&gt;=&lt;/span&gt; forest.pred&lt;span class="token punctuation"&gt;,&lt;/span&gt; test.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;forest.precision &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; forest.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Pos Pred Value'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;forest.recall    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; forest.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Sensitivity'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;forest.F1        &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; forest.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'F1'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="evaluation-metrics"&gt;Evaluation Metrics &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#evaluation-metrics"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;log.precision&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Pos Pred Value&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##      0.8333333&lt;/span&gt;&lt;br /&gt;tree.precision&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Pos Pred Value&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##      0.8088235&lt;/span&gt;&lt;br /&gt;forest.precision&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Pos Pred Value&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##      0.8134328&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;log.recall&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Sensitivity&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0.9016393&lt;/span&gt;&lt;br /&gt;tree.recall&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Sensitivity&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0.9016393&lt;/span&gt;&lt;br /&gt;forest.recall&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Sensitivity&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0.8934426&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;log.F1&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##        F1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 0.8661417&lt;/span&gt;&lt;br /&gt;tree.F1&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##        F1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 0.8527132&lt;/span&gt;&lt;br /&gt;forest.F1&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##        F1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 0.8515625&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Surprisingly, the logistic regression model performs the best, with the top precision score and equal recall score with that of the decision tree. With more time, I’d see if tweaks to the decision tree and random forest models could change this. It's also possible over/undersampling could help. From here on I will use the logistic regression model.&lt;/p&gt;
&lt;h2 id="examine-the-incorporation-of-time-information"&gt;Examine the incorporation of time information &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#examine-the-incorporation-of-time-information"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Per the second aim, examine the inclusion of time information. This requires more data munging. Taking code used from above, I will extend to include the derivation of a very basic time period variable.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Create binary 'leading_indicator' column&lt;/span&gt;&lt;br /&gt;model.df&lt;span class="token operator"&gt;$&lt;/span&gt;leading_indicator &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Min date for which a leading_indicator can be calculated (lower limit of data)&lt;/span&gt;&lt;br /&gt;min.date &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; min&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;date&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# If month before 'churn' (churn-1), is below the level of mandates of the month 2 months prior (churn-2) then&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# make leading_indicator == 1&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;for&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;company &lt;span class="token keyword"&gt;in&lt;/span&gt; churners&lt;span class="token operator"&gt;$&lt;/span&gt;company_id&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Subset data to company&lt;/span&gt;&lt;br /&gt;    df.sub &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; subset&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;,&lt;/span&gt; df&lt;span class="token operator"&gt;$&lt;/span&gt;company_id &lt;span class="token operator"&gt;==&lt;/span&gt; company&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Get month prior to churn&lt;/span&gt;&lt;br /&gt;    month.prior &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;date&lt;span class="token punctuation"&gt;[&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;churn &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%m-%&lt;/span&gt; months&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Get two months prior to churn&lt;/span&gt;&lt;br /&gt;    two.month.prior &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;date&lt;span class="token punctuation"&gt;[&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;churn &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%m-%&lt;/span&gt; months&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;2&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# If two months prior is within dataset date range and level of mandates is greater than 0&lt;/span&gt;&lt;br /&gt;    &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;two.month.prior &lt;span class="token operator"&gt;&gt;&lt;/span&gt; min.date&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;mandates&lt;span class="token punctuation"&gt;[&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;date &lt;span class="token operator"&gt;==&lt;/span&gt; two.month.prior&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="token comment"&gt;# Compare number of mandates 1 month prior to 2 months prior, if less, mark 'leading_indicator' as '1'&lt;/span&gt;&lt;br /&gt;        &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;mandates&lt;span class="token punctuation"&gt;[&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;date &lt;span class="token operator"&gt;==&lt;/span&gt; month.prior&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;mandates&lt;span class="token punctuation"&gt;[&lt;/span&gt;df.sub&lt;span class="token operator"&gt;$&lt;/span&gt;date &lt;span class="token operator"&gt;==&lt;/span&gt; two.month.prior&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;            model.df&lt;span class="token punctuation"&gt;[&lt;/span&gt;model.df&lt;span class="token operator"&gt;$&lt;/span&gt;company_id &lt;span class="token operator"&gt;==&lt;/span&gt; company&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token operator"&gt;$&lt;/span&gt;leading_indicator &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;br /&gt;        &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="of-the-churners%2C-how-many-have-a-leading-indicator%3F"&gt;Of the churners, how many have a leading indicator? &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#of-the-churners%2C-how-many-have-a-leading-indicator%3F"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;model.df &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    filter&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    group_by&lt;span class="token punctuation"&gt;(&lt;/span&gt;leading_indicator&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    summarise&lt;span class="token punctuation"&gt;(&lt;/span&gt;n&lt;span class="token operator"&gt;=&lt;/span&gt;n&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token percent-operator operator"&gt;%&gt;%&lt;/span&gt;&lt;br /&gt;    mutate&lt;span class="token punctuation"&gt;(&lt;/span&gt;percent &lt;span class="token operator"&gt;=&lt;/span&gt; round&lt;span class="token punctuation"&gt;(&lt;/span&gt;n &lt;span class="token operator"&gt;/&lt;/span&gt; sum&lt;span class="token punctuation"&gt;(&lt;/span&gt;n&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;*&lt;/span&gt; &lt;span class="token number"&gt;100&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;## # A tibble: 2 x 3&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   leading_indicator     n percent&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##               &amp;lt;dbl&gt; &amp;lt;int&gt;   &amp;lt;dbl&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 1                 0   264    91.3&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## 2                 1    25     8.7&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="re-train-model-and-evaluate"&gt;Re-train model and evaluate &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#re-train-model-and-evaluate"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Re-split data so 'leading_indicator' is in columns (the index remains the same)&lt;/span&gt;&lt;br /&gt;train.df &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; model.df&lt;span class="token punctuation"&gt;[&lt;/span&gt;index&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;test.df  &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; model.df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token operator"&gt;-&lt;/span&gt;index&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="logistic-2"&gt;Logistic &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#logistic-2"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Run model&lt;/span&gt;&lt;br /&gt;lead.logistic.model &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; glm&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;~&lt;/span&gt; incorporation_time &lt;span class="token operator"&gt;+&lt;/span&gt; vertical &lt;span class="token operator"&gt;+&lt;/span&gt; leading_indicator&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                      data   &lt;span class="token operator"&gt;=&lt;/span&gt; train.df&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                      family &lt;span class="token operator"&gt;=&lt;/span&gt; binomial&lt;span class="token punctuation"&gt;(&lt;/span&gt;link &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'logit'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predict&lt;/span&gt;&lt;br /&gt;log.pred &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;lead.logistic.model&lt;span class="token punctuation"&gt;,&lt;/span&gt; newdata &lt;span class="token operator"&gt;=&lt;/span&gt; test.df&lt;span class="token punctuation"&gt;,&lt;/span&gt; type &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'response'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Convert probs to binary&lt;/span&gt;&lt;br /&gt;log.pred &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; as.factor&lt;span class="token punctuation"&gt;(&lt;/span&gt;ifelse&lt;span class="token punctuation"&gt;(&lt;/span&gt;log.pred &lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token number"&gt;0.5&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Evaluation Metrics&lt;/span&gt;&lt;br /&gt;lead.log.result    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; confusionMatrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;data &lt;span class="token operator"&gt;=&lt;/span&gt; log.pred&lt;span class="token punctuation"&gt;,&lt;/span&gt; test.df&lt;span class="token operator"&gt;$&lt;/span&gt;churn&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;lead.log.precision &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; log.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Pos Pred Value'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;lead.log.recall    &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; log.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Sensitivity'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;lead.log.F1        &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; log.result&lt;span class="token operator"&gt;$&lt;/span&gt;byClass&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'F1'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="evaluation-metrics-2"&gt;Evaluation Metrics &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#evaluation-metrics-2"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Compare the precision and recall of the logistic model with and without the &lt;code&gt;lead_indicator&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;log.precision&lt;br /&gt;&lt;span class="token comment"&gt;## Pos Pred Value&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##      0.8333333&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;lead.log.precision&lt;br /&gt;&lt;span class="token comment"&gt;## Pos Pred Value&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##      0.8333333&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;log.recall&lt;br /&gt;&lt;span class="token comment"&gt;## Sensitivity&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0.9016393&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;lead.log.recall&lt;br /&gt;&lt;span class="token comment"&gt;## Sensitivity&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##   0.9016393&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Have a look at the model coefficients and p-values&lt;/span&gt;&lt;br /&gt;summary&lt;span class="token punctuation"&gt;(&lt;/span&gt;lead.logistic.model&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Call:&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## glm(formula = churn ~ incorporation_time + vertical + leading_indicator,&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##     family = binomial(link = "logit"), data = train.df)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Deviance Residuals:&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##     Min       1Q   Median       3Q      Max  &lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## -1.4429  -0.8252  -0.4957   0.9938   2.5564  &lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Coefficients:&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##                              Estimate Std. Error z value Pr(&gt;|z|)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## (Intercept)                   0.74066    0.20007   3.702 0.000214 ***&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## incorporation_time           -0.26140    0.03045  -8.584  &amp;lt; 2e-16 ***&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## verticalfreelance developer   0.12614    0.21737   0.580 0.561714&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## verticalgym/fitness          -0.91099    0.22342  -4.077 4.55e-05 ***&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## leading_indicator            18.06219  482.97671   0.037 0.970168&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## (Dispersion parameter for binomial family taken to be 1)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##     Null deviance: 907.42  on 722  degrees of freedom&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Residual deviance: 736.18  on 718  degrees of freedom&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## AIC: 746.18&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Number of Fisher Scoring iterations: 15&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Generally, it is best to minimise the &lt;code&gt;AIC&lt;/code&gt;. The &lt;code&gt;Logistic.model&lt;/code&gt; model AIC is 800.5 compared with the &lt;code&gt;lead.logistic.model&lt;/code&gt; incorporating the &lt;code&gt;lead_indicator&lt;/code&gt; is 746.18. The &lt;code&gt;lead_indicator&lt;/code&gt; has not changed the predictive power on this dataset, but since the &lt;code&gt;AIC&lt;/code&gt; favours a better model fit whilst penalising for additional predictors, the model to choose is the &lt;code&gt;lead.logistic.model&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="re-train-model-and-save"&gt;Re-train model and save &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#re-train-model-and-save"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Re-train on all data&lt;/span&gt;&lt;br /&gt;final.model &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; glm&lt;span class="token punctuation"&gt;(&lt;/span&gt;churn &lt;span class="token operator"&gt;~&lt;/span&gt; incorporation_time &lt;span class="token operator"&gt;+&lt;/span&gt; vertical &lt;span class="token operator"&gt;+&lt;/span&gt; leading_indicator&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                      data   &lt;span class="token operator"&gt;=&lt;/span&gt; model.df&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                      family &lt;span class="token operator"&gt;=&lt;/span&gt; binomial&lt;span class="token punctuation"&gt;(&lt;/span&gt;link &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'logit'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="recommendations-for-further-investigation%2Fcomments"&gt;Recommendations for further investigation/Comments &lt;a class="direct-link" href="https://lukesingham.com/how-to-make-a-churn-model-in-r/#recommendations-for-further-investigation%2Fcomments"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;lead_indicator&lt;/code&gt; was a quick and dirty test, I’d spend more time looking at a better construction (e.g. moving avg)&lt;/li&gt;
&lt;li&gt;If the cost of retention activities vs losing a customer was known then the optimal trade-off in terms of business cost could be found.&lt;/li&gt;
&lt;li&gt;Incorporating additional data, e.g. CRM data showing interactions. Potentially assessing sales/account staff.&lt;/li&gt;
&lt;li&gt;If it were a production model prompting staff to do retention calls, evaluate the impact of such calls through modelling e.g. a/b testing&lt;/li&gt;
&lt;li&gt;Test model performance with a change to balancing the classes e.g. under/oversampling, bootstrap samples. This may explain the relative underperformance of tree based models in this exercise.&lt;/li&gt;
&lt;li&gt;Try other binary classifier models.&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Tue, 21 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/how-to-make-a-churn-model-in-r/</guid></item><item><title>Cryptocurrencies</title><link>https://rob.sh/post/cryptocurrency/</link><description>&lt;p&gt;The concept of having no central entity control currency seems attractive to a
lot of people.  However, trust in some decentralised entity means trusting the
way that they operate their business - how they&amp;rsquo;re able to audit their code,
and write bug-free software. The only thing I know about software is that it
isn&amp;rsquo;t ever bug-free. To reduce MTBF, you implement things multiple times, in
disjoint environments.&lt;/p&gt;
&lt;p&gt;That said, &lt;a href="https://tether.to/tether-critical-announcement/"&gt;the latest hack on a cryptocurrency/smart
wallet&lt;/a&gt; I saw, made me wonder
about their testing. How many bugs are they looking for, in terms of both their
standard operating environment, as well as for security.&lt;/p&gt;</description><author>rob.sh</author><pubDate>Tue, 21 Nov 2017 00:30:00 GMT</pubDate><guid isPermaLink="true">https://rob.sh/post/cryptocurrency/</guid></item><item><title>PyEnv is the new Conda</title><link>https://bastibe.de/2017-11-20-pyenv.html</link><description>&lt;p&gt;How to install Python? If your platform has a package manager, you might be tempted to use that to install Python. But I don't like that. That version is often outdated, and you risk messing with an integral part of your operating system. Instead, I like to install a separate Python in my home directory. I used to use &lt;a href="https://conda.io/miniconda.html"&gt;Anaconda&lt;/a&gt; (or &lt;a href="http://winpython.github.io/"&gt;WinPython&lt;/a&gt;, or &lt;a href="https://www.enthought.com/product/enthought-python-distribution"&gt;EPD&lt;/a&gt;) to do this. But now there is a better way: &lt;a href="https://github.com/pyenv/pyenv"&gt;PyEnv&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The thing is: PyEnv installs (any version of) Python. That's all it does.&lt;/p&gt;
&lt;p&gt;So why would I choose PyEnv over the more popular Anaconda? Because Anaconda is a Python distribution, a package manager, an environment manager, and a platform for paid packages. In the past, they once did &lt;a href="https://stackoverflow.com/questions/38524856/anaconda-3-for-linux-has-no-ensurepip#39114277"&gt;break pip&lt;/a&gt; because they wanted to promote conda instead. Some features of conda &lt;a href="https://anaconda.org/"&gt;require a login&lt;/a&gt;, some require a &lt;a href="https://www.anaconda.com/enterprise/"&gt;paid subscription&lt;/a&gt;. When you install packages through conda, you get binaries and source code from anaconda's servers, &lt;em&gt;not&lt;/em&gt; the official packages from PyPi, which might or might not be up-to-date and feature-complete. For every package you install, you have to make a choice of using pip or conda, and the same goes for specifying your dependencies.&lt;/p&gt;
&lt;p&gt;As an aside, many of these complaints are just as true for package-manager-provided Python packages (which often &lt;a href="https://askubuntu.com/questions/879437/ensurepip-is-disabled-in-debian-ubuntu-for-the-system-python#897004"&gt;break pip&lt;/a&gt;, too!). Just like Anaconda, package managers want to be the true and only source of packages, and don't like to interact with Python's own package manager.&lt;/p&gt;
&lt;p&gt;In contrast, with PyEnv, you install a Python. This can be a version of CPython, PyPy, IronPython, Jython, Pyston, stackless, miniconda, or even Anaconda. It downloads the sources from the official repos, and compiles them on your machine &lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. Plus, it provides an easy and transparent way of switching between installed versions (including any system-installed versions). After that, you use Python's own venv and pip.&lt;/p&gt;
&lt;p&gt;I find this process much simpler, and easier to manage, because it relies on small, orthogonal tools (pyenv, venv, pip) instead of one integrated conda that kind of does everything. I also like to use these official tools and packages instead of conda's parallel universe of mostly-open, mostly-free, mostly-standard replacements.&lt;/p&gt;
&lt;p&gt;Mind you, conda solved real problems back in the day (binary package distributions, Python version management, and environment management), and arguably still does (MKL et al, paid packages). But ever since wheels became &lt;a href="https://pythonwheels.com/"&gt;ubiquitous and painless&lt;/a&gt;, and virtualenv was &lt;a href="https://docs.python.org/3/library/venv.html"&gt;integrated into Python&lt;/a&gt;, and the development of PyEnv, these issues now have better solutions, and conda is no longer needed for my applications.&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;the downside of compilation is: no Windows support.&lt;a class="footnote" href="#fnref-1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>bastibe.de</author><pubDate>Mon, 20 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-11-20-pyenv.html</guid></item><item><title>Server security scan #manpage</title><link>https://yasha.solutions/server-security-scan-manpage/</link><description>chkrootkit – Linux rootkit scanner What it does : Find rootkits
Where to find it : in your distribution – or on chkrootkit.org
Malware protection Option 1: ISPProtect – 90 euro / year but worth it.
Where to find it : ispprotect.com
Step #1: Get a licence Step #2: Download and install and run Then indicate your key number or trial if you want a trial version.
Indicate /var/www to start the scan on the web installs.</description><author>Yasha Solutions</author><pubDate>Mon, 20 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/server-security-scan-manpage/</guid></item><item><title>Nextcloud snap to be updated to v12</title><link>https://kyrofa.com/posts/nextcloud-snap-to-be-updated-to-v12/</link><description>If you&amp;rsquo;re a user of the Nextcloud snap, you may have noticed that upstream Nextcloud released v12 a while back, but you&amp;rsquo;re still on v11. That&amp;rsquo;s because v12 introduced several regressions that made us maintainers decide to hold off on the upgrade. Thankfully, things are finally looking up.
As of today, it seems that all the blocking regressions have been fixed. Which means that, barring any additional regressions being introduced between now and then, v12.</description><author>kyrofa's blog</author><pubDate>Mon, 20 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/nextcloud-snap-to-be-updated-to-v12/</guid></item><item><title>Knock, knock. This thing still on?</title><link>https://skife.org/b3/knock-knock-still-on/</link><description>&lt;p&gt;I've attempted to wake this blog up a couple times, but between &lt;a href="https://jekyllrb.com/" rel="external"&gt;Jekyll&lt;/a&gt; changing, &lt;a href="http://pygments.org/" rel="external"&gt;Pygments&lt;/a&gt; changing, and whatnot, it has been more pain than any given post seemed worth. I've recently had three folks independently chastise me for no longer writing, however, and three is a magic number.&lt;/p&gt;
&lt;p&gt;So, this is basically just a test post as I try converting over to &lt;a href="http://gohugo.io/" rel="external"&gt;Hugo&lt;/a&gt;. Jekyll resisted hard enough that I declared bankruptcy. We'll try this one. If I get annoyed at it, &lt;a href="https://www.getgutenberg.io/" rel="external"&gt;Gutenberg&lt;/a&gt; is next on the list. &lt;a href="https://twitter.com/tcurdt" rel="external"&gt;Torsten&lt;/a&gt; says nice things about it :-)&lt;/p&gt;
&lt;p&gt;All my old posts should be &lt;a href="https://skife.org/b3/knock-knock-still-on/archive.html"&gt;exactly where I left them&lt;/a&gt;, no sense breaking URLs.&lt;/p&gt;
&lt;p&gt;For a test post I need to include some code, that being most of the point of this thig, so some Rust from &lt;a href="https://github.com/brianm/wsf" rel="external"&gt;wsf&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="giallo" style="color: #24292E; background-color: #FFFFFF;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span style="color: #D73A49;"&gt;impl&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt; From&lt;/span&gt;&lt;span&gt;&amp;lt;hyper&lt;/span&gt;&lt;span style="color: #D73A49;"&gt;::&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span style="color: #D73A49;"&gt;::&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt;Error&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #D73A49;"&gt; for&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt; CliError&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #D73A49;"&gt;    fn&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt; from&lt;/span&gt;&lt;span&gt;(err&lt;/span&gt;&lt;span style="color: #D73A49;"&gt;:&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt; hyper&lt;/span&gt;&lt;span style="color: #D73A49;"&gt;::&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt;error&lt;/span&gt;&lt;span style="color: #D73A49;"&gt;::&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt;Error&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style="color: #D73A49;"&gt; -&amp;gt;&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt; CliError&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #6F42C1;"&gt;        CliError&lt;/span&gt;&lt;span style="color: #D73A49;"&gt;::&lt;/span&gt;&lt;span style="color: #6F42C1;"&gt;Http&lt;/span&gt;&lt;span&gt;(err)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far, so good.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox" /&gt;
Build with Hugo&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox" /&gt;
Code is pretty&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox" /&gt;
Ensure Atom/RSS is sane&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox" /&gt;
Add some kind of commenting (&lt;a href="https://staticman.net/" rel="external"&gt;staticman&lt;/a&gt;?)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox" /&gt;
Better favicon&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Off to deploy and see if this thing works!&lt;/p&gt;</description><author>Brian's Waste of Time</author><pubDate>Sun, 19 Nov 2017 03:09:31 GMT</pubDate><guid isPermaLink="true">https://skife.org/b3/knock-knock-still-on/</guid></item><item><title>Installing Emacs on Windows</title><link>https://bastibe.de/2017-11-19-emacs-on-windows.html</link><description>&lt;p&gt;The &lt;a href="https://www.gnu.org/software/emacs/download.html#windows"&gt;official website&lt;/a&gt; states that you need to download Emacs from a &lt;a href="http://ftpmirror.gnu.org/emacs/windows"&gt;nearby GNU mirror&lt;/a&gt;. However, this does not install gnutls, which is required for installing packages from &lt;a href="http://melpa-stable.milkbox.net"&gt;melpa&lt;/a&gt; or &lt;a href="https://marmalade-repo.org/"&gt;marmalade&lt;/a&gt;. The &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs-gnutls/Help-For-Users.html"&gt;documentation&lt;/a&gt; says that this can be obtained from &lt;a href="https://sourceforge.net/projects/ezwinports/files/"&gt;ezwinports&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, I have found that this does not work any more: As of Emacs 25, Emacs is available in 64 bit, but ezwinport only supplies 32 bit binaries. I had to search a bit, but the (in retrospect, obvious) solution is to download the required binaries from &lt;a href="https://gnutls.org/download.html"&gt;GnuTLS's website&lt;/a&gt;, directly. Then unpack all &lt;code&gt;*.dll&lt;/code&gt; from the &lt;code&gt;bin&lt;/code&gt; directory to your Emacs's &lt;code&gt;bin&lt;/code&gt; directory, and you are good to go.&lt;/p&gt;
&lt;p&gt;This situation is really a bit sad. Installing Emacs should not be this hard. But there is &lt;a href="https://lists.gnu.org/archive/html/emacs-devel/2017-10/msg00805.html"&gt;talk&lt;/a&gt; about providing a Windows installer for Emacs in one of the next versions, which will hopefully fix these issues.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Sun, 19 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-11-19-emacs-on-windows.html</guid></item><item><title>Voice &amp;amp; IOT</title><link>https://yasha.solutions/voice-iot/</link><description>Voice and IOT
Amazon Echo, Alexa, Google Home, Apple HomePod and Siri (and Microsoft Cortana) are all fighting to control the voice market. While they get full respect for doing so, I am not gonna say I am particularly trusting any of these companies to provide us with the best level of privacy, service and control over what we do with our devices and how is the data used.
Therefore I am compiling here some resources which I’ll probably update as we go on interesting DIY tools to build similar devices.</description><author>Yasha Solutions</author><pubDate>Sun, 19 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/voice-iot/</guid></item><item><title>The Brothers Karamazov</title><link>https://nindalf.com/posts/the-brothers-karamazov/</link><description>The Brothers Karamazov by Fyodor Dostoevsky is a challenging but rewarding read, with richly detailed characters and authentic relationships.</description><author>Krishna's blog</author><pubDate>Sun, 19 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/the-brothers-karamazov/</guid></item><item><title>Game Review: WildSnake - SNES</title><link>https://kernelcurry.com/blog/snes-wildsnake/</link><description>&lt;figure&gt;&lt;img src="https://kernelcurry.com/blog/snes-wildsnake/cart-front.png" /&gt;&lt;figcaption&gt;
 &lt;h4&gt;Wildsnake Cartridge&lt;/h4&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;If you thought Tetris was fun, get ready for Tetris with snakes! Yeah, actual Snakes; Wild Snakes. Alexey Pajitnov, the creator of Tetris, thought it would be a good idea to add snakes to the classic game. To be honest, when I started playing this game I thought it was just a crappy rip off of Tetris, but NOPE the creator of Tetris himself thought this was a good idea&amp;hellip; sigh.&lt;/p&gt;</description><author>KernelCurry</author><pubDate>Sat, 18 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kernelcurry.com/blog/snes-wildsnake/</guid></item><item><title>An overview of arrays in Ada 2012</title><link>https://www.jviotti.com/2017/11/18/an-overview-of-arrays-in-ada-2012.html</link><description>This article is an overview of array types in Ada 2012</description><author>Juan Cruz Viotti</author><pubDate>Sat, 18 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.jviotti.com/2017/11/18/an-overview-of-arrays-in-ada-2012.html</guid></item><item><title>Drafting</title><link>https://lambdaland.org/posts/2017-11-18-drafting/</link><description>&lt;p&gt;I once asked my dad over email how to improve my the potency of my words and thoughts. His reply came back as one word:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Revision.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Good writing does not emerge spontaneously; it comes as one practices writing. A “draft” is a pass of writing a particular work. It’s like sketching in art: when an artist starts a painting, they usually start with a rough sketch outlining where the ﬁgures will be, what the landscape will be like, etc. These sketches are composed of many lines: each coming closer to their ﬁnal position.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Rearing Horse by Leonardo da Vinci" src="https://www.leonardodavinci.net/images/drawings/rearing-horse.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;When I draft, I start out with a few different freewrites. I usually start with a stream of consciousness to get my ideas out on paper and to sort of flesh out what I actually want to talk about. Then I will beat out a very rough draft. After this initial draft, I usually will have a good idea of how I want to treat the subject matter. I will do things like read my paper aloud to hear how it flows, check for grammatical inconsistencies, look for more concise phrases that convey my ideas more clearly. Occasionally I will decide that I need to change how I structure my argument entirely. In these situations I will often do a complete rewrite.&lt;/p&gt;
&lt;p&gt;I usually use something akin to &lt;a class="link-external" href="https://en.wikipedia.org/wiki/Software_versioning#Degree_of_compatibility" rel="external"&gt;semantic versioning&lt;/a&gt;—the first version number of my draft indicates the major write of the paper, (e.g. 0.0.1 for the rough draft, 1.0.0 for the first full draft after the rough draft, 2.0.0 for the next full rewrite, etc.) the second number might indicate significant changes in the text, but not complete structural changes, and the third number indicates minor changes, such as spelling and grammar errors.&lt;/p&gt;
&lt;p&gt;I don’t follow this system too rigorously; it’s just a kind of fun thing I use to keep track of my drafts. My brain is messy some times, and I’m okay with that.&lt;/p&gt;</description><author>Lambda Land</author><pubDate>Sat, 18 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2017-11-18-drafting/</guid></item><item><title>Recurse Center 9: rayon par iter</title><link>https://peterlyons.com/problog/2017/11/recurse-center-9-rayon-par-iter/</link><description>&lt;p&gt;Today I refactored my little rust blockchain miner to divide the mining work across multiple CPUs. The rayon crate's &lt;code&gt;par_iter()&lt;/code&gt; provides the magic for this. Before coding that, I was imagining how I'd handle that given I'm searching a 32-bit integer space where each number is equally likely to be a "golden nonce" (meaning a successful block mine). The most straightforward approach I could think of would be to break the single range into equal-sized partial ranges and ask the OS to distribute the load across cores. So instead of trying 0 then 1 then 2 in serial, you'd have 4 workers starting at (using 100 for obviousness) 0, 25, 50, 75 for the first round then each would advance so you'd have 1, 26, 51, 76 and so on.&lt;/p&gt;
&lt;p&gt;I coded a simpler scratch version and printed debug output and was delighted to see at least part of that holding true with rayon. I could definitely see several sequences of incrementing nonces being tested in ascending order, they just weren't obviously mapped to the range in a way I could grok.&lt;/p&gt;
&lt;p&gt;I also found out the testing I did yesterday with the &lt;code&gt;shaman&lt;/code&gt; crate had a bug and you can indeed both give it read-only access to an existing vector of the payload data plus you can call &lt;code&gt;.insert()&lt;/code&gt; more than once, so I refactored to just call &lt;code&gt;.insert()&lt;/code&gt; with a reference to the payload then again with a reference to the 4-byte nonce slice and that avoids any memory copies and mutation, which I believe is nearly as good as you can do in rust.&lt;/p&gt;
&lt;p&gt;So now my macbook can mine 8-16x faster than yesterday. However, the concurrent version no longer has deterministic behavior, so finding the same nonce on the same payload doesn't always take the same number of hashes, and the lower difficulty setting the larger the number of possible golden nonces so on separate runs you can mine different nonces. But however with multiple runs you do see it is just a small set of nonces that repeat.&lt;/p&gt;
&lt;p&gt;How to print progress in a unit-test-friendly way is still unclear, at least in terms of what would be the idiom in rust. Maybe since output is captured by default you just don't worry about it? Not sure but I tried to use a channel such that each worker could send a message to the parent thread whenever it wanted to report a batch of a million non-golden nonces tested, allowing the parent thread to handling printing that as a dot to stdout, but I couldn't get that to compile.&lt;/p&gt;
&lt;p&gt;One helpful development pattern I'm using a lot is focusing on the core function signatures and building a mock-up in a separate "scratch" project I have where the guts of most functions are stubbed out to just return a hard coded value or some dummy data but all the type signatures are exactly what I need for the real project. Then I iterate on that and do my compiler battling, and when that's over only then do I start adding implementation logic to the function bodies. That has been helpful this week for sure.&lt;/p&gt;
&lt;p&gt;In other news I made Firefox Quantum my default browser today, partially due to rust fanboyism. So far so good. The "Vertical Tabs Reloaded" add-on is nice.&lt;/p&gt;
&lt;p&gt;Oh random shell tip when debugging checksums. I wasn't sure if I was using the rust &lt;code&gt;shaman&lt;/code&gt; crate correctly so I wrote a scratch rust program to feed it data from the first command line argument, then simulate a nonce as &lt;code&gt;"aaaa"&lt;/code&gt; and print the hex of that hash. Then I verified with an independent implementation via the command line: &lt;code&gt;echo -n abcdefghijkaaaa| shasum -a 256&lt;/code&gt; and when both hashes were identical I knew I had the right code. (Don't forget the &lt;code&gt;-n&lt;/code&gt; or you'll accidentally include the newline as your hash payload).&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 18 Nov 2017 00:05:44 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-9-rayon-par-iter/</guid></item><item><title>Never Graduate</title><link>https://peterlyons.com/problog/2017/11/never-graduate/</link><description>&lt;p&gt;&lt;strong&gt;Neo&lt;/strong&gt;: Whoa. Déjà vu. Déjà vu.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Trinity&lt;/strong&gt;: What did you see, Neo?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Neo&lt;/strong&gt;: It felt like I just did three Code and Coffees back to back.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Morpheus&lt;/strong&gt;: Code and Coffee is a system. A system with rules. Rules like "Code and Coffee is once a week". Rules like "Code and Coffee is nine to noon".
Some of these rules can be bent. Others can be broken.
What if I told you that you could do sixty Code and Coffees in a row?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Neo&lt;/strong&gt;: That's impossible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Morpheus&lt;/strong&gt;: Is that what you believe? What if I told you some people do one hundred and eighty Code and Coffees back to back? Impossible? Free your mind. Never graduate.&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Morpheus slow-mo backflips over a desk, reaches  overhead to start typing on a laptop while still upside down before landing into a swivel chair&lt;/em&gt;)&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 17 Nov 2017 23:11:59 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/never-graduate/</guid></item><item><title>Use the telephone for outgoing requests, email for incoming requests</title><link>https://www.databasesandlife.com/email-vs-phone/</link><description>&lt;p&gt;I have been thinking about &lt;strong&gt;emails vs phone&lt;/strong&gt;, or more generally &lt;strong&gt;asynchronous vs synchronous&lt;/strong&gt; communication, and have realized:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you &lt;strong&gt;receive a call&lt;/strong&gt;, it breaks your flow, &lt;strong&gt;which is bad.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you &lt;strong&gt;send an email&lt;/strong&gt;, it breaks your flow, &lt;strong&gt;which is bad.&lt;/strong&gt; (As you have to wait for an answer, and do something else in the meantime.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If &lt;strong&gt;you&lt;/strong&gt; have a question, the optimal strategy (for you) is to &lt;strong&gt;make a call&lt;/strong&gt;.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Fri, 17 Nov 2017 16:35:38 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/email-vs-phone/</guid></item><item><title>Lord of the Flies</title><link>https://apurva-shukla.me/bookshelf/lord-of-the-flies/</link><description>⭐ ⭐ ⭐ ⭐ Thought provoking, revealing the hidden precipice of our human nature; animalistic and savage. Golding cleverly guides the audience…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Fri, 17 Nov 2017 13:53:02 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/lord-of-the-flies/</guid></item><item><title>Recurse Center 8: binary literals</title><link>https://peterlyons.com/problog/2017/11/recurse-center-8-binary-literals/</link><description>&lt;p&gt;Not that much to report today mostly some tweaks to my rust blockchain miner exercise. I remembered rust has binary literals and bitwise operations are one place they actually are useful. I've watched all the &lt;a href="http://intorust.com"&gt;Into Rust&lt;/a&gt; tutorials/exercises and they were great but there's only a handful. I did an exercism on isograms and demoed my rustblock program during Thursday evening demos. As tends to be the case, I learned a lot from the RCers while talking about the miner and apparently the bitcoin difficulty factor is so high that you need datacenter scale computing power to even hope to mine one block in a small number of minutes. My rust miner starts to take more than a few seconds searching for a golden nonce with about 27 or 28 leading zeros so presumably the bitcoin work factor is quite a bit larger than that (with a maximum of 256 since that's the sha size but practically has to be quite a bit lower than that to allow space for enough blocks to get unique hashes for all of bitcoin's lifetime I guess).&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 17 Nov 2017 04:18:51 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-8-binary-literals/</guid></item><item><title>How to root Nexus 7 (2012) and flash it to LineageOS, from Mac OSX</title><link>http://blog.pythonaro.com/2017/11/how-to-root-nexus-7-2012-and-flash-it.html</link><description>I've finally got fed up enough with the old Nexus 7 (2012) that we originally bought to let the kids play - it's never really worked properly, getting laggy every 5 minutes and running out of battery after an hour. The kids moved on to an iPad, so I "installed" this crappy tablet to the kitchen wall, hoping to use it for calendaring and podcasts, but it was still horrendously laggy. I've decided to give a chance to LineageOS (previously CyanogenMod) to see if it helps. I'd be interested to know if anybody else uses a tablet wall-mounted in their kitchen, and what apps they installed - at the moment I have Paprika, the BBC players and weather, and PodcastAddict.&lt;br /&gt;
&lt;br /&gt;
Here are the full steps required for flashing - I write them here because some of these are at risk to disappear from the internet for good after the demise of CyanogenMod wiki.&lt;br /&gt;
&lt;br /&gt;
Note: &lt;b&gt;THIS WILL WIPE YOUR DEVICE, YOU WILL LOSE EVERYTHING THAT IS ON IT&lt;/b&gt; so first make backups etc etc.&lt;br /&gt;
&lt;br /&gt;
First you need to install the Android tools. I recommend doing this with &lt;a href="https://brew.sh/" target="_blank"&gt;homebrew&lt;/a&gt;, install it if you don't have it yet (it's extremely useful in many many cases).&lt;br /&gt;
Then open a terminal on your mac and type:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;brew tap caskroom/cask &lt;/li&gt;
&lt;li&gt;brew tap caskroom/versions&lt;/li&gt;
&lt;li&gt;brew cask install java8&lt;/li&gt;
&lt;li&gt;brew cask install android-sdk&lt;/li&gt;
&lt;/ul&gt;
Enable Developer Mode on the tablet by tapping 7 times on the build number under &lt;i&gt;Settings -&amp;gt; About tablet.&lt;/i&gt;&lt;br /&gt;
Back to Settings, tap on &lt;i&gt;Developer Options&lt;/i&gt; and enable USB Debug mode and Stay Awake.&lt;br /&gt;
Go back to your mac terminal and type:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;sudo adb start-server&lt;/li&gt;
&lt;/ul&gt;
This starts the android debugger server. &lt;br /&gt;
Connect the tablet with a real USB cable (beware charging-only cables! Those won't work.)&lt;br /&gt;
On the tablet screen, you should be prompted to authorize the device; do it.&lt;br /&gt;
Back to terminal:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;adb reboot bootloader&lt;/li&gt;
&lt;/ul&gt;
once the device comes back in bootloader mode:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;fastboot oem unlock&lt;/li&gt;
&lt;/ul&gt;
Accept the disclaimer on the tablet by clicking the power button when &lt;i&gt;Yes&lt;/i&gt; is highlighted (you can move with the volume buttons).&lt;br /&gt;
If it doesn't reboot on its own, select &lt;i&gt;Start&lt;/i&gt; (again with the power button). At this point you should see an unlocked pad at the bottom of the screen as Android loads.&lt;br /&gt;
Note: if you plan to flash another OS, there is no point in going through the whole setup at this point, skip as much as you can. &lt;br /&gt;
Re-enable Developer mode and USB Debugging.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;At this point the machine is rooted. &lt;/b&gt;The following steps are necessary only if you want to install LineageOS or other hacks; at the very minimum, though, you should install Trimmer (fstrim) from the Play store and use it liberally. Anyway, on with the flashing... &lt;br /&gt;
&lt;br /&gt;
Get the latest image for "grouper" from &lt;a href="https://twrp.me/"&gt;https://twrp.me/&lt;/a&gt;, and unzip it.&lt;br /&gt;
Back to the terminal:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;cd folder/where/you/have/your-downloaded-image.img&lt;/li&gt;
&lt;li&gt;fastboot flash recovery your-downloaded-image.img&lt;/li&gt;
&lt;li&gt;adb reboot bootloader&lt;/li&gt;
&lt;/ul&gt;
At this point you have a custom recovery image with a bunch of nifty features that make it very easy to hack the device. Tap Wipe and select system, cache, and dalvik.&lt;br /&gt;
Get the image you want to install. I'm currently trying &lt;a href="https://forum.xda-developers.com/nexus-7/development/rom-lineageos-14-1-nexus-7-2012-t3530261" target="_blank"&gt;this&lt;/a&gt; but in general anything after CM10 / Android 4.1 may be on the slow side for the original Nexus. You probably want the Google Apps from opengapps.org - choose ARM / 7.1 and the Micro option. Save both the apps zip and the image zip in the same folder.&lt;br /&gt;
Back to Terminal, let's copy these files to the device:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;cd folder/where/you/have/your/zips&lt;/li&gt;
&lt;li&gt;adb push your-downloaded-image.zip /&lt;/li&gt;
&lt;li&gt;adb push your-downloaded-gapps.zip /&lt;/li&gt;
&lt;/ul&gt;
On the tablet, in the recovery screen, select Install, tap on Install ZIP, then select the image file and install. Repeat for the gapps file. If gapps refuse to go in because of space constraints, download &lt;a href="https://www.androidfilehost.com/?fid=745425885120692225" target="_blank"&gt;this file&lt;/a&gt;, rename it &lt;i&gt;gapps-config.txt&lt;/i&gt;, then copy it to the device in the same location as the gapps zip:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;adb push gapps-config.txt /&lt;/li&gt;
&lt;/ul&gt;
and try again to install the gapps image. &lt;ul&gt;
&lt;/ul&gt;
Reboot the tablet. You might have to re-enable developer mode and usb debugging.&lt;br /&gt;
Install the &lt;a href="https://play.google.com/store/apps/details?id=com.fifthelement.trimmer" target="_blank"&gt;Trimmer (fstrim)&lt;/a&gt; app, which is absolutely necessary. Launch it and click Trim Now. Click on the settings icon and enable autotrim as frequently as possible. In fact, every time you install an app or write a bunch of files, before you launch the new app, open Trimmer and do a trim, or it will all get laggy again.&lt;br /&gt;
Another good app is &lt;a href="https://play.google.com/store/apps/details?id=com.icecoldapps.sshserver&amp;amp;hl=en" target="_blank"&gt;Android SSH Server&lt;/a&gt;, although it's a bit old it still works fine and it's easy to configure. You just have to use the options &lt;i&gt;-t -oHostKeyAlgorithms=+ssh-dss -p XXXXX&lt;/i&gt; (where XXXXX is the custom port configured in the app, Android won't allow the classic one) when connecting.&lt;br /&gt;
&lt;i&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
And that's it.</description><author>Subclassed</author><pubDate>Fri, 17 Nov 2017 02:56:59 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2017/11/how-to-root-nexus-7-2012-and-flash-it.html</guid></item><item><title>My first custom element</title><link>https://qubyte.codes/blog/my-first-custom-element</link><description>&lt;p&gt;After some years of browser vendors working out what web components should look
like, they're almost ready for the prime time. The part which I find most
intriguing (custom elements) has finally stabilised. With custom elements, you
can make new HTML elements which have custom behaviour which you define using
JavaScript. In this post I'll demonstrate a custom element for fuzzy counting.&lt;/p&gt;
&lt;p&gt;Custom elements are created in two parts. Firstly we need to extend an element
with a JavaScript class.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;FuzzyCount&lt;/span&gt; &lt;span class="hljs-keyword"&gt;extends&lt;/span&gt; &lt;span class="hljs-title class_ inherited__"&gt;HTMLElement&lt;/span&gt; {

}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So far this describes no custom behaviour. All this is is the extended class,
with identical behaviour to an &lt;code&gt;HTMLElement&lt;/code&gt;. We can customize the constructor
to add the behaviour we want. In order to give the element data to use, it must
be passed in as an attribute. We'll use an attribute called &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;FuzzyCount&lt;/span&gt; &lt;span class="hljs-keyword"&gt;extends&lt;/span&gt; &lt;span class="hljs-title class_ inherited__"&gt;HTMLElement&lt;/span&gt; {
  &lt;span class="hljs-title function_"&gt;constructor&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) {
    &lt;span class="hljs-comment"&gt;// The parent constructor must be called&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// before using `this`.&lt;/span&gt;
    &lt;span class="hljs-variable language_"&gt;super&lt;/span&gt;();

    &lt;span class="hljs-comment"&gt;// rawCount is a string.&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; rawCount = &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;getAttribute&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;count&amp;#x27;&lt;/span&gt;);
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; count = &lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(rawCount, &lt;span class="hljs-number"&gt;10&lt;/span&gt;);

    &lt;span class="hljs-comment"&gt;// Set text content based on the count.&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;none&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count === &lt;span class="hljs-number"&gt;1&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;one&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count === &lt;span class="hljs-number"&gt;2&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;a couple&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count &amp;lt; &lt;span class="hljs-number"&gt;5&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;a few&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count &amp;lt; &lt;span class="hljs-number"&gt;10&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;several&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;lots&amp;#x27;&lt;/span&gt;;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The element reads and parses the &lt;code&gt;count&lt;/code&gt; attribute, giving itself a text content
accordingly.&lt;/p&gt;
&lt;p&gt;To make the element available to a page, it must be registered. One interesting
restriction placed upon custom elements is that they must contain a hyphen so
that they can be distinguished from built-in elements. We're going to register
our element as &lt;code&gt;fuzzy-count&lt;/code&gt;, but in the real world you should prefix it with
a namespace. For example, if we're working at a place called Funky Corp, we
could name the element &lt;code&gt;funkycorp-fuzzy-count&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;customElements.&lt;span class="hljs-title function_"&gt;define&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;fuzzy-count&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-title class_"&gt;FuzzyCount&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can use this to make elements on the page!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;fuzzy-count&lt;/span&gt; &lt;span class="hljs-attr"&gt;count&lt;/span&gt;=&lt;span class="hljs-string"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;fuzzy-count&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Any matching custom elements which exist before the element is defined will be
upgraded. This means a page can be sent by the server with custom elements
included, and everything will be rendered properly once the custom element is
registered.&lt;/p&gt;
&lt;p&gt;But what if we want to create elements in JS? We can try:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; fuzzyCount = &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createElement&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;fuzzy-count&amp;#x27;&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;but an error will be thrown. It turns out that newly constructed elements cannot
contain other stuff (the text content). Even if no error was thrown, we'd
have an element with no &lt;code&gt;count&lt;/code&gt; attribute, and so we've missed our chance since
all the logic is in the constructor. It turns out that the constructor is the
wrong place for this stuff.&lt;/p&gt;
&lt;p&gt;Thankfully we can make a few changes to defer the setting of text content.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;FuzzyCount&lt;/span&gt; &lt;span class="hljs-keyword"&gt;extends&lt;/span&gt; &lt;span class="hljs-title class_ inherited__"&gt;HTMLElement&lt;/span&gt; {
  &lt;span class="hljs-comment"&gt;// Called when the element is inserted into&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// the document or upgraded.&lt;/span&gt;
  &lt;span class="hljs-title function_"&gt;connectedCallback&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) {
    &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;setTextContent&lt;/span&gt;();
  }

  &lt;span class="hljs-title function_"&gt;setTextContent&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; rawCount = &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;getAttribute&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;count&amp;#x27;&lt;/span&gt;);

    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (!rawCount) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;;
      &lt;span class="hljs-keyword"&gt;return&lt;/span&gt;;
    }

    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; count = &lt;span class="hljs-built_in"&gt;parseInt&lt;/span&gt;(rawCount, &lt;span class="hljs-number"&gt;10&lt;/span&gt;);

    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;none&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count === &lt;span class="hljs-number"&gt;1&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;one&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count === &lt;span class="hljs-number"&gt;2&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;a couple&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count &amp;lt; &lt;span class="hljs-number"&gt;5&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;a few&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (count &amp;lt; &lt;span class="hljs-number"&gt;10&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;several&amp;#x27;&lt;/span&gt;;
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;textContent&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;lots&amp;#x27;&lt;/span&gt;;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The logic which sets the &lt;code&gt;textContent&lt;/code&gt; has moved to its own method
&lt;code&gt;setTextContent&lt;/code&gt;, and &lt;code&gt;connectedCallback&lt;/code&gt; calls it when the element is
&amp;quot;connected&amp;quot; to avoid the error when constructing the element in JS. Connected is
called when the element is inserted into the document, or the element is
upgraded by custom element registration.&lt;/p&gt;
&lt;p&gt;This is enough to get the behaviour we want, so long as the count attribute
of a new &lt;code&gt;fuzzy-count&lt;/code&gt; element is set &lt;em&gt;before&lt;/em&gt; it is appended to the document.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; fuzzy = &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createElement&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;fuzzy-count&amp;#x27;&lt;/span&gt;);
fuzzy.&lt;span class="hljs-title function_"&gt;setAttribute&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;count&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-number"&gt;10&lt;/span&gt;);
&lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-property"&gt;body&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;appendChild&lt;/span&gt;(fuzzy);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can take one more step to make the element react to changes to the count
attribute...&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;FuzzyCount&lt;/span&gt; &lt;span class="hljs-keyword"&gt;extends&lt;/span&gt; &lt;span class="hljs-title class_ inherited__"&gt;HTMLElement&lt;/span&gt; {
  &lt;span class="hljs-comment"&gt;// Called for each watched attribute when&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// the element is added to the document or&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// upgraded. Also fired for a watched&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// attribute when it is added, updated, or&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// removed.&lt;/span&gt;
  &lt;span class="hljs-title function_"&gt;attributeChangedCallback&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) {
    &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;setTextContent&lt;/span&gt;();
  }

  &lt;span class="hljs-comment"&gt;// A static getter because we can&amp;#x27;t add a&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// static value within a class declaration&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// directly (yet).&lt;/span&gt;
  &lt;span class="hljs-keyword"&gt;static&lt;/span&gt; &lt;span class="hljs-keyword"&gt;get&lt;/span&gt; &lt;span class="hljs-title function_"&gt;observedAttributes&lt;/span&gt;() {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; [&lt;span class="hljs-string"&gt;&amp;#x27;count&amp;#x27;&lt;/span&gt;];
  }

  &lt;span class="hljs-title function_"&gt;setTextContent&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) {
    &lt;span class="hljs-comment"&gt;// Same as before.&lt;/span&gt;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;connectedCallback&lt;/code&gt; has been replaced with &lt;code&gt;attributeChangedCallback&lt;/code&gt;, and a
static getter defines the list of attributes to watch. For each watched
attribute, when an element is inserted, upgraded, or the attribute is added,
updated, or removed, this &lt;code&gt;attributeChangedCallback&lt;/code&gt; is called. These changes
allow us to update elements before appending as before, and also &lt;em&gt;after&lt;/em&gt;
appending.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; fuzzy = &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createElement&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;fuzzy-count&amp;#x27;&lt;/span&gt;);
&lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-property"&gt;body&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;appendChild&lt;/span&gt;(fuzzy);
fuzzy.&lt;span class="hljs-title function_"&gt;setAttribute&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;count&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-number"&gt;10&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Overall I'm impressed. I've only covered some of the API available here. &lt;em&gt;It is&lt;/em&gt;
a little fiddly, but upon consideration it all seems to make sense so far. It
strikes me that a good way to use it would be for small components, or as a low
level primitive for a front end framework.&lt;/p&gt;
&lt;p&gt;Finally, a note on compatibility. At the time of writing Chrome and Safari
support custom elements with no additional effort. Other browsers must be
&lt;a href="https://github.com/webcomponents/custom-elements"&gt;polyfilled&lt;/a&gt; for support.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Thu, 16 Nov 2017 03:45:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/my-first-custom-element</guid></item><item><title>Recurse Center 7: blockchain mining in rust</title><link>https://peterlyons.com/problog/2017/11/recurse-center-7-blockchain-mining-in-rust/</link><description>&lt;p&gt;This morning I tweaked my hexagonal lambda tooling and tests. No big deal. I also started watching the "Into Rust" screencasts. The first one is great for answering the "Why Rust?" question which I got asked twice today already.&lt;/p&gt;
&lt;p&gt;After lunch I paired on the inner guts of a blockchain miner in rust. Just enough to combine a nonce with an array of block payload bytes and hunt for a sha256 "golden nonce" with a given number of leading zero bits.&lt;/p&gt;
&lt;p&gt;We initially arbitrarily picked a suboptimal crate for the sha256 algorithm that needed a mutable reference to the block+nonce data so we had to clone it every time we had to hash a different nonce. I eventually did a second shopping trip to crates.io and found shaman which just needed an immutable reference to our data, which was perfect. There's a little bit of bitwise logic and bit shifting required which is normally "scary low level" land from which I run away but with a pair to check me on things like "If I want the second bit of a u8 to be a 1, that's 64, right?" it was OK.&lt;/p&gt;
&lt;p&gt;We increased the difficulty factor up to 24 leading zero bits and were able to mine blocks quickly on my 2014 mackbook, but at 25 bits it started to take a minute or so. I haven't tried 26 but maybe I'll try tonight and leave it running with a timer.&lt;/p&gt;
&lt;p&gt;Some of the RCers played "Coding Bee" this evening which was a very amusing spectacle. It's done in 2-coder teams. You are read a small programming exercise of self-selected difficulty (easy/medium/hard). You then code a solution by each taking turns speaking a single character to a dedicated typist who types it up onto the projector, but the players are not allowed to look at the screen. There's also no backspace, just "clear line" and you have to speak all indentation and punctuation. Amazingly, some teams actually wrote correct programs.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 16 Nov 2017 02:01:27 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-7-blockchain-mining-in-rust/</guid></item><item><title>org-babel Objective-C support</title><link>https://xenodium.com/org-babel-objective-c-support</link><description>&lt;p&gt;Wanted to quickly execute an Objective-C snippet. org-babel didn't support it out of the box, but adding it was straightforward (looked at ob-C.el and ob-java.el):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(require 'ob)

(defcustom org-babel-objc-compile-command &amp;quot;clang -x objective-c -framework Foundation&amp;quot;
  &amp;quot;For example: \&amp;quot;clang -x objective-c -framework Foundation\&amp;quot;.&amp;quot;
  :group 'org-babel
  :version &amp;quot;24.3&amp;quot;
  :type 'string)

(defun org-babel-execute:objc (body params)
  &amp;quot;Compile Objective-C BODY with org PARAMS and execute binary.&amp;quot;
  (let* ((src-file (org-babel-temp-file &amp;quot;org-babel-objc-block-&amp;quot; &amp;quot;.m&amp;quot;))
         (cmpflag (or (cdr (assq :cmpflag params)) &amp;quot;&amp;quot;))
         (full-body (org-babel-expand-body:generic body params))
         (bin-file
          (org-babel-process-file-name
           (org-babel-temp-file &amp;quot;org-babel-objc-block&amp;quot; org-babel-exeext))))
    (with-temp-file src-file (insert full-body))
    (org-babel-eval
     (concat org-babel-objc-compile-command &amp;quot; &amp;quot; cmpflag &amp;quot; &amp;quot; src-file &amp;quot; &amp;quot; &amp;quot;-o&amp;quot; &amp;quot; &amp;quot; bin-file) &amp;quot;&amp;quot;)

    ;; Using 2&amp;gt;&amp;amp;1 since org babel does not include stderr in output from NSLog.
    (let ((results (org-babel-eval (concat (org-babel-process-file-name bin-file) &amp;quot; 2&amp;gt;&amp;amp;1&amp;quot;)  &amp;quot;&amp;quot;)))
      (org-babel-reassemble-table
       (org-babel-result-cond (cdr (assq :result-params params))
         (org-babel-read results)
         (let ((tmp-file (org-babel-temp-file &amp;quot;c-&amp;quot;)))
           (with-temp-file tmp-file (insert results))
           (org-babel-import-elisp-from-file tmp-file)))
       (org-babel-pick-name
        (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
       (org-babel-pick-name
        (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))

(provide 'ob-objc)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add &lt;em&gt;objc&lt;/em&gt; to &lt;em&gt;org-babel-load-languages&lt;/em&gt;, and you can subsequently compile and run Objective-C blocks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.objc"&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;

int main() {
  NSLog(@&amp;quot;Hello World&amp;quot;);
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 16 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/org-babel-objective-c-support</guid></item><item><title>Olaf's Frozen Adventure</title><link>https://blog.yiningkarlli.com/2017/11/olafs-frozen-adventure.html</link><description>&lt;div style="display: none;"&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;

&lt;div class="tableofcontents"&gt;
    &lt;div class="tableofcontents-row"&gt;
        &lt;div class="tableofcontents-column3"&gt;
            &lt;div class="tableofcontents-content"&gt;
                1. &lt;a href="/2017/11/olafs-frozen-adventure.html#2017-11-16-work"&gt;Making Olaf's Frozen Adventure&lt;/a&gt;&lt;br /&gt;
                2. &lt;a href="/2017/11/olafs-frozen-adventure.html#2017-11-16-frames"&gt;Frames from the Film&lt;/a&gt;&lt;br /&gt;
                3. &lt;a href="/2017/11/olafs-frozen-adventure.html#2017-11-16-references"&gt;References&lt;/a&gt;&lt;br /&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class="tableofcontents-column3"&gt;
        &lt;/div&gt;
        &lt;div class="tableofcontents-column3"&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="2017-11-16-work"&gt;&lt;/div&gt;

&lt;p&gt;After an amazing 2016, &lt;a href="http://www.disneyanimation.com/"&gt;Walt Disney Animation Studios&lt;/a&gt; is having a bit of a break year this year.
Disney Animation doesn’t have a feature film this year; instead, we made a half-hour featurette called &lt;a href="https://www.disneyanimation.com/projects/olafsfrozenadventure"&gt;&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;&lt;/a&gt;, which will be released in front of Pixar’s &lt;a href="https://www.pixar.com/feature-films/coco#coco-main"&gt;&lt;em&gt;Coco&lt;/em&gt;&lt;/a&gt; during Thanksgiving.
I think this is the first time a Disney Animation short/featurette has accompanied a Pixar film.
&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; is a fun little holiday story set in the world of &lt;em&gt;Frozen&lt;/em&gt;, and I had the privilege of getting to play a small role in making &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;!
I got an official credit as part of a handful of engineers that did some specific, interesting technology development for &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_01.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_01.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; is really really funny; because Olaf is the main character, the entire story takes on much more of a self-aware, at times somewhat absurdist tone.
The featurette also has a bunch of new songs- there are six new songs in total, which is somehow pretty close to the original film’s count of eight songs, but in a third of the runtime.
&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; was originally announced as a TV special, but the wider Walt Disney Company was so happy with the result that they decided to give &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; a theatrical release instead!&lt;/p&gt;

&lt;p&gt;Something I personally find fascinating about &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; is comparing it visually with the original &lt;em&gt;Frozen&lt;/em&gt;.
&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; is rendered entirely with Disney’s &lt;a href="http://www.disneyanimation.com/technology/innovations/hyperion"&gt;Hyperion Renderer&lt;/a&gt;, compared with &lt;em&gt;Frozen&lt;/em&gt;, which was rendered using pre-RIS Renderman.
While both films used our Disney BRDF &lt;a href="https://doi.org/10.1145/2343483.2343493"&gt;[Burley 2012]&lt;/a&gt; and Ptex &lt;a href="https://doi.org/10.1111/j.1467-8659.2008.01253.x"&gt;[Burley and Lacewell 2008]&lt;/a&gt;, &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; benefits from all of the improvements and advancements that have been made during &lt;em&gt;Big Hero 6&lt;/em&gt;, &lt;em&gt;Zootopia&lt;/em&gt;, and &lt;em&gt;Moana&lt;/em&gt;.
The original &lt;em&gt;Frozen&lt;/em&gt; used dipole subsurface scattering, radiosity caching, and generally had fairly low geometric complexity relative to Hyperion-era films.
In comparison, &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; uses brute force subsurface scattering, uses path-traced global illumination, uses the full Disney BSDF (which is significantly extended from the Disney BRDF) &lt;a href="https://doi.org/10.1145/2776880.2787670"&gt;[Burley 2015]&lt;/a&gt;, uses our advanced fur/hair shader developed during &lt;em&gt;Zootopia&lt;/em&gt; &lt;a href="https://doi.org/10.1111/cgf.12830"&gt;[Chiang et al. 2016]&lt;/a&gt;, and has much greater geometric complexity.
A great example of the greater geometric complexity is the knitted scarf sequence &lt;a href="https://doi.org/10.1145/3214745.3214817"&gt;[Staub et al. 2018]&lt;/a&gt;, where 2D animation was brought into Hyperion as a texture map to drive the colors on a knitted scarf that was modeled and rendered down to the fiber level.
Some shots even utilize an extended version of the photon mapped caustics we developed during &lt;em&gt;Moana&lt;/em&gt;; the photon mapped caustics system on &lt;em&gt;Moana&lt;/em&gt; only supported distant lights as a photon source, but for &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;, the photon mapping system was extended to support all of Hyperion’s existing light types as photon sources.
These extensions to our photon mapping system is one of the things I worked on for &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;, and was used for lighting the ice crystal tree that Elsa creates at the end of the film.
Even the water in Arendelle Harbor looks way better than in &lt;em&gt;Frozen&lt;/em&gt;, since the FX artists were able to make use of the incredible water systems developed for &lt;em&gt;Moana&lt;/em&gt; &lt;a href="https://doi.org/10.1145/3084363.3085067"&gt;[Palmer et al. 2017]&lt;/a&gt;.
Many of these advancements are discussed in our SIGGRAPH 2017 Course Notes &lt;a href="http://www.yiningkarlli.com/projects/ptcourse2017.html"&gt;[Burley et al. 2017]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the huge advantages to working on an in-house production rendering team in a vertically integrated studio is being able to collaborate and partner closely with productions on executing long-term technical visions.
Because of the show leadership’s confidence in our long-term development efforts targeted at later shows, the artists on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; were willing to take on and try out early versions of a number of new features in Hyperion that were originally targeted at later shows.
Some of these “preview” features wound up making a big difference on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;, and lessons learned on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; were instrumental in making these features much more robust and complete on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;One major feature was brute force path-traced subsurface scattering; Peter Kutz, Matt Chiang, and Brent Burley had originally started development during &lt;em&gt;Moana&lt;/em&gt;’s production on brute force path-traced subsurface scattering &lt;a href="https://doi.org/10.1145/2897839.2927433"&gt;[Chiang 2016]&lt;/a&gt; as a replacement for Hyperion’s existing normalized diffusion based subsurface scattering &lt;a href="https://doi.org/10.1145/2776880.2787670"&gt;[Burley 2015]&lt;/a&gt;.
This feature wasn’t completed in time for use on &lt;em&gt;Moana&lt;/em&gt; (although some initial testing was done using &lt;em&gt;Moana&lt;/em&gt; assets), but was far enough along by &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; was in production that artists started to experiment with it.
If I remember correctly, the characters in &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; are still using normalized diffusion, but path-traced subsurface wound up finding extensive use in rendering all of the snow in the show, since the additional detail that path-traced subsurface brings out helped highlight the small granular details in the snow.
A lot of lessons learned from using path-traced subsurface scattering on the snow were then applied to making path-traced subsurface scattering more robust and easier to use and control.
These experiences gave us the confidence to go ahead with full-scale deployment on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;, which uses path-traced subsurface scattering for everything including characters.&lt;/p&gt;

&lt;p&gt;Another major development effort that found experimental use on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; were some large overhauls to Hyperion’s ray traversal system.
During the production of &lt;em&gt;Moana&lt;/em&gt;, we started running into problems with how large instance groups are structured in Hyperion.
&lt;em&gt;Moana&lt;/em&gt;’s island environments featured vast quantities of instanced vegetation geometry, and because of how the instancing was authored, Hyperion’s old strategy for grouping instances in the top-level BVH wound up producing heavily overlapping BVH leaves, which in extreme cases could severely degrade traversal performance.
On &lt;em&gt;Moana&lt;/em&gt;, the solution to this problem was to change how instances were authored upstream in the pipeline, but the way that the renderer wanted instances organized was fairly different from how artists and our pipeline like to think about instances, which made authoring more difficult.
This problem motivated Peter Kutz and I to develop a new traversal system that would be less sensitive to how instance groups were authored; the system we came up with allows Hyperion to internally break up top-level BVH nodes with large overlapping bounds into smaller, tighter subbounds based on the topology of the lower-level BVHs.
It turns out this system is conceptually essentially identical to BVH rebraiding &lt;a href="https://doi.org/10.1145/3105762.3105776"&gt;[Benthin et al. 2017]&lt;/a&gt;, but we developed and deployed this system independently before Benthin 2017 was published.
As part of this effort, we also wound up revisiting Hyperion’s original cone-based packet traversal strategy &lt;a href="https://doi.org/10.1111/cgf.12158"&gt;[Eisenacher et al. 2013]&lt;/a&gt; and, motivated by extensive testing and statistical performance analysis, developed a new, simpler, higher performance multithreading strategy for handling Hyperion’s ultra-wide batched ray traversal.
&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; has a sequence where Olaf and Sven are being pulled down a mountainside through a forest by a burning sled; the enormous scale of the groundplane and large quantities of instanced trees proved to be challenging for Hyperion’s old traversal system.
We were able to partner with the artists to deploy a mid-development prototype of our new traversal system on this sequence, and were able to cut traversal times by up to close to an order of magnitude in some cases.
As a result, the artists were able to render this sequence with reasonable render times, and we were able to field-test the new traversal system prior to studio-wide deployment and iron out various kinks that were found along the way.&lt;/p&gt;

&lt;p&gt;The last major mid-development Hyperion feature that saw early experimental use on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; was our new, next-generation spectral and decomposition tracking &lt;a href="https://doi.org/10.1145/3072959.3073665"&gt;[Kutz et al. 2017]&lt;/a&gt; based null-collision volume rendering system, which was written with the intention of eventually completely replacing Hyperion’s existing residual ratio tracking &lt;a href="https://doi.org/10.1145/2661229.2661292"&gt;[Novák 2014]&lt;/a&gt; based volume rendering system &lt;a href="https://doi.org/10.1145/3084873.3084907"&gt;[Fong 2017]&lt;/a&gt;.
Artists on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; ran into some difficulties with rendering loose, fluffy white snow, where the bright white appearance is the result of high-order scattering requiring large numbers of bounces.
We realized that this problem is essentially identical to the problem of rendering white puffy clouds, which also have an appearance dominated by energy from high-order scattering.
Since null-collision volume integration is specifically very efficient at handling high-order scattering, we gave the artists an early prototype version of Hyperion’s new volume rendering system to experiment with rendering loose fluffy snow as a volume.
The initial results looked great; I’m not sure if this approach wound up being used in the final film, but this experiment gave both us and the artists a lot of confidence in the new volume rendering system and provided valuable feedback.&lt;/p&gt;

&lt;div id="2017-11-16-frames"&gt;&lt;/div&gt;

&lt;p&gt;As usual with Disney Animation projects I get to work on, here are some stills in no particular order, from the film.
Even though &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; was originally meant for TV, the whole studio still put the same level of effort into it that goes into full theatrical features, and I think it shows!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_02.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_02.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_03.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_03.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_04.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_04.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_05.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_05.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_06.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_06.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_07.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_07.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_08.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_08.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_09.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_09.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_10.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_10.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_11.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_11.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_12.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_12.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_13.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_13.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_14.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_14.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_15.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_15.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_17.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_17.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_18.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_18.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_19.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_19.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_20.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_20.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_22.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_22.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_23.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_23.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_26.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_26.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_24.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_24.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_25.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_25.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_21.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_21.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_27.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_27.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_16.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_16.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a credits frame with my name! I wasn’t actually expecting to get a credit on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;, but because I had spent a lot of time supporting the show and working with artists on deploying experimental Hyperion features to solve particularly difficult shots, the show decided to give me a credit! I was very pleasantly surprised by that; my teammate Matt Chiang got a credit as well for similar reasons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Nov/LOAF_credits.png"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Nov/preview/LOAF_credits.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All images in this post are courtesy of and the property of Walt Disney Animation Studios.&lt;/p&gt;

&lt;div id="2017-11-16-references"&gt;&lt;/div&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;

&lt;p&gt;Carsten Benthin, Sven Woop, Ingo Wald, and Attila T. Áfra. 2017. &lt;a href="https://doi.org/10.1145/3105762.3105776"&gt;Improved Two-Level BVHs using Partial Re-Braiding&lt;/a&gt;. In &lt;em&gt;Proc. of High Performance Graphics (HPG 2017)&lt;/em&gt;. Article 7.&lt;/p&gt;

&lt;p&gt;Brent Burley. 2012. &lt;a href="https://doi.org/10.1145/2343483.2343493"&gt;Physically Based Shading at Disney&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2012 Course Notes: &lt;a href="https://blog.selfshadow.com/publications/s2012-shading-course/"&gt;Practical Physically-Based Shading in Film and Game Production&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Brent Burley. 2015. &lt;a href="https://doi.org/10.1145/2776880.2787670"&gt;Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2015 Course Notes: &lt;a href="https://blog.selfshadow.com/publications/s2015-shading-course"&gt;Physically Based Shading in Theory and Practice&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Brent Burley, David Adler, Matt Jen-Yuan Chiang, Ralf Habel, Patrick Kelly, Peter Kutz, Yining Karl Li, and Daniel Teece. 2017. &lt;a href="https://www.yiningkarlli.com/projects/ptcourse2017.html"&gt;Recent Advances in Disney’s Hyperion Renderer&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2017 Course Notes: &lt;a href="http://dx.doi.org/10.1145/3084873.3084904"&gt;Path Tracing in Production Part 1&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Brent Burley and Dylan Lacewell. 2008. &lt;a href="https://doi.org/10.1111/j.1467-8659.2008.01253.x"&gt;Ptex: Per-face Texture Mapping for Production Rendering&lt;/a&gt;. &lt;em&gt;Computer Graphics Forum (Proc. of Eurographics Symposium on Rendering)&lt;/em&gt; 27, 4 (Jun. 2008), 1155-1164.&lt;/p&gt;

&lt;p&gt;Matt Jen-Yuan Chiang, Benedikt Bitterli, Chuck Tappan, and Brent Burley. 2016. &lt;a href="https://onlinelibrary.wiley.com/doi/abs/10.1111/cgf.12830"&gt;A Practical and Controllable Hair and Fur Model for Production Path Tracing&lt;/a&gt;. &lt;em&gt;Computer Graphics Forum (Proc. of Eurographics)&lt;/em&gt; 35, 2 (May 2016), 275-283.&lt;/p&gt;

&lt;p&gt;Matt Jen-Yuan Chiang, Peter Kutz, and Brent Burley. 2016. &lt;a href="https://doi.org/10.1145/2897839.2927433"&gt;Practical and Controllable Subsurface Scattering for Production Path Tracing&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2016 Talks&lt;/em&gt;. Article 49.&lt;/p&gt;

&lt;p&gt;Christian Eisenacher, Gregory Nichols, Andrew Selle, and Brent Burley. 2013. &lt;a href="https://doi.org/10.1111/cgf.12158"&gt;Sorted Deferred Shading for Production Path Tracing&lt;/a&gt;. &lt;em&gt;Computer Graphics Forum (Proc. of Eurographics Symposium on Rendering)&lt;/em&gt; 32, 4 (Jul. 2013), 125-132.&lt;/p&gt;

&lt;p&gt;Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel. 2017. &lt;a href="https://doi.org/10.1145/3084873.3084907"&gt;Production Volume Rendering&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2017 Courses&lt;/em&gt;. Article 2.&lt;/p&gt;

&lt;p&gt;Peter Kutz, Ralf Habel, Yining Karl Li, and Jan Novák. 2017. &lt;a href="https://doi.org/10.1145/3072959.3073665"&gt;Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 36, 4 (Aug. 2017), Article 111.&lt;/p&gt;

&lt;p&gt;Jan Novák, Andrew Selle and Wojciech Jarosz. 2014. &lt;a href="https://dl.acm.org/citation.cfm?id=2661292"&gt;Residual Ratio Tracking for Estimating Attenuation in Participating Media&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics (Proc. of SIGGRAPH Asia)&lt;/em&gt; 33, 6 (Nov. 2014), Article 179.&lt;/p&gt;

&lt;p&gt;Sean Palmer, Jonathan Garcia, Sara Drakeley, Patrick Kelly, and Ralf Habel. 2017. &lt;a href="https://doi.org/10.1145/3084363.3085067"&gt;The Ocean and Water Pipeline of Disney’s Moana&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2017 Talks&lt;/em&gt;. Article 29.&lt;/p&gt;

&lt;p&gt;Josh Staub, Alessandro Jacomini, Dan Lund. 2018. &lt;a href="https://doi.org/10.1145/3214745.3214817"&gt;The Handiwork Behind “Olaf’s Frozen Adventure”&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2018 Talks&lt;/em&gt;. Article 26.&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Thu, 16 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2017/11/olafs-frozen-adventure.html</guid></item><item><title>Isso Comments</title><link>https://www.hallada.net/2017/11/15/isso-comments.html</link><description>&lt;p&gt;I’ve been meaning to add a commenting system to this blog for a while, but I
couldn’t think of a good way to do it. I implemented my own commenting system on
my &lt;a href="https://github.com/thallada/personalsite"&gt;old Django personal site&lt;/a&gt;. While I
enjoyed working on it at the time, it was a lot of work, especially to fight the
spam. Now that my blog is hosted statically on Github’s servers, I have no way
to host something dynamic like comments.
&lt;!--excerpt--&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://disqus.com/"&gt;Disqus&lt;/a&gt; seems to be the popular solution to this problem
for other people that host static blogs. The way it works is that you serve a
javascript client script on the static site you own. The script will make AJAX
requests to a separate server that Disqus owns to retrieve comments and post new
ones.&lt;/p&gt;

&lt;p&gt;The price you pay for using Disqus, however, is that &lt;a href="https://replyable.com/2017/03/disqus-is-your-data-worth-trading-for-convenience/"&gt;they get to sell all of
the data that you and your commenters give
them&lt;/a&gt;.
That reason, plus the fact that I wanted something more DIY, meant this blog has
gone without comments for a few years.&lt;/p&gt;

&lt;p&gt;Then I discovered &lt;a href="https://github.com/posativ/isso"&gt;Isso&lt;/a&gt;. Isso calls itself a
lightweight alternative to &lt;a href="http://disqus.com/"&gt;Disqus&lt;/a&gt;. Isso allows you to
install the server code on your own server so that the comment data never goes
to a third party. Also, it does not require logging into some social media
account just to comment. Today, I installed it on my personal AWS EC2 instance
and added the Isso javascript client script on this blog. So far, my experience
with it has been great and it performs exactly the way I expect.&lt;/p&gt;

&lt;p&gt;I hit a few snags while installing it, however.&lt;/p&gt;

&lt;h2 id="debian-package"&gt;Debian Package&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I don’t recommend using the Debian package anymore as it frequently goes out 
of date and breaks on distribution upgrades. See bottom edit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a very handy &lt;a href="https://github.com/jgraichen/debian-isso"&gt;Debian package&lt;/a&gt;
that someone has made for Isso. Since my server runs Ubuntu 16.04, and Ubuntu is
based off of Debian, this is a package I can install with my normal ubuntu
package manager utilities. There is no PPA to install since the package is in
the &lt;a href="https://packages.ubuntu.com/xenial/isso"&gt;main Ubuntu package archive&lt;/a&gt;. Just
run &lt;code class="language-plaintext highlighter-rouge"&gt;sudo apt-get install isso&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I got a bit confused after that point, though. There seems to be no
documentation I could find about how to actually configure and start the server
once you have installed it. This is what I did:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/default/isso /etc/isso.d/available/isso.cfg
&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/isso.d/available/isso.cfg /etc/isso.d/enabled/isso.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then you can edit &lt;code class="language-plaintext highlighter-rouge"&gt;/etc/isso.d/available/isso.cfg&lt;/code&gt; with your editor of choice to
&lt;a href="https://posativ.org/isso/docs/configuration/server/"&gt;configure the Isso server for your
needs&lt;/a&gt;. Make sure to set
the &lt;code class="language-plaintext highlighter-rouge"&gt;host&lt;/code&gt; variable to the URL for your static site.&lt;/p&gt;

&lt;p&gt;Once you’re done, you can run &lt;code class="language-plaintext highlighter-rouge"&gt;sudo service isso restart&lt;/code&gt; to reload the server
with the new configuration. &lt;code class="language-plaintext highlighter-rouge"&gt;sudo service isso status&lt;/code&gt; should report &lt;code class="language-plaintext highlighter-rouge"&gt;Active
(running)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Right now, there should be a &lt;a href="http://gunicorn.org/"&gt;gunicorn&lt;/a&gt; process running
the isso server. You can check that with &lt;code class="language-plaintext highlighter-rouge"&gt;top&lt;/code&gt; or running &lt;code class="language-plaintext highlighter-rouge"&gt;ps aux | grep
gunicorn&lt;/code&gt;, which should return something about “isso”.&lt;/p&gt;

&lt;h2 id="nginx-reverse-proxy"&gt;Nginx Reverse Proxy&lt;/h2&gt;

&lt;p&gt;In order to map the URL “comments.hallada.net” to this new gunicorn server, I
need an &lt;a href="https://www.nginx.com/resources/admin-guide/reverse-proxy/"&gt;nginx reverse
proxy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To do that, I made a new server block: &lt;code class="language-plaintext highlighter-rouge"&gt;sudo vim
/etc/nginx/sites-available/isso&lt;/code&gt; which I added:&lt;/p&gt;

&lt;div class="language-nginx highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;comments.hallada.net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Script-Name&lt;/span&gt; &lt;span class="n"&gt;/isso&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8000&lt;/span&gt;&lt;span class="p"&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;Then I enabled this new server block with:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/isso /etc/nginx/sites-enabled/isso
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="dns-configuration"&gt;DNS Configuration&lt;/h2&gt;

&lt;p&gt;I added a new A record for “comments.hallada.net” that pointed to my server’s IP
address to the DNS configuration for my domain (which I recently switched to
&lt;a href="https://aws.amazon.com/route53/"&gt;Amazon Route 53&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;After the DNS caches had time to refresh, visiting &lt;code class="language-plaintext highlighter-rouge"&gt;http://comments.hallada.net&lt;/code&gt;
would hit the new &lt;code class="language-plaintext highlighter-rouge"&gt;isso&lt;/code&gt; nginx server block, which would then pass the request
on to the gunicorn process.&lt;/p&gt;

&lt;p&gt;You can verify if nginx is getting the request by looking at
&lt;code class="language-plaintext highlighter-rouge"&gt;/var/log/nginx/access.log&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="adding-the-isso-script-to-my-jekyll-site"&gt;Adding the Isso Script to my Jekyll Site&lt;/h2&gt;

&lt;p&gt;I created a file called &lt;code class="language-plaintext highlighter-rouge"&gt;_includes/comments.html&lt;/code&gt; with the contents that &lt;a href="https://posativ.org/isso/docs/quickstart/#integration"&gt;the
Isso documentation&lt;/a&gt;
provides. Then, in my post template, I simply included that on the page where I
wanted the comments to go:&lt;/p&gt;

&lt;div class="language-html highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row clearfix"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;data-isso=&lt;/span&gt;&lt;span class="s"&gt;"https://comments.hallada.net/"&lt;/span&gt;
              &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://comments.hallada.net/js/embed.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"isso-thread"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;Javascript needs to be activated to view comments.&lt;span class="nt"&gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another thing that was not immediately obvious to me is that the value of the
&lt;code class="language-plaintext highlighter-rouge"&gt;name&lt;/code&gt; variable in the Isso server configuration is the URL path that you will
need to point the Isso JavaScript client to. For example, I chose &lt;code class="language-plaintext highlighter-rouge"&gt;name = blog&lt;/code&gt;,
so the &lt;code class="language-plaintext highlighter-rouge"&gt;data-isso&lt;/code&gt; attribute on the script tag needed to be
&lt;code class="language-plaintext highlighter-rouge"&gt;http://comments.hallada.net/blog/&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="the-uncaught-referenceerror"&gt;The Uncaught ReferenceError&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You won’t need to fix this if you install Isso from PIP! See bottom edit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There’s &lt;a href="https://github.com/posativ/isso/issues/318"&gt;an issue&lt;/a&gt; with that Debian
package that causes a JavaScript error in the console when trying to load the
Isso script in the browser. I solved this by uploading the latest version of the
Isso &lt;code class="language-plaintext highlighter-rouge"&gt;embeded.min.js&lt;/code&gt; file to my server, which I put at
&lt;code class="language-plaintext highlighter-rouge"&gt;/var/www/html/isso/embeded.min.js&lt;/code&gt;. Then I modified the nginx server block to
serve that file when the path matches &lt;code class="language-plaintext highlighter-rouge"&gt;/isso&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-nginx highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;comments.hallada.net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Script-Name&lt;/span&gt; &lt;span class="n"&gt;/isso&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/isso&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s"&gt;.php?&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&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;Now requesting &lt;code class="language-plaintext highlighter-rouge"&gt;http://comments.hallada.net/isso/embeded.min.js&lt;/code&gt; would return
the newer script without the bug.&lt;/p&gt;

&lt;h2 id="sending-emails-through-amazon-simple-email-service"&gt;Sending Emails Through Amazon Simple Email Service&lt;/h2&gt;

&lt;p&gt;I already set up &lt;a href="https://aws.amazon.com/ses/"&gt;Amazon’s SES&lt;/a&gt; in my &lt;a href="http://www.hallada.net/2017/08/30/making-mailing-list-jekyll-blog-using-sendy.html"&gt;last
blog
post&lt;/a&gt;.
To get Isso to use SES to send notifications about new comments, create a new
credential in the SES UI, and then set the &lt;code class="language-plaintext highlighter-rouge"&gt;user&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;password&lt;/code&gt; fields in the
&lt;code class="language-plaintext highlighter-rouge"&gt;isso.cfg&lt;/code&gt; to what get’s generated for the IAM user. The SES page also has
information for what &lt;code class="language-plaintext highlighter-rouge"&gt;host&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;port&lt;/code&gt; to use. I used &lt;code class="language-plaintext highlighter-rouge"&gt;security = starttls&lt;/code&gt; and
&lt;code class="language-plaintext highlighter-rouge"&gt;port = 587&lt;/code&gt;. Make sure whatever email you use for &lt;code class="language-plaintext highlighter-rouge"&gt;from&lt;/code&gt; is a verified email in
SES. Also, don’t forget to add your email as the &lt;code class="language-plaintext highlighter-rouge"&gt;to&lt;/code&gt; value.&lt;/p&gt;

&lt;h2 id="enabling-https-with-lets-encrypt"&gt;Enabling HTTPS with Let’s Encrypt&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://letsencrypt.org/"&gt;Let’s Encrypt&lt;/a&gt; allows you to get SSL certificates for
free! I had already installed the certbot/letsencrypt client before, so I just
ran this to generate a new certificate for my new sub-domain
“comments.hallada.net”:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;letsencrypt certonly &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; comments.hallada.net
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once that successfully completed, I added a new nginx server block for the https
version at &lt;code class="language-plaintext highlighter-rouge"&gt;/etc/nginx/sites-available/isso-https&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-nginx highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;comments.hallada.net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/comments.hallada.net/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/comments.hallada.net/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_trusted_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/comments.hallada.net/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Script-Name&lt;/span&gt; &lt;span class="n"&gt;/isso&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/isso&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s"&gt;.php?&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&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;And, I changed the old http server block so that it just permanently redirects
to the https version:&lt;/p&gt;

&lt;div class="language-nginx highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;comments.hallada.net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://comments.hallada.net&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&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;Then I enabled the https version:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/isso-https /etc/nginx/sites-enabled/isso-https
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I checked that I didn’t get any errors visiting &lt;code class="language-plaintext highlighter-rouge"&gt;https://comments.hallada.net/&lt;/code&gt;,
and then changed my Jekyll include snippet so that it pointed at the &lt;code class="language-plaintext highlighter-rouge"&gt;https&lt;/code&gt;
site instead of &lt;code class="language-plaintext highlighter-rouge"&gt;http&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you can securely leave a comment if you want to yell at me for writing the
wrong thing!&lt;/p&gt;

&lt;h2 id="edit-5282019"&gt;EDIT 5/28/2019:&lt;/h2&gt;

&lt;p&gt;I don’t recommend using the Debian package anymore since it frequently goes out 
of date and breaks when upgrading your Linux distribution.&lt;/p&gt;

&lt;p&gt;Instead, follow the &lt;a href="https://posativ.org/isso/docs/install/"&gt;Isso docs&lt;/a&gt; by 
creating a &lt;a href="https://virtualenv.pypa.io/en/latest/"&gt;virtualenv&lt;/a&gt; and then run &lt;code class="language-plaintext highlighter-rouge"&gt;pip 
install isso&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;pip install gunicorn&lt;/code&gt; from within the virtualenv.  Then, when 
creating &lt;a href="https://github.com/jgraichen/debian-isso/blob/master/debian/isso.service"&gt;a systemd 
service&lt;/a&gt;, 
make sure to point to the gunicorn executable in that virtualenv (e.g.&lt;br /&gt;
&lt;code class="language-plaintext highlighter-rouge"&gt;/opt/isso/bin/gunicorn&lt;/code&gt;). It should load and run Isso from the same virtualenv.&lt;/p&gt;</description><author>Tyler Hallada - Blog</author><pubDate>Wed, 15 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hallada.net/2017/11/15/isso-comments.html</guid></item><item><title>Recurse Center 6: nth prime</title><link>https://peterlyons.com/problog/2017/11/recurse-center-6-nth-prime/</link><description>&lt;p&gt;This morning I wrote a script to manage AWS session tokens and asked for a code review. Not optimistic that I'll ultimately use it and I'll probably go back to aws-vault, but at least it works now and I can test drive it.&lt;/p&gt;
&lt;p&gt;I did the 3 next exercism rust exercises. There are 70+ of them and I'm worried they are too much about basic programming problems and not enough about how to write idiomatic rust, so I think starting tomorrow I'm going to just cherry pick a few that look the most interesting.&lt;/p&gt;
&lt;p&gt;Heading to Etsy to hear Suz Hinton talk about Code as Craft this evening.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 15 Nov 2017 00:33:52 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-6-nth-prime/</guid></item><item><title>C++ Smart Pointers: weak_ptr</title><link>https://studiofreya.org/cpp/c-smart-pointers-weak_ptr/</link><description>&lt;p&gt;C++ smart pointers are pointers that wrap raw C++ pointers. There are several types of smart pointers in C++.&lt;/p&gt;
&lt;p&gt;This article will be about the weak pointer (&lt;code&gt;std::weak_ptr&lt;/code&gt;) in the C++ standard that is a type of a smart pointer. It’s closely related to the shared pointer (&lt;code&gt;std::shared_ptr&lt;/code&gt;) that is also a type of C++ smart pointers.&lt;/p&gt;
&lt;p&gt;Other types are &lt;a href="https://studiofreya.com/cpp/boost/boost-scoped_ptr-vs-unique_ptr/"&gt;unique_ptr and scoped_ptr&lt;/a&gt;. There was also an &lt;code&gt;auto_ptr&lt;/code&gt;, but it was removed in C++17.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Tue, 14 Nov 2017 22:16:06 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/cpp/c-smart-pointers-weak_ptr/</guid></item><item><title>cURL to Postman</title><link>https://daniellittle.dev/curl-to-postman</link><description>Postman is a fantastic tool for testing any HTTP endpoint. But if you're using your browser to look around and you find something of…</description><author>Daniel Little Dev</author><pubDate>Tue, 14 Nov 2017 02:18:32 GMT</pubDate><guid isPermaLink="true">https://daniellittle.dev/curl-to-postman</guid></item><item><title>How to Deploy Plotly's Dash using Shinyproxy</title><link>https://lukesingham.com/how-to-deploy-plotlys-dash-using-shinyproxy/</link><description>&lt;p&gt;In a &lt;a href="https://lukesingham.com/shiny-containers-with-shinyproxy/#adding-additional-non-shiny-apps"&gt;previous post&lt;/a&gt; I established that I could easily deploy a 'Hello World' &lt;a href="http://flask.pocoo.org/"&gt;flask.py&lt;/a&gt; web application using &lt;a href="https://www.shinyproxy.io/"&gt;Shinyproxy&lt;/a&gt;. Therefore, I thought it would be straightforward to deploy a &lt;a href="https://plot.ly/dash/"&gt;Dash&lt;/a&gt; app which is built on top of &lt;a href="http://flask.pocoo.org/"&gt;flask.py&lt;/a&gt;. However, it proved to be a little more difficult than that. This blog post runs through the errors and eventual solution to deploying a Dash app on Shinyproxy.&lt;/p&gt;
&lt;h3 id="the-issue"&gt;The Issue &lt;a class="direct-link" href="https://lukesingham.com/how-to-deploy-plotlys-dash-using-shinyproxy/#the-issue"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Dash apps, like most web apps, load additional static resources, but upon deploying on Shinyproxy these aren't being delivered to the client (browser) as the URL path is wrong. This results in the all too familiar &lt;strong&gt;404 Not Found&lt;/strong&gt;. &lt;em&gt;Disclaimer&lt;/em&gt;: I haven't programmed in Java or SpringBoot (yet!). However, as far as I can see from looking at &lt;a href="https://developer.chrome.com/devtools"&gt;Chrome dev tools&lt;/a&gt; there are two ways Shinyproxy delivers static files to the client. I'm taking a look first at how it works with a &lt;a href="https://shiny.rstudio.com/"&gt;Shiny&lt;/a&gt; app.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Webjars&lt;/strong&gt; - I can see that the &lt;a href="https://github.com/openanalytics/shinyproxy/blob/master/src/main/resources/templates/app.html"&gt;main template of shinyproxy&lt;/a&gt; loads the bootstrap CSS which also gets utilised by each Shiny app.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Load from the container&lt;/strong&gt; - Additional static content for shiny apps is requested by using the container name, in this case &lt;code&gt;peaceful_jepsen&lt;/code&gt; e.g.:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;Request URL:http://&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;my-ip-address&lt;span class="token operator"&gt;&gt;&lt;/span&gt;/peaceful_jepsen/dt-core-1.10.12/css/jquery.dataTables.min.css&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let's move on to it not working with Dash...&lt;/p&gt;
&lt;h2 id="deploying-a-dash-app-on-shinyproxy"&gt;Deploying a Dash App on Shinyproxy &lt;a class="direct-link" href="https://lukesingham.com/how-to-deploy-plotlys-dash-using-shinyproxy/#deploying-a-dash-app-on-shinyproxy"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;react.min.js&lt;/code&gt; as an example, I'm going to contrast how the app fetches static content on my local machine in a container vs Shinyproxy on a remote server. I'll do this by inspecting the path for the &lt;code&gt;GET&lt;/code&gt; requests using &lt;a href="https://developer.chrome.com/devtools"&gt;Chrome dev tools&lt;/a&gt;. Firstly, what is the default behaviour of Dash.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By default, dash serves the JavaScript and CSS resources from the online CDNs.&lt;br /&gt;
Source: &lt;a href="https://plot.ly/dash/external-resources"&gt;Dash Docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dash Container on my Local Machine&lt;/strong&gt;&lt;br /&gt;
&lt;img alt="local-dash-cdn-get" src="https://lukesingham.com/content/images/2017/11/local-dash-cdn-get.png" /&gt;&lt;/p&gt;
&lt;p&gt;All resources loaded and the application displayed correctly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dash Container on Shinyproxy&lt;/strong&gt;&lt;br /&gt;
&lt;img alt="shinyproxy-dash-cdn-get" src="https://lukesingham.com/content/images/2017/11/shinyproxy-dash-cdn-get.png" /&gt;&lt;/p&gt;
&lt;p&gt;On Shinyproxy &lt;code&gt;react.min.js&lt;/code&gt; gets loaded however &lt;code&gt;_dash-layout&lt;/code&gt; and &lt;code&gt;_dash-dependencies&lt;/code&gt; fail to GET the necessary resources from the &lt;code&gt;Request URL: http://&amp;lt;my-ip-address&amp;gt;/_dash-layout&lt;/code&gt;. As we know from the Shiny app, the container name should be in there e.g. &lt;code&gt;Request URL: http://&amp;lt;my-ip-address&amp;gt;/&amp;lt;container_name&amp;gt;/_dash-layout&lt;/code&gt;. This is how Dash is supposed to behave, looking at &lt;a href="https://github.com/plotly/dash/blob/4ee769d3593d5297602c2bb6faca0eb63884d480/dash/dash.py#L74"&gt;the source code&lt;/a&gt; we can see a configurable &lt;code&gt;routes_pathname_prefix&lt;/code&gt; (I'll come back to this later in the post). So a possible solution is to get the Dash app to obtain the container name from which it is running.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://plot.ly/dash/external-resources"&gt;Dash Docs&lt;/a&gt; have the following lines of code to serve content locally.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;app&lt;span class="token punctuation"&gt;.&lt;/span&gt;css&lt;span class="token punctuation"&gt;.&lt;/span&gt;config&lt;span class="token punctuation"&gt;.&lt;/span&gt;serve_locally &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;br /&gt;app&lt;span class="token punctuation"&gt;.&lt;/span&gt;scripts&lt;span class="token punctuation"&gt;.&lt;/span&gt;config&lt;span class="token punctuation"&gt;.&lt;/span&gt;serve_locally &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's see how that changes the behaviour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dash Container on my Local Machine&lt;/strong&gt;&lt;br /&gt;
&lt;img alt="local-dash-serve-local-get" src="https://lukesingham.com/content/images/2017/11/local-dash-serve-local-get.png" /&gt;&lt;br /&gt;
Since all static content is now requested from Dash this is probably going to prevent all content from being loaded on Shinyproxy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dash Container on Shinyproxy&lt;/strong&gt;&lt;br /&gt;
&lt;img alt="shinyproxy-dash-serve-local-get" src="https://lukesingham.com/content/images/2017/11/shinyproxy-dash-serve-local-get.png" /&gt;&lt;br /&gt;
Yup! A whole lot of red 404s.&lt;/p&gt;
&lt;p&gt;Essentially it doesn't matter if you configure Dash to serve static files locally, the underlying issue is the relative URL route prefix. We know from the &lt;a href="https://github.com/plotly/dash/blob/master/dash/dash.py#L50"&gt;Dash source code&lt;/a&gt; how we could prefix the URL route. However, Shinyproxy is already doing this for Shiny apps, what's different for the requests from Dash?&lt;/p&gt;
&lt;p&gt;I started scouring the Shinyproxy Java code base. I found the construction of the &lt;code&gt;containerPath&lt;/code&gt; in &lt;a href="https://github.com/openanalytics/shinyproxy/blob/f934f108573f1ed1d24a719d9e0815012240e11f/src/main/java/eu/openanalytics/controllers/AppController.java#L74"&gt;Shinyproxy's AppController.java&lt;/a&gt;. But since I am not a Java developer I decided that this would probably not be the best allocation of my efforts. However, what the &lt;code&gt;containerPath&lt;/code&gt; does show is the construction of the path begins with &lt;code&gt;'/'&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another approach I thought of was obtaining the container name from within the Dash application and appending that to the GET URL requests initiated by Dash. Alas, Docker doesn't allow that. You can access the ContainerID but not the ContainerName. There is a &lt;a href="https://github.com/moby/moby/issues/8427"&gt;3 year old open issue regarding this&lt;/a&gt;. I then started looking for an easy way to pass into the container the containerName but I couldn't find a non-hacky way to do that either.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sidenote&lt;/strong&gt; - I was wondering what the logic was on the container name generation e.g. &lt;code&gt;adorin_raman&lt;/code&gt;. If you look at the docker source code you will find &lt;a href="https://github.com/moby/moby/blob/master/pkg/namesgenerator/names-generator.go"&gt;some go-lang code called &lt;code&gt;names-generator.go&lt;/code&gt;.&lt;/a&gt; This contains two lists, a list of adjectives and a list of &amp;quot;notable scientists and hackers&amp;quot;. The function that randomly combines these into a container name formatted as &amp;quot;adjective_surname&amp;quot; has one funny exception:&lt;/p&gt;
&lt;pre class="language-go"&gt;&lt;code class="language-go"&gt;&lt;span class="token keyword"&gt;if&lt;/span&gt; name &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token string"&gt;"boring_wozniak"&lt;/span&gt; &lt;span class="token comment"&gt;/* Steve Wozniak is not boring */&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt; &lt;span class="token keyword"&gt;goto&lt;/span&gt; begin&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two other approaches that weren't very appealing would have been managing the resources as &lt;a href="https://www.webjars.org/"&gt;webjars&lt;/a&gt; or an &lt;a href="https://nginx.org/en/"&gt;Nginx&lt;/a&gt; redirect.&lt;/p&gt;
&lt;h2 id="the-final-solution"&gt;The Final Solution &lt;a class="direct-link" href="https://lukesingham.com/how-to-deploy-plotlys-dash-using-shinyproxy/#the-final-solution"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I posted &lt;a href="https://support.openanalytics.eu/t/what-is-the-best-way-of-delivering-static-assets-to-the-client-for-custom-apps/363/5"&gt;a question to the shinyproxy forum&lt;/a&gt;, &lt;a href="http://www.fcm-consulting.be/resume.html"&gt;Frederick&lt;/a&gt; one of the main authors responded with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then that means the href being used was &lt;code&gt;/_dash-layout&lt;/code&gt; and not &lt;code&gt;_dash-layout&lt;/code&gt;.&lt;br /&gt;
Do you control the hrefs? If so, removing the slash may solve your issue. If not, it becomes trickier… you could use javascript and extract the correct URL from window.location.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If we dig into the &lt;a href="https://github.com/plotly/dash/blob/master/dash/dash.py"&gt;dash.py code&lt;/a&gt; We can see the construction of the URL paths for &lt;code&gt;_dash-layout&lt;/code&gt; &lt;code&gt;_dash-dependencies&lt;/code&gt; occurs on lines 73-80:&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;add_url&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span class="token string"&gt;'{}_dash-layout'&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;format&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;self&lt;span class="token punctuation"&gt;.&lt;/span&gt;config&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'routes_pathname_prefix'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;    self&lt;span class="token punctuation"&gt;.&lt;/span&gt;serve_layout&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;add_url&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'{}_dash-dependencies'&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;format&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;self&lt;span class="token punctuation"&gt;.&lt;/span&gt;config&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'routes_pathname_prefix'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; self&lt;span class="token punctuation"&gt;.&lt;/span&gt;dependencies&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next question is, where is &lt;code&gt;routes_pathname_prefix&lt;/code&gt; defined? On lines 46-51 &lt;code&gt;routes_pathname_prefix&lt;/code&gt; is mapped to &lt;code&gt;url_base_pathname&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;self&lt;span class="token punctuation"&gt;.&lt;/span&gt;url_base_pathname &lt;span class="token operator"&gt;=&lt;/span&gt; url_base_pathname&lt;br /&gt;self&lt;span class="token punctuation"&gt;.&lt;/span&gt;config &lt;span class="token operator"&gt;=&lt;/span&gt; _AttributeDict&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class="token string"&gt;'suppress_callback_exceptions'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;False&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="token string"&gt;'routes_pathname_prefix'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; url_base_pathname&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="token string"&gt;'requests_pathname_prefix'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; url_base_pathname&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which begs the question, where is url &lt;code&gt;url_base_pathname&lt;/code&gt; defined... on lines 20-28:&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;Dash&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;object&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="token keyword"&gt;def&lt;/span&gt; &lt;span class="token function"&gt;__init__&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;        self&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        name&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;None&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        server&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;None&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        static_folder&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;None&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        url_base_pathname&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'/'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class="token operator"&gt;**&lt;/span&gt;kwargs&lt;br /&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As Frederick said, the request should not have the &lt;code&gt;'/'&lt;/code&gt; prefix in the GET request. Unsurprisingly, having &lt;code&gt;'//'&lt;/code&gt; in your request paths is not good practice (see this &lt;a href="https://stackoverflow.com/a/20524044/3691003"&gt;SO answer&lt;/a&gt; and &lt;a href="https://stackoverflow.com/a/10161264/3691003"&gt;this one&lt;/a&gt;) as it can cause problems depending on how requests are handled. The &lt;a href="https://lukesingham.com/shiny-containers-with-shinyproxy/"&gt;software layers of Shinyproxy&lt;/a&gt; are reasonably complex with requests being handled by multiple technologies. The best solution after this trouble-shooting exercise is to use the following code in your Dash app.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# In order to work on shinyproxy (and perhaps other middleware)&lt;/span&gt;&lt;br /&gt;app&lt;span class="token punctuation"&gt;.&lt;/span&gt;config&lt;span class="token punctuation"&gt;.&lt;/span&gt;supress_callback_exceptions &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;br /&gt;app&lt;span class="token punctuation"&gt;.&lt;/span&gt;config&lt;span class="token punctuation"&gt;.&lt;/span&gt;update&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# remove the default of '/'&lt;/span&gt;&lt;br /&gt;    &lt;span class="token string"&gt;'routes_pathname_prefix'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;''&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# remove the default of '/'&lt;/span&gt;&lt;br /&gt;    &lt;span class="token string"&gt;'requests_pathname_prefix'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;''&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</description><author>Luke Singham</author><pubDate>Tue, 14 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/how-to-deploy-plotlys-dash-using-shinyproxy/</guid></item><item><title>Talk - Clustered, Distributed File and Volume Storage with GlusterFS</title><link>https://smcleod.net/2017/11/talk-clustered-distributed-file-and-volume-storage-with-glusterfs/</link><description>&lt;p&gt;Using GlusterFS to provide volume storage to Kubernetes as a replacement for our existing file and static content hosting.&lt;/p&gt;
&lt;p&gt;This talk was given at &lt;a href="https://www.meetup.com/Infrastructure-Coders/events/244535588/"&gt;Infracoders&lt;/a&gt; on Tuesday 14th November 2017.&lt;/p&gt;
&lt;p&gt;Click below to view slides (PDF version):
&lt;a href="https://media.githubusercontent.com/media/sammcj/smcleod_files/refs/heads/master/slides/lightning_san.pdf"&gt;&lt;img alt="Click to view slides" src="https://smcleod.net//img/gluster-first-slide.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://media.githubusercontent.com/media/sammcj/smcleod_files/refs/heads/master/slides/lightning_san.pdf"&gt;&lt;em&gt;Direct download link&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img src="https://github.com/sammcj/smcleod_files/blob/master/images/gluster_talk_14112017/2.jpg?raw=true" /&gt;
&lt;img src="https://github.com/sammcj/smcleod_files/blob/master/images/gluster_talk_14112017/3.jpg?raw=true" /&gt;
&lt;img src="https://github.com/sammcj/smcleod_files/blob/master/images/gluster_talk_14112017/4.jpg?raw=true" /&gt;
&lt;img src="https://github.com/sammcj/smcleod_files/blob/master/images/gluster_talk_14112017/5.jpg?raw=true" /&gt;
&lt;img src="https://github.com/sammcj/smcleod_files/blob/master/images/gluster_talk_14112017/6.jpg?raw=true" /&gt;&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Tue, 14 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/11/talk-clustered-distributed-file-and-volume-storage-with-glusterfs/</guid></item><item><title>Come To The Edge by Christopher Logue</title><link>https://ho.dges.online/words/commonplace/come-to-the-edge-by-christopher-logue/</link><description>&lt;p&gt;Come to the edge.&lt;br /&gt;
We might fall.&lt;br /&gt;
Come to the edge.&lt;br /&gt;
It’s too high!&lt;br /&gt;
COME TO THE EDGE!&lt;br /&gt;
And they came,&lt;br /&gt;
And he pushed,&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Tue, 14 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/come-to-the-edge-by-christopher-logue/</guid></item><item><title>Recurse Center 5: command line arg parsing</title><link>https://peterlyons.com/problog/2017/11/recurse-center-5-command-line-arg-parsing/</link><description>&lt;p&gt;This morning I integrated the rust clap crate into some of my little CLI exercise utilities and learned a bit about dealing with a mix of &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt; types, which is annoying. clap is really nice. I found a problem with the docs and filed a github issue and sent them a PR. It's actually ultimately an issue with the crates.io website code so I'm hoping one of those maintainers makes a fix that will handle the situation for all crates.&lt;/p&gt;
&lt;p&gt;I've been basically trying to make a customized &lt;code&gt;aws-vault&lt;/code&gt; and hitting some frustrations. Not sure if this approach makes sense but we'll see.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Tue, 14 Nov 2017 00:52:32 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-5-command-line-arg-parsing/</guid></item><item><title>Hello World!</title><link>https://purpleidea.com/blog/hello-world/</link><description>&lt;p&gt;Hello! This is a new version of my website and blog. If you experience any
issues, please let me know!&lt;/p&gt;
&lt;p&gt;Happy Hacking,
James&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;i&gt;You can &lt;a href="https://m9rx.com/" target="_blank"&gt;hire James&lt;/a&gt; and his team at &lt;a href="https://m9rx.com/" target="_blank"&gt;m9rx corporation&lt;/a&gt;.&lt;/i&gt;

&lt;br /&gt;&lt;i&gt;You can &lt;a href="https://mastodon.social/@purpleidea" target="_blank"&gt;follow James on Mastodon&lt;/a&gt; for more frequent updates and other random thoughts.&lt;/i&gt;

&lt;br /&gt;&lt;i&gt;You can &lt;a href="https://twitter.com/intent/follow?screen_name=purpleidea" target="_blank"&gt;follow James on Twitter&lt;/a&gt; for more frequent updates and other random thoughts.&lt;/i&gt;

&lt;br /&gt;&lt;i&gt;You can &lt;a href="https://github.com/sponsors/purpleidea/" target="_blank"&gt;support James on GitHub&lt;/a&gt; if you'd like to help sustain this kind of content.&lt;/i&gt;

&lt;br /&gt;&lt;i&gt;You can &lt;a href="https://www.patreon.com/purpleidea" target="_blank"&gt;support James on Patreon&lt;/a&gt; if you'd like to help sustain this kind of content.&lt;/i&gt;
&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Mon, 13 Nov 2017 16:18:15 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/hello-world/</guid></item><item><title>Practical Coprocesses</title><link>https://www.anardil.net/2017/practical-coprocesses.html</link><description>&lt;p&gt;A practical example using Bash coprocesses&lt;/p&gt;</description><author>Anardil</author><pubDate>Mon, 13 Nov 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2017/practical-coprocesses.html</guid></item><item><title>San Francisco, Downtown</title><link>https://faingezicht.com/photos/2017/11/13/sf-arch/</link><description>&gt;Light can be instantaneous. You must be ready, and you must have the damn camera with you.
&gt;
&gt; -Jay Maisel, Light Gesture And Color

I have been trying to take my camera with me more often when I go about my daily life. I usually bike to work, but when I take public transit instead, this is what happens:</description><author>Avy Faingezicht</author><pubDate>Mon, 13 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/11/13/sf-arch/</guid></item><item><title>Be interesting to somebody</title><link>https://yasha.solutions/be-interesting-to-somebody/</link><description>Not to anybody.
You cannot be interesting to anybody.
Whatever medium you are using to express yourself – it won’t work with every human being.
So instead of trying to please the world – go make sure the people your information is intended to reach – actually catch their attention.
If you don’t know – just pick one and go with it.
You will have an other opportunity tomorrow to write for the other crowd you have ignored today.</description><author>Yasha Solutions</author><pubDate>Mon, 13 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/be-interesting-to-somebody/</guid></item><item><title>Quick Thoughts: Machine Learning</title><link>https://peterlyons.com/problog/2017/11/quick-thoughts-machine-learning/</link><description>&lt;p&gt;Things machine learning plus UX teams seemingly can't get right yet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is this non-friend facebook message important or not?&lt;/li&gt;
&lt;li&gt;Do I care if this person liked some random thing on facebook?&lt;/li&gt;
&lt;li&gt;Do I need notifications or directions to an event I'm already at?&lt;/li&gt;
&lt;li&gt;Am I in a vehicle right now?&lt;/li&gt;
&lt;li&gt;What zoom level would be useful for this map?&lt;/li&gt;
&lt;/ul&gt;</description><author>Pete's Points</author><pubDate>Sun, 12 Nov 2017 16:33:55 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/quick-thoughts-machine-learning/</guid></item><item><title>Cleaning up locally installed Rubies &amp;amp; Gems</title><link>https://caiustheory.com/cleaning-up-locally-installed-rubies-gems/</link><description>&lt;p&gt;Given the following is broadly true:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rubies installed to &lt;code&gt;~/.rubies&lt;/code&gt; (via ruby-install most likely)&lt;/li&gt;
&lt;li&gt;Gems for each ruby version installed under ~/.gem (via chruby most likely)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What to do when you want to reclaim some disk space? Delete unused ruby versions of course! Pretty straight forward, look in ~/.rubies for ones you want to remove, then delete them.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ls ~/.rubies
ruby-2.0.0
ruby-2.1.7
ruby-2.3.1
ruby-2.4.1
$ rm -r ~/.rubies/ruby-{2.0.0,2.1.7}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the problem is we&amp;rsquo;re left with artifacts hanging around, namely any gems we installed for ruby 2.0.0 or 2.1.7 are still present under &lt;code&gt;~/.gem&lt;/code&gt; using up disk space. We could go through and find them by hand, or we could get the computer to delete anything under &lt;code&gt;~/.gem&lt;/code&gt; that doesn&amp;rsquo;t have a corresponding runtime under &lt;code&gt;~/.rubies&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;diff --old-line-format&lt;span class="o"&gt;=&lt;/span&gt; --unchanged-line-format&lt;span class="o"&gt;=&lt;/span&gt; --new-line-format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.gem/ruby/%L &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;ls ~/.rubies &lt;span class="p"&gt;|&lt;/span&gt; sed -Ee &lt;span class="s1"&gt;'s/ruby-|-p[0-9]+//g'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;ls ~/.gem/ruby&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs -pL1 rm -r
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(&lt;code&gt;xargs -pL1&lt;/code&gt; will prompt with each command it wants to run before running it - answer &lt;code&gt;y&lt;/code&gt; to proceed, anything else to prevent it running that command. Lets you see what ruby versions it is removing before it does so.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ls ~/.gem/ruby
2.0.0
2.1.7
2.3.1
2.4.1
$ diff --old-line-format= --unchanged-line-format= --new-line-format=$HOME/.gem/ruby/%L \
&amp;lt;(ls ~/.rubies | sed -Ee 's/ruby-|-p[0-9]+//g') &amp;lt;(ls ~/.gem/ruby) \
| xargs -pL1 rm -r
rm -r /Users/caius/.gem/ruby/2.0.0?...y
rm -r /Users/caius/.gem/ruby/2.1.7?...y
$ ls ~/.gem/ruby
2.3.1
2.4.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now revel in your reclaimed disk space. (Hunting other large folders/items on your disk? &lt;a href="http://dev.yorhel.nl/ncdu"&gt;&lt;code&gt;ncdu&lt;/code&gt;&lt;/a&gt; is a great tool for that.)&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Sun, 12 Nov 2017 13:30:24 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/cleaning-up-locally-installed-rubies-gems/</guid></item><item><title>iOS dev command-line goodies</title><link>https://xenodium.com/ios-dev-command-line-goodies</link><description>&lt;h2&gt;Install ipa on device&lt;/h2&gt;
&lt;p&gt;Get utility with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;npm install -g ipa-deploy
npm install -g ios-deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Install ipa on connected iPhone:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ipa-deploy path/to/your/App.ipa
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Install app on booted simulator&lt;/h2&gt;
&lt;p&gt;Install ipa on connected iPhone:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;xcrun simctl install booted path/to/your/App.app
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Install ipa on booted simulator&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;#!/bin/bash

# Unzip ipa, install app, and run on booted simulator.

set -o nounset
set -o errexit

readonly IPA_PATH=$1
readonly TEMP_DIR_PATH=$(mktemp -d)
readonly BASENAME=$(basename ${IPA_PATH})
readonly NAME=${BASENAME%.*}
readonly APP_DIR_PATH=&amp;quot;${TEMP_DIR_PATH}/Payload/${NAME}.app&amp;quot;
readonly PLIST_FILE_PATH=&amp;quot;${APP_DIR_PATH}/Info.plist&amp;quot;

trap &amp;quot;rm -rf ${TEMP_DIR_PATH}&amp;quot; EXIT

unzip -o &amp;quot;${IPA_PATH=}&amp;quot; -d &amp;quot;${TEMP_DIR_PATH}&amp;quot;

readonly BUNDLE_ID=$(/usr/libexec/PlistBuddy -c &amp;quot;Print CFBundleIdentifier&amp;quot; ${PLIST_FILE_PATH})

xcrun simctl install booted &amp;quot;${APP_DIR_PATH}&amp;quot;
xcrun simctl launch booted &amp;quot;${BUNDLE_ID}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 12 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/ios-dev-command-line-goodies</guid></item><item><title>Halloween 2017</title><link>https://faingezicht.com/photos/2017/11/12/halloween-2017/</link><description>This year for Halloween we went out in the Castro. It was a fun night, but to be honest the costumes were not as interesting or outrageous as I expected them to be.

I had planned to go to the Dia De Los Muertos event in the Mission a couple of days later, and post photos from both days in one set, but I messed up, and went to MoMa the day of instead, so you only get the Halloween photos. Sorry.</description><author>Avy Faingezicht</author><pubDate>Sun, 12 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/11/12/halloween-2017/</guid></item><item><title>Recurse Center 4: Reservoir Sampling</title><link>https://peterlyons.com/problog/2017/11/recurse-center-4-reservoir-sampling/</link><description>&lt;p&gt;This morning I battled the borrow checker for a while trying to properly pass a variable through a closure to a child thread. I eventually figured out calling &lt;code&gt;.to_owned()&lt;/code&gt; in the right place was needed, but it took a long time to get to that point. My normal urge is to try to understand what's happening by studying closely the compiler error message and the standard library docs, but for pragmatic reasons I need to let go of that and not wait to just google "how to X in rust" sooner rather than later.&lt;/p&gt;
&lt;p&gt;In the afternoon I paired with Casey on refining my rust basics for my little toy CLI apps and learned some good idioms there with the question operator. Then we refactored my tirefox program to use the reservoir sampling algorithm from The Art of Computer Programming so we could sample our words file in a single pass instead of needing a separate pass to count the words.&lt;/p&gt;
&lt;p&gt;I managed to get in 2 sets of physical exercise which some of the RCers do periodically and two halfway decent naps which made a huge difference (it's after 6PM and I'm still functioning). Another takeaway is that I learn a lot while pairing so I intend to request to pair very frequently and accept all offers of pairing.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 11 Nov 2017 01:08:36 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-4-reservoir-sampling/</guid></item><item><title>Recurse Center 3: Box</title><link>https://peterlyons.com/problog/2017/11/recurse-center-3-box/</link><description>&lt;p&gt;Today I wrote a little unix utility to ensure a given line is present in a file. It's not that much longer than I would expect in a scripting language (60 lines vs probably ~10 for python), but the number of machinations I had to go through was vastly larger. To get basename of &lt;code&gt;argv[0]&lt;/code&gt; I had to make a &lt;code&gt;Path&lt;/code&gt; struct which brings lots of &lt;code&gt;Option&lt;/code&gt;/&lt;code&gt;Result&lt;/code&gt; handling into things. I'm getting less terrible at reading the standard library reference documentation. I continue to be frustrated that the expandable sections for each method are all expanded by default. Maybe I'll work on a PR for that later assuming it's not baked into the tool they use to generate the docs.&lt;/p&gt;
&lt;p&gt;The timing in NYC is indeed proving to be tricky as I predicted. I work best first thing in the morning, but that's when the subways are most crowded. So RC mostly starts late around 10:30ish and goes late. I also start to fade fast into late afternoon exhaustion around 4PM. Today I just came in early. The commute wasn't that bad, but I had to let 2 trains pass because they were totally full. I think I'll end up working at home or from a coffee shop in Park Slope or from Brooklyn Boulders in the mornings for about 2 hours, then commute into RC, and either head home on the early side or find exhaustion-compatible things to fill the last 2 or so hours before commuting back home.&lt;/p&gt;
&lt;p&gt;Oh and I learned 3 new ways to make coffee so far: chemex, aeropress, and keurig (not as easy as you might assume). Only tried 2 myself but tomorrow I'll try making a mug via aeropress.&lt;/p&gt;
&lt;p&gt;I also paired with Casey at the end of the day and got a good verbal explanation of the differences between Refs and Boxes in rust.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 10 Nov 2017 06:58:32 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-3-box/</guid></item><item><title>Something Goes Here</title><link>https://caiustheory.com/something-goes-here/</link><description>&lt;!-- raw HTML omitted --&gt;
&lt;pre&gt;&lt;code&gt;Something goes here
and something else
over there slowly
wrapping lines a
little each time
oh no, you fucked
up one little comma
and now everything is running away drastically from you
End it.
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- raw HTML omitted --&gt;</description><author>Caius Theory</author><pubDate>Fri, 10 Nov 2017 02:27:07 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/something-goes-here/</guid></item><item><title>Easy Recipe For Making Chili at Home with Matt Crampton</title><link>https://www.mattcrampton.com/blog/how_to_make_easy_chili/</link><description>Easy Recipe For Making Chili at Home with Matt Crampton Cooking chili doesn't have to be a pain, use this easy recipie to make it at home. Easy Recipe For Making Chili at Home Cooking chili is easy if you make it my way. Recipe as follows... Ingredients: 1 pound of ground beef 1 onion 1 can of Ro-Tel (chopped tomatoes and green chilis) 1 can of creamed corn 1 can of tomato paste 1 packet of chili seasoning 2 cubes of frozen garlic (or just chop up a bunch of garlic) Instructions: Throw your ground beef in a pot. (I use a cast iron dutch oven.) Brown the meat over medium heat until mostly brown. Chop up the onion and add it to the pot. Pour the contents of the Ro-Tel, creamed corn and tomato paste into the pot. Drop in the garlic. Simmer at low heat. Stir every 5 to 10 minutes. Cook for as long as you like, at least 45 min. (Also remember to get your bread ahead of time).</description><author>MattCrampton.com</author><pubDate>Thu, 09 Nov 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/how_to_make_easy_chili/</guid></item><item><title>Links - November 09, 2017</title><link>https://faingezicht.com/links/2017/11/09/links/</link><description/><author>Avy Faingezicht</author><pubDate>Thu, 09 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/11/09/links/</guid></item><item><title>Go v1.9.1 vs Node v8.9.0 Microbenchmark</title><link>https://thomashunter.name/posts/2017-11-09-go-v1-9-1-vs-node-v8-9-0-microbenchmark</link><author>Thomas Hunter II</author><pubDate>Thu, 09 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-11-09-go-v1-9-1-vs-node-v8-9-0-microbenchmark</guid></item><item><title>Four Fun Phobias</title><link>https://huphtur.nl/4-fun-phobias/</link><description>&lt;ol&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Acrophobia"&gt;Acrophobia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Misophonia"&gt;Misophonia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Trypophobia"&gt;Trypophobia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Arachnophobia"&gt;Arachnophobia&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><author>huphtur</author><pubDate>Thu, 09 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://huphtur.nl/4-fun-phobias/</guid></item><item><title>Running terraform and docker on my home server</title><link>https://captnemo.in/blog/2017/11/09/home-server-update/</link><description>&lt;p&gt;The last time I’d posted about my Home Server build in September, I’d just gotten it working. Since then, I’ve made a lot of progress. It is now running almost 10 services, up from just Kodi back then. Now it has a working copy of:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;a href="https://kodi.tv/"&gt;Kodi&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;I was running &lt;code class="language-plaintext highlighter-rouge"&gt;kodi-standalone-service&lt;/code&gt;, set to run on boot, as per the &lt;a href="https://wiki.archlinux.org/index.php/Kodi#Kodi-standalone-service"&gt;ArchLinux Wiki&lt;/a&gt;, but switched in favor of openbox to a simple autorun.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="http://store.steampowered.com/linux"&gt;Steam&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;The current setup uses Steam as the application launcher. This lets me ensure that the Steam Controller works across all applications.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="http://openbox.org/wiki/Main_Page"&gt;Openbox&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Instead of running Kodi on xinit, I’m now running openbox with autologin against a non-privileged user.&lt;/dd&gt;
  &lt;dt&gt;PulseAudio&lt;/dt&gt;
  &lt;dd&gt;I tried fighting it, but it was slightly easier to configure compared to dmix. Might move to dmix if I get time.&lt;/dd&gt;
  &lt;dt&gt;btrfs&lt;/dt&gt;
  &lt;dd&gt;I now have the following disks:
    &lt;ol&gt;
      &lt;li&gt;128GB root volume. (Samsung EVO-850)&lt;/li&gt;
      &lt;li&gt;1TB volume for data backups&lt;/li&gt;
      &lt;li&gt;3TB RAID0 configuration across 2 disks.
There are some btrfs subvolumes in the 3TB raid setup, including one specifically for docker volumes. The docker guide recommends running btrfs subvolumes on the block device, which I didn’t like, so I’m running docker volumes in normal mode on a btrfs disk. I don’t have enough writes to care much yet, but might explore this further.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;This has been an interesting experiment. Kodi is still installed natively, but I’ve been trying to run almost everything else as a docker container. I’ve managed to do the configuration entirely via terraform, which has been a great learning experience. I’ve found terraform much more saner as a configuration system compared to something like ansible, which gets quite crazy. (We have a much more crazy terraform config at work, though).&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;I have a private repository on GitLab called &lt;code class="language-plaintext highlighter-rouge"&gt;nebula&lt;/code&gt; which I use as the source of truth for the configuration. It doesn’t hold everything yet, just the following:
    &lt;ol&gt;
      &lt;li&gt;Docker Configuration (not the docker service, just the container/volumes)&lt;/li&gt;
      &lt;li&gt;CloudFlare - I’m using &lt;code class="language-plaintext highlighter-rouge"&gt;bb8.fun&lt;/code&gt; as the root domain, which is entirely managed using the CloudFlare terraform provider.&lt;/li&gt;
      &lt;li&gt;MySQL - Running a MariaDB container, which has been configured by-hand till &lt;a href="https://github.com/hashicorp/go-version/pull/34"&gt;this PR gets merged&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/go-gitea/gitea"&gt;Gitea&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Running as a docker container, provisioned using terraform. Plan to proxy this using &lt;code class="language-plaintext highlighter-rouge"&gt;git.captnemo.in&lt;/code&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://emby.media/"&gt;Emby&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Docker Container. Nothing special. Plan to set this up as the Kodi backend.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://couchpota.to/"&gt;Couchpotato&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Experimental setup for now. Inside a docker container.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://flexget.com/"&gt;Flexget&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;I wish I knew how to configure this. Also inside docker.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://traefik.io/"&gt;traefik&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Running as a simple reverse proxy for most of the above services&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="http://elibsrv.sourceforge.net/"&gt;elibsrv&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;A simple OPDS server, which I use against my Kindle. If you don’t know what OPDS is, you should [check this out][]. Running on a simple apache setup on the archlinux box for now. WIP for dockerization.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://vaemendis.net/ubooquity/"&gt;ubooquity&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Simple ebook server. Proxied over the internet. Has a online ebook reader, which is pretty cool.&lt;/dd&gt;
  &lt;dt&gt;MariaDB&lt;/dt&gt;
  &lt;dd&gt;I set this up planning to shift Kodi’s data to this, but now that I have emby setup - I’m not so sure. Still, keeping this running for now.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://transmissionbt.com/"&gt;Transmission&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Hooked up to couchpotato,flexget, and sickrage so it can do things.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://sickrage.github.io/"&gt;Sickrage&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Liking this more than flexget so far, much more easier to configure and use.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://airsonic.github.io/"&gt;AirSonic&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;This is the latest fork of libresonic, which was itself forked off subsonic. My attempt at getting off Google Play Music.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id="learnings"&gt;Learnings&lt;/h2&gt;

&lt;p&gt;Moved these to a separate &lt;a href="/blog/2017/12/18/home-server-learnings/"&gt;blog post&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="todo"&gt;TODO&lt;/h2&gt;

&lt;p&gt;A few things off my TODO list:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a Docker image for elibsrv that comes with both &lt;code class="language-plaintext highlighter-rouge"&gt;ebook-convert&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;kindlegen&lt;/code&gt; pre-installed&lt;/li&gt;
  &lt;li&gt;&lt;del&gt;Do the same for ubooquity as well&lt;/del&gt; (Using the &lt;code class="language-plaintext highlighter-rouge"&gt;linuxserver/ubooquity&lt;/code&gt; docker image)&lt;/li&gt;
&lt;/ol&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;</description><author>Nemo's Home</author><pubDate>Thu, 09 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/11/09/home-server-update/</guid></item><item><title>Rapid Website Development with Mojolicious and Polymer</title><link>https://lambdaland.org/posts/2017-11-09-quick-website-programming-with-mojolicious-and-polymer/</link><description>&lt;p&gt;My girlfriend works for BYU SA—it’s the division of BYU that’s responsible for planning and running events. As part of her job, she has to review song lyrics and make sure that the song is okay to play at BYU functions.&lt;/p&gt;
&lt;p&gt;This can get rather irksome. Imagine reading text &lt;em&gt;looking&lt;/em&gt; for vulgar words or phrases. Yuck. I took some time this evening to write a little website that checks &lt;a class="link-external" href="http://metrolyrics.com" rel="external"&gt;MetroLyrics&lt;/a&gt; for any vulgar words or phrases. I have an extensible blacklist which gets initialized at server start by some phrases from &lt;a class="link-external" href="https://www.frontgatemedia.com/a-list-of-723-bad-words-to-blacklist-and-how-to-use-facebooks-moderation-tool/" rel="external"&gt;FrontGate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I coded this up with &lt;a class="link-external" href="http://mojolicious.org" rel="external"&gt;Mojolicious&lt;/a&gt; and &lt;a class="link-external" href="https://www.polymer-project.org" rel="external"&gt;Polymer Web Components&lt;/a&gt;. Polymer might have been a little overkill, but it saved me from writing lots of boring jQuery to set variable.&lt;/p&gt;
&lt;p&gt;Here’s what the site looks like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Sing Clearly" src="https://lambdaland.org/content/images/2017/11/Screen-Shot-2017-11-08-at-11.12.02-PM.png" /&gt;&lt;/p&gt;
&lt;p&gt;You can look at the code for the repository &lt;a class="link-external" href="https://github.com/ashton314/sing_clearly" rel="external"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This all took about 3 hours, the last of which was spent mostly getting some of the finer points of the user interface to work.&lt;/p&gt;
&lt;p&gt;I’d be happy to get some contributions to my project, if anyone is feeling a little bored. ;-) Some more robust song searching would be nice, as well as better heuristics for bad phrases and whatnot.&lt;/p&gt;</description><author>Lambda Land</author><pubDate>Thu, 09 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2017-11-09-quick-website-programming-with-mojolicious-and-polymer/</guid></item><item><title>Recurse Center 2: Generics</title><link>https://peterlyons.com/problog/2017/11/recurse-center-2-generics/</link><description>&lt;p&gt;Worked through 3 of the really tricky chapters of Rust By Example today. Still not a ton of lightbulbs illuminating but it will come with more coding. I feel hesitant to code more exercises until I get through the next 3 chapters on error handling etc and then I'll have a bit more knowledge whereas this morning hacking through stuff it was clear I didn't have the basics down when I had working code and just wanted to extract it unchanged into a function, which should in theory be straightforward, but I was unable to express the type signatures correctly.&lt;/p&gt;
&lt;p&gt;Also paired a little bit on passport.js and nginx with my batchmates.&lt;/p&gt;
&lt;p&gt;Already had a bit of panic about what if I need 2 weeks just to get basic fluency in rust then I have only 4 weeks to code on a project.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 09 Nov 2017 00:27:21 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-2-generics/</guid></item><item><title>C++ Hello World with Classes</title><link>https://studiofreya.org/cpp/c-hello-world-with-classes/</link><description>&lt;p&gt;In this article we will show you how to write C++ Hello World program using classes with constructors and destructors. We will create different beginner C++ programs that will output “Hello, World!” as an example.&lt;/p&gt;
&lt;h2 id="hello-world"&gt;&lt;span id="Hello-World"&gt;Hello World&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;The most trivial example is to create a simple cpp HelloWorld file inside your &lt;a href="https://studiofreya.com/cpp/how-to-create-new-cpp-project-in-visual-studio-2017/"&gt;C++ project&lt;/a&gt; and a class with the same name. Now we are going to call a method in this class that prints &lt;em&gt;“Hello World!”&lt;/em&gt;.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Wed, 08 Nov 2017 22:13:37 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/cpp/c-hello-world-with-classes/</guid></item><item><title>Showing how poor performance affects user behaviour</title><link>https://philbooth.me/blog/showing-how-poor-performance-affects-user-behaviour/</link><description>&lt;p&gt;&amp;ldquo;Bad performance hurts user engagement&amp;rdquo;
is a sentiment that feels intuitively true
but can be hard to sell in product conversations.
The best way to persuade a non-believer
is to point them at hard evidence
and for that you need
to do a few things
with your performance data.&lt;/p&gt;
&lt;p&gt;Firstly, don&amp;rsquo;t store it in a silo.
That might sound obvious
but silos occur incidentally
for all kinds of organisational reasons
that can be hard to resolve.
&lt;a href="http://www.melconway.com/Home/Conways_Law.html"&gt;Conway&amp;rsquo;s law&lt;/a&gt;
is real and causes inertia.
If you want to draw meaningful inferences from your data,
it must be possible to link it
to other events that track user behaviour.&lt;/p&gt;
&lt;p&gt;Consider the following graph
(numbers redacted):&lt;/p&gt;
&lt;p&gt;&lt;img alt="A chart that shows user engagment on Firefox Accounts is positively correlated with page load performance" src="https://assets.philbooth.me/images/fxa-perf-percentiles-1.e66d28d61ce1bab83577c3ed4a58df57516e5206.png" /&gt;&lt;/p&gt;
&lt;p&gt;Here, the x-axis is time
and the y-axis is the count of users
that successfully signed in to Firefox Accounts.
The different coloured lines
represent evenly-sized cohorts of users,
grouped according to how quickly
the initial page loaded.
If web performance
had no effect on user behaviour,
those lines would roughly overlay each other.
Instead, they show that the 10% of users
who experienced the fastest initial page load
were about twice as likely
to sign in to their account,
as the 10% of users who experienced the slowest.
If you&amp;rsquo;re having trouble convincing others
to invest engineering effort in improving performance,
having graphs like this can help.
And they&amp;rsquo;re only possible
if you can directly link performance data
to user events.&lt;/p&gt;
&lt;p&gt;Secondly,
be careful if you&amp;rsquo;re using a time-series database
like &lt;a href="https://graphiteapp.org/"&gt;Graphite&lt;/a&gt;.
These are often configured
to gradually expire data,
which is good for storage costs
but bad for precision.
The expiry is achieved by storing averages
of your metrics in progressively coarser-grained buckets
as they get older,
which reduces precision
and can produce strange jumps
at the bucket boundaries
when rendered in a chart.
People looking at those
might mistake them for genuine
performance changes.&lt;/p&gt;
&lt;p&gt;Instead of a time-series database,
consider storing your data
somewhere that can handle it &lt;em&gt;en masse&lt;/em&gt;.
We use &lt;a href="https://aws.amazon.com/documentation/redshift/"&gt;Redshift&lt;/a&gt; for this,
maintaining parallel datasets
that trade history length for sample rate.
We have an unsampled set
that contains 3 months of history,
a 50%-sampled set that goes back 6 months
and a 10%-sampled set that includes 2 years.
After the initial sampling is performed for each set,
we keep all of the data until it expires.
Data is automatically popped from the end of each set
as we push it at the start.
Limiting the size of the sets
keeps query times reasonable.
In practice,
we rarely need to consult the sampled histories
but it&amp;rsquo;s good to have them available
for occasional longer-term analysis
and maintaining them in parallel
means we can always compare like with like.
Medians and percentiles are computed on the fly inside queries,
which can be scheduled to run at regular intervals in the background
so we don&amp;rsquo;t have to wait for them every time we want to view a chart.&lt;/p&gt;
&lt;p&gt;Finally,
produce multiple visualisations
of your data.
For instance,
the chart I showed earlier
has a partner that maps the percentile boundaries
to concrete timings:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A chart that maps performance percentiles to concrete timing values" src="https://assets.philbooth.me/images/fxa-perf-percentiles-2.346a62c0ba60c5010cc20473b026b2f570612f15.png" /&gt;&lt;/p&gt;
&lt;p&gt;This is useful,
but it&amp;rsquo;s a bit annoying
to look at a separate chart
when you want to know the timing value.
So we have another chart
that tries to combine the work of both
into a single view:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A chart that shows the percent success in concrete timing bands" src="https://assets.philbooth.me/images/fxa-perf-bands-1.3168484c066ee9828da658b2a90c69068d584647.png" /&gt;&lt;/p&gt;
&lt;p&gt;Here, each band is between concrete timing values
and the y-axis is the percent of users in each band
that successfully signed in to their account.
It tells the same story as before,
with some extra spikiness
due to the interaction between
weekend behaviour and performance.
Backing up an argument from one chart
with evidence from another
makes our case more compelling.&lt;/p&gt;
&lt;p&gt;It also helps make our dashboards
useful for other purposes,
like keeping an eye on performance regressions
and tracking how we&amp;rsquo;re doing over time.
Here are the same 1-second timing bands
rendered to show how many people are in each:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A chart that shows the distribution of users within concrete timing bands" src="https://assets.philbooth.me/images/fxa-perf-bands-2.93f9adb9d6570637ae035d3de133c5f0ac901a28.png" /&gt;&lt;/p&gt;
&lt;p&gt;Ideally,
we want to see users moving
from the red bands at the top of the chart
towards the green bands at the bottom.
If the opposite occurs,
we&amp;rsquo;re doing something wrong
and we know how that affects user behaviour.&lt;/p&gt;</description><author>Phil Booth's Blog</author><pubDate>Wed, 08 Nov 2017 09:18:22 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/showing-how-poor-performance-affects-user-behaviour/</guid></item><item><title>Recurse Center 1: Shuffle Iterator</title><link>https://peterlyons.com/problog/2017/11/recurse-center-1-shuffle-iterator/</link><description>&lt;p&gt;This post is pretty stream of consciousness.&lt;/p&gt;
&lt;p&gt;Thoughts on rust language and syntax so far (about ~45 hours spent studying, trickled in over the last 6 months or so).&lt;/p&gt;
&lt;h2 id="the-hard"&gt;The Hard&lt;/h2&gt;
&lt;p&gt;rust stuff that are hard for me, unfamiliar, or I haven't studied yet&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ref/stack/heap&lt;/li&gt;
&lt;li&gt;move/borrow&lt;/li&gt;
&lt;li&gt;lifetimes&lt;/li&gt;
&lt;li&gt;traits&lt;/li&gt;
&lt;li&gt;generics&lt;/li&gt;
&lt;li&gt;ampersand ref syntax, tick lifetime syntax&lt;/li&gt;
&lt;li&gt;keeping track of intermediate type conversions when chaining methods like &lt;code&gt;.iter().map().collect()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;super/self unclear when/how these are OK to use, especially self&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-easy"&gt;The Easy&lt;/h2&gt;
&lt;p&gt;rust stuff that is easy for me or familiar&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pub, access&lt;/li&gt;
&lt;li&gt;most syntax
&lt;ul&gt;
&lt;li&gt;function&lt;/li&gt;
&lt;li&gt;let assignment&lt;/li&gt;
&lt;li&gt;match&lt;/li&gt;
&lt;li&gt;loop&lt;/li&gt;
&lt;li&gt;if&lt;/li&gt;
&lt;li&gt;most keywords&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cargo.toml&lt;/li&gt;
&lt;li&gt;most cargo subcommands are clear enough for the basics&lt;/li&gt;
&lt;li&gt;mod keyword (mostly I think)&lt;/li&gt;
&lt;li&gt;Option/Some/None, Result/OK/Err (similar to elm)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-bad"&gt;The Bad&lt;/h2&gt;
&lt;p&gt;rust stuff I dislike&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;double colon namespacing, one should suffice&lt;/li&gt;
&lt;li&gt;C-style abbreviations&lt;/li&gt;
&lt;li&gt;turbofish type hinter seems weird both syntax and position
&lt;ul&gt;
&lt;li&gt;unclear when I need an annotation before the assignment, a turbofish, or both/neither&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;println macro is so verbose&lt;/li&gt;
&lt;li&gt;something feels weird about the &lt;code&gt;use&lt;/code&gt; statement when bringing a trait into scope but not getting a name for that. Why is this necessary?&lt;/li&gt;
&lt;li&gt;I mostly don't like aliasing you can do with &lt;code&gt;use&lt;/code&gt;. I acknowledge it's necessary but linters should check it's only used when necessary. If you alias something from the std lib just because you don't like the name, you discard a bunch of easy understanding and readability by Un-Ronsealing (https://en.wikipedia.org/wiki/Does_exactly_what_it_says_on_the_tin) stuff&lt;/li&gt;
&lt;li&gt;attribute syntax is overly verbose&lt;/li&gt;
&lt;li&gt;Needing doc comments on every line. I'd so much rather just have a start and end delimiter so hard wrapping via editor tooling was easy
&lt;ul&gt;
&lt;li&gt;maybe make an atom plugin for this?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;attribute config language. Why is there a &lt;code&gt;not(fool = "bar")&lt;/code&gt; syntax instead of &lt;code&gt;foo != bar&lt;/code&gt; like actual rust&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-good"&gt;The Good&lt;/h2&gt;
&lt;p&gt;rust stuff I like&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lower_snake_case for most things&lt;/li&gt;
&lt;li&gt;both separating external API tests but keeping internal unit tests in the same file as the code feel good to me&lt;/li&gt;
&lt;li&gt;benchmarking support baked in, not that I've ever benchmarked anything, but it's cool&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="notes-and-questions-from-today"&gt;Notes and Questions from Today&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;don't skim the rust by example snippets, read them line by line or you'll miss key stuff&lt;/li&gt;
&lt;li&gt;are super and self always referring to module scopes?&lt;/li&gt;
&lt;li&gt;I'm losing/lost interest in the web because I feel like it's actively and rapidly and irrecoverably getting worse (mostly due to advertising and corporate interests) vs unix/command line which is at least a stable level of brokenness and not getting worse.&lt;/li&gt;
&lt;li&gt;Need a totally new-to-me coding process to deal with rust
&lt;ul&gt;
&lt;li&gt;First just get the type signatures right and return a hard coded basic value&lt;/li&gt;
&lt;li&gt;one line at a time try to get something working, anything&lt;/li&gt;
&lt;li&gt;separate &lt;code&gt;src/scratch.rs&lt;/code&gt; file I can periodically wipe clean to have a low-context area to attempt things in isolation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;social screw ups: I referred to people as "guys" once. I'm sorry.&lt;/li&gt;
&lt;/ul&gt;</description><author>Pete's Points</author><pubDate>Wed, 08 Nov 2017 01:38:20 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-1-shuffle-iterator/</guid></item><item><title>Recurse Center 0: Rust Anagrams</title><link>https://peterlyons.com/problog/2017/11/recurse-center-0-rust-anagrams/</link><description>&lt;p&gt;Today was my first day at Recurse Center! I was excited. Like Christmas excited. And in fact, I woke up at 5AM due to said excitement. We weren't supposed to show up earlier than 10AM so I had a while to wait around in the morning.&lt;/p&gt;
&lt;p&gt;All day was orientation type stuff about the logistics of the space, time to meet people and chat over food, panels about how best to use our time here, and some lightning talks.&lt;/p&gt;
&lt;p&gt;We did a pair programming exercise which I did in rust. We managed to get a no-op version compiling and then spent the remaining 45 minutes with various flavors of non-compiling code and battling lifetimes. After dinner I took another crack at it and had something passing all the tests after another 2 hours most of which was reading online trying to find examples that did the type conversions I needed to appease the compiler.&lt;/p&gt;
&lt;p&gt;https://github.com/focusaurus/rust-basics/blob/master/anagram/src/lib.rs&lt;/p&gt;
&lt;p&gt;I was pleased that RC encourages naps and plan to nap at least once a day. There are also 2 people from the F2 batch doing some rust and a bunch of folks knowledgeable about rust on the RC chat server which I think will be great because getting in-person help can save tons of time with hard-to-google rust type conversion errors such as I had tonight which amounts to "I have &lt;code&gt;Vec&amp;lt;&amp;amp;&amp;amp;str&amp;gt;&lt;/code&gt; but I need &lt;code&gt;Vec&amp;lt;&amp;amp;str&amp;gt;&lt;/code&gt;" which as you might predict is tough as a web search term.&lt;/p&gt;
&lt;p&gt;I found these two good blog posts in my search:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also learned what a Functor is in one of the lightning talks and no it's not as hard as it sounds but oh man it is nothing like I what I thought it might be. In fact, after the talk I asked a question that amounts to "Wait so which of your examples is actually the functor itself: A or B" and the answer was "neither, it's C" and that was very surprising.&lt;/p&gt;
&lt;p&gt;Today was I believe the one and only structured day at RC. Starting tomorrow it's entirely self-directed.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Tue, 07 Nov 2017 05:05:19 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/11/recurse-center-0-rust-anagrams/</guid></item><item><title>2017-11-07</title><link>https://ho.dges.online/pictures/2017-11-07/</link><description/><author>ho.dges.online</author><pubDate>Tue, 07 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-11-07/</guid></item><item><title>Sense8: Season 2</title><link>https://olshansky.info/tv/sense8_season_2/</link><description>Olshansky's review of Sense8: Season 2</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 05 Nov 2017 02:18:10 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/sense8_season_2/</guid></item><item><title>Data Storage on Unix</title><link>https://venam.net/blog/unix/2017/11/05/unix-filesystem.html</link><description>Libraries and banks, amongst other institutions, used to have a filing system, some still have them. They had drawers, holders, and many tools to store the paperwork and organise it so that they could easily retrieve, through some documented process, at a later stage whatever they needed.  That's where the name filesystem in the computer world emerges from and this is one of the subject of this episode.  We're going to discuss data storage on Unix with some discussion about filesystem and an emphasis on storage device.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 05 Nov 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/11/05/unix-filesystem.html</guid></item><item><title>Four Simple Steps To Post To Twitter Using Python</title><link>https://www.mattcrampton.com/blog/step_by_step_tutorial_to_post_to_twitter_using_python/</link><description>Four Simple Steps To Post To Twitter Using Python NOTE: Don't miss the part 2 of this blog post: Posting Photos to Twitter with Python Automating Twitter can be an easy coding exercise once you have everything set up, but figuring out all the steps that Twitter puts you through to generate your access keys and tokens can be a challenge. I put these four steps together to make it easier to walk to the process, hopefully it's useful for someone else out there. Create An Application On app.twitter.com Install Python Dependencies Write The Python Code Post Your First Tweet TLDR; If you just want the code, you can grab the code repo for this tutorial here: https://github.com/mattccrampton/post_to_twitter_using_python Step #1 - Create An Application on app.twitter.com First head over to https://apps.twitter.com/, sign in to your twitter account and then click on the "Create New App" button. Enter your application's information. For the purposes of this demo I'm creating an application to ...</description><author>MattCrampton.com</author><pubDate>Fri, 03 Nov 2017 07:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/step_by_step_tutorial_to_post_to_twitter_using_python/</guid></item><item><title>Digital Security Coach</title><link>https://www.dannyguo.com/blog/digital-security-coach</link><author>Danny Guo</author><pubDate>Fri, 03 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/digital-security-coach</guid></item><item><title>My journey to find the best Bible</title><link>https://honza.pokorny.ca/2017/11/my-journey-to-find-the-best-bible/</link><description>&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/pitt-minion/20171025_0003_thumb.jpg" /&gt;
&lt;/figure&gt;

&lt;p&gt;&amp;hellip; or, &lt;em&gt;ESV Pitt Minion in black goatskin review&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I have been reading Mark Bertrand&amp;rsquo;s &lt;a href="https://www.bibledesignblog.com/"&gt;Bible Design Blog&lt;/a&gt; for a few years now.
Through his long-form writing, I have come to appreciate beautiful typography,
fine craftsmanship, single-column layouts, and attention to detail in modern
Bible-making.  I even helped him with a website update several years ago.&lt;/p&gt;
&lt;p&gt;For the longest time, though, my reading was just that&amp;mdash;reading.  I couldn&amp;rsquo;t
imagine spending so much money on a single Bible.  I already had a few Bibles
in the house, and there wasn&amp;rsquo;t any pressing need to buy another one.  This
spring, after saving up some money, I decided to invest in a premium Bible.  I
made a list of requirements, and I read and watched just about every review I
could find on the world wide web.  I was searching for &lt;em&gt;the one&lt;/em&gt; Bible, the
elusive unicorn of typographic design.  I read articles about how that Bible
doesn&amp;rsquo;t exist, and that I should just come to terms with the fact that I shall
have to acquire a few different Bibles, each one for its own intended purpose.&lt;/p&gt;
&lt;p&gt;I became addicted to the idea of single-column design.  I read all about it.  I
could absolutely sign Mark Ward&amp;rsquo;s &lt;a href="https://byfaithweunderstand.com/bible-typography-manifesto/"&gt;Bible Typography Manifesto&lt;/a&gt;.  Two years
before the search began, my wife bought me the single-volume
&lt;a href="https://www.crossway.org/bibles/esv-readers-bible-cob/"&gt;ESV Reader&amp;rsquo;s Bible&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This Bible is relatively cheap, and gorgeous.  It looks a lot more like a
regular book than a dictionary or a reference book.  It features a large font,
single-column layout, &amp;hellip; but its significance is in what it lacks: verse
numbers, references, section headings, book introductions, etc.  It&amp;rsquo;s very clean
and a joy to read.  I highly recommend it to anyone, and often show it off to
visitors to our house.  My friends are usually dismissive of the idea of a
single column Bible because it doesn&amp;rsquo;t look like a &lt;em&gt;real&lt;/em&gt; Bible.  The inertia of
Bible design is so tremendous that people experience a mild culture shock when
looking at modern Bibles.&lt;/p&gt;
&lt;p&gt;Unfortunately, the Reader doesn&amp;rsquo;t work as &lt;em&gt;the one&lt;/em&gt; Bible.&lt;/p&gt;
&lt;p&gt;From the start, I knew I didn&amp;rsquo;t want to become a Bible collector.  I have no
desire to own thousands of dollars worth of Bibles.  I wanted to acquire a
single Bible that I could use in many different scenarios.  The primary
motivation for this is that over time, you get to know your Bible, and you will
learn where things are, and you can find them quickly.  Professor Grant Horner
is an advocate of this argument in his &lt;a href="http://www.sohmer.net/media/professor_grant_horners_bible_reading_system.pdf"&gt;10 chapters per day reading plan&lt;/a&gt; which
I enjoy.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s see if we can put together a list of priorities.  The Bible must work
during private reading, study, public worship, family worship, and adult Bible
study with others.  It must be easy to read, and yet be small enough that it&amp;rsquo;s
practical to carry everywhere.  It must be available in the English Standard
Version.  It must be pleasing to the eye and to the touch.  It should be
rendered in single-column layout.  Since I want it to be as practical as
possible, it should come with verse numbers, and section headings.  References
are unimportant.&lt;/p&gt;
&lt;p&gt;I was immediately captivated by Crossway&amp;rsquo;s &lt;a href="https://www.crossway.org/bibles/esv-heirloom-single-column-legacy-bible-none-gskn/"&gt;ESV Heirloom Single Column
Legacy&lt;/a&gt;, and Cambridge&amp;rsquo;s &lt;a href="http://www.cambridge.org/bibles/bible-versions/english-standard-version/clarion/#fWEczIpRK89Frx95.97"&gt;Clarion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is the Heirloom:&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/esv-heirloom-psalms.jpg" /&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/esv-heirloom-cover.jpg" /&gt;
&lt;/figure&gt;

&lt;p&gt;(&lt;em&gt;Photos via evangelicalbible.com&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;Judging by the photos in &lt;a href="https://www.bibledesignblog.com/blog/2017/8/10/refined-in-every-sense-the-new-heirloom-legacy"&gt;Mark Bertrand&amp;rsquo;s review of the new ESV Heirloom
Legacy&lt;/a&gt;, the Bible looks huge.  This means two things for me: it features a
large, readable page, and it&amp;rsquo;s likely too big to carry everywhere.  This would
make a great sit-at-home-and-read-for-hours Bible, but I wouldn&amp;rsquo;t drag it to
church with me.  Still, the page looks amazing, single column; I love the
headings on the side instead of in the text.  I like that it has verse numbers
and no references.  It makes the text look clean.  This Bible will set you back
275 USD.&lt;/p&gt;
&lt;p&gt;And here is the Clarion:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/clarion-open.jpg" /&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/clarion-cover.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Photos via evangelicalbible.com&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;The Clarion is short and stout.  I like the shape of it better than the Heirloom
Legacy.  Given its supple cover, it can be difficult to hold.  It features
references and a single-column text block.  For some strange reason, the
references are on the outside.  This causes the text of the Bible to dip into
the fold near the spine.  Crossway&amp;rsquo;s Personal Reference Bible is also rendered
in a single column setting but its references are in the middle.  This is a much
better solution in my opinion. Unfortunately, the Clarion seems to have problems
with ghosting (also known as show-through), page curling, and while it&amp;rsquo;s smaller
than the Heirloom, it&amp;rsquo;s still rather bulky.  It&amp;rsquo;s about the same size as my ESV
Reader&amp;rsquo;s Bible which definitely isn&amp;rsquo;t very portable.  The Clarion costs about
255 USD.&lt;/p&gt;
&lt;p&gt;These two Bibles are absolutely excellent, and very expensive.  If I were a
collector, I think both of these should be in my collection.  However, that&amp;rsquo;s
not why we&amp;rsquo;re here.&lt;/p&gt;
&lt;p&gt;After dismissing the Heirloom and the Clarion, I was browsing publishers'
websites, and came across another Bible from Cambridge: the &lt;a href="http://www.cambridge.org/bibles/bible-versions/king-james-version/reference-editions/pitt-minion-first-edition/#EGkUW5ImTubwglOP.97"&gt;Pitt Minion&lt;/a&gt;. The
size of this Bible is absolutely spot on: not too big (portable), and not too
small (readable), not too short and not fat.  I absolutely love the black
goatskin edition with the red accent of a ribbon.  Only problem?  It&amp;rsquo;s double
column.&lt;/p&gt;
&lt;p&gt;Initially, I dismissed it&amp;mdash;almost immediately.  Who would buy a double column
Bible in 2017?  But I kept thinking about the Pitt Minion, and kept coming back
to it.  I read all of Mark Bertrand&amp;rsquo;s reviews of it over and over.  I think
there are at least four articles on his website dedicated to the Pitt Minion.
Mark&amp;rsquo;s argument for the Pitt Minion is that its columns are magic.  There is
something about the ratio between the column&amp;rsquo;s width, the font size, and the
leading that makes it just work.  This leads to high readability in spite of
the tiny 6.75 font.  Also, the size of the Bible is somewhere in between a
pocket Bible and a medium sized Bible.  This makes it unique in the kind of
situations you&amp;rsquo;d want to use it in.&lt;/p&gt;
&lt;p&gt;I also greatly benefited from &lt;a href="https://www.youtube.com/channel/UCzZeN-hOXtiz9Q0YvVUee8A"&gt;Matthew Everhard&amp;rsquo;s&lt;/a&gt; videos.  Matthew is a pastor
who uses a Pitt Minion has his take-it-with-you-everywhere Bible, and does a
video review once a year to show how the Bible is doing with daily use.  I love
how the leather ages, and how the board covers soften as you use it.&lt;/p&gt;

&lt;p&gt;Once I was willing to seriously consider the double-column layout, I went back
to the drawing board, as it were, and had another look at the available
options.  I have yet to see a Bible from R. L. Allan that I like (sorry folks).
But Schuyler is a different story!  Their Quentel is very intriguing,
especially the Personal size version.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/quentel-1-small.jpg" /&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/quentel-2-small.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Photos via evangelicalbible.com&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;The only problem is the price.  I live in Canada, and shipping is around 50
USD, and I&amp;rsquo;m probably going to get hit with import tax fees, etc.  The Bible
itself is about 175 USD.  Evangelical Bible really needs to figure a better
distribution model for their awesome Bibles.  A lot more people would buy them
if the shipping were cheaper (e.g. partner with Amazon).&lt;/p&gt;
&lt;p&gt;After much thought, I decided to order the Pitt Minion.  Another huge reason
was its price. It costs about 150 USD and I even found a great deal on Amazon,
so I ended up paying about 100 USD (shipped).  Compare that to the 225+ USD for
the Quentel.  The Pitt Minion is a steal!  I opted for the black goatskin which
to my eyes and heart looks the best.  Just as a side note, you can get the
Clarion for about that price but with a much inferior leather cover.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0001_thumb.jpg" /&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0002_thumb.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Just look at that delicious grain!&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/pitt-minion/20171025_0003_thumb.jpg" /&gt;
&lt;/figure&gt;

&lt;p&gt;The book opens flat after a few days of handling it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0004_thumb.jpg" /&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0005_thumb.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Notice the red under gold art gilding on the sides of the pages.  Just
gorgeous.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0006_thumb.jpg" /&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0007_thumb.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;I love the red accent that the ribbons provide.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0008_thumb.jpg" /&gt;&lt;img alt="" src="https://honza.pokorny.ca/images/pitt-minion/20171025_0009_thumb.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Photos by me, you can use them for any purpose&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;While I was waiting for it to arrive in the mail, I was rather nervous about
the whole thing.  But as soon as I opened the box, I was relieved and happy
with the new Bible.  It far exceeded by expectations.  It&amp;rsquo;s even more beautiful
than in the pictures.&lt;/p&gt;
&lt;p&gt;Right out of the box, the Pitt Minion doesn&amp;rsquo;t open flat.  You have to handle it
and read it for about a week, and then it will happily oblige.  The quality of
the print is exceptional.  Many reviewers have said that the font is small.
That might be true in the technical sense, but given the high quality of the
printing, the font doesn&amp;rsquo;t feel small.  Think of it like this: your normal
Bible is like an old TV, it has very low resolution and unnatural colors.  The
Pitt Minion is your latest 4K smart TV with life-like colors.  Premium Bibles
stand out not just wit their binding and covers, but also with the quality of
the printing.  I find the font size of the Pitt Minion luxurious.&lt;/p&gt;
&lt;p&gt;Then there is the question of the double column.  I remain convinced on a
theoretical level that the single column layout is superior in readability.
However, it does in a sense waste space in poetry sections.  This leads to more
bulk in the final form factor of the Bible.  In practice, I don&amp;rsquo;t feel any
hindrance in reading the Pitt Minion.  My eye can track the words easily, and I
don&amp;rsquo;t find I lose my place often when reading for extended periods of time.
Moreover, there is something to be said about the Bible looking like a Bible,
and double column is certainly the more traditional look.  I realize this is a
pretty weak argument.  With Cambridge, you are purchasing a piece of history or
Bible publishing history.  Cambridge University Press is the world&amp;rsquo;s oldest
Bible printer and publisher.  They have been in continuous operation since 1591
when they published the Geneva Bible.&lt;/p&gt;
&lt;p&gt;Once you handle a premium Bible, you won&amp;rsquo;t settle for inferior quality.  I have
been reading from the Pitt Minion for several months now.  I have carried it
many places.  I travelled to Europe with it. I certainly don&amp;rsquo;t baby this Bible.
I fold back one side of the cover when reading, I roll it up when it&amp;rsquo;s closed,
and I take it with me when going out.  I find it delightful, and it&amp;rsquo;s truly a
great all-around Bible.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Thu, 02 Nov 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/11/my-journey-to-find-the-best-bible/</guid></item><item><title>Java Hello World – How to Run</title><link>https://studiofreya.org/java/java-hello-world-how-to-run/</link><description>&lt;p&gt;In this article we will show you how to start programming in Java from scratch. We will use Java 9 for this beginner tutorial and write and run a “Hello, World!” example program on your computer.&lt;/p&gt;
&lt;h2 id="installing-java"&gt;&lt;span id="Installing-Java"&gt;Installing Java&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;In order to start programming in Java you will need to install Java on your computer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1. Install JDK&lt;/strong&gt;&lt;br /&gt;
Go to the &lt;a href="http://www.oracle.com/technetwork/java/javase/overview/index.html" rel="noopener nofollow" target="_blank"&gt;Oracle website&lt;/a&gt; and download and install the latest JDK pack. We used &lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848520.html" rel="noopener nofollow" target="_blank"&gt;Java 9 JDK&lt;/a&gt;. JDK stands for Java Development Kit and is a library that you need to compile and run Java applications.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Thu, 02 Nov 2017 12:55:37 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/java/java-hello-world-how-to-run/</guid></item><item><title>How I Structure GameObjects - Components and Mixin-based Inheritance</title><link>https://blog.varunramesh.net/posts/unifying-component-based-gameobject-systems-and-mixin-based-inheritance/</link><description>My recent game projects have used a GameObject architecture that unifies Component-based GameObjects and Mixin-based inheritance.</description><author>Varun Ramesh's Blog</author><pubDate>Thu, 02 Nov 2017 11:04:17 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/unifying-component-based-gameobject-systems-and-mixin-based-inheritance/</guid></item><item><title>Newsletter email confirmation – NextCloud UX copy</title><link>https://yasha.solutions/newsletter-email-confirmation-nextcloud-justanexample/</link><description>Nextcloud is an awesome solution to create and manage your own cloud you should really check them out if you have never heard of them.
Here we have a quick look at the newsletter confirmation – an always challenging issue for open rate and engagement with your users. I found this one pretty good – so I have added it here.
Why is it good?
 It gets personal  It gets personnal real quick – which force you to care about that guy who is writing to you.</description><author>Yasha Solutions</author><pubDate>Thu, 02 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/newsletter-email-confirmation-nextcloud-justanexample/</guid></item><item><title>The Mega List Of Free Image Sites For Blogging</title><link>https://www.mattcrampton.com/blog/mega_list_of_free_image_sites_for_blogging/</link><description>The Mega List Of Free Image Sites For Blogging Blogging is hard work, and finding good images to make your content compelling can be even harder. Luckily a number of talented photographers and engineers have taken it upon themselves to make a huge number of free images available for commercial use. Take a look at the list below for a huge set of sites you can use for your next project. This list is a work in progress. If you have a site you think should be on the list, or if any of these links are broken, please tweet it at me. Artvee Discover Classical Art, Browse and download high-resolution, public domain artworks. https://artvee.com/ Albumarium Author Vilem Ries, developed by Filip Skokan &amp; Lukas Prvy http://albumarium.com/ Bucketlistly A free creative common collection of over 5000+ travel photos from all over the world anyone can use. http://photos.bucketlistly.com/ Burst Free stock photos for everyone https://burst.shopify.com/ Cupcake Free (do what ever you want) photos. htt...</description><author>MattCrampton.com</author><pubDate>Wed, 01 Nov 2017 07:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/mega_list_of_free_image_sites_for_blogging/</guid></item><item><title>Eshell pcomplete company completion</title><link>https://xenodium.com/eshell-pcomplete-company-completion</link><description>&lt;p&gt;Howard Abrams's &lt;a href="https://www.youtube.com/watch?v=RhYNu6i_uY4"&gt;Introduction to eshell video&lt;/a&gt; prompted me to poke at eshell some more. This time, I got eshell context aware completion by glueing the excellent &lt;a href="https://company-mode.github.io"&gt;company&lt;/a&gt; and &lt;a href="https://masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs"&gt;pcomplete&lt;/a&gt; packages.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/eshell-pcomplete-company-completion/company-pcomplete.png" /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(require 'cl-lib)
(require 'company)
(require 'dash)
(require 'pcomplete)
(require 's)

(defun company-pcomplete--overlap-tail (a b)
  &amp;quot;When A is \&amp;quot;SomeDev\&amp;quot; and B is \&amp;quot;Developer\&amp;quot;, return \&amp;quot;eloper\&amp;quot;.&amp;quot;
  (let ((prefix a)
        (remaining nil))
    (while (and (not remaining) (&amp;gt; (length prefix) 0))
      (when (s-starts-with? prefix b)
        (setq remaining (substring b (length prefix))))
      (setq prefix (substring prefix 1)))
    remaining))

(defun company-pcomplete--candidates (prefix)
  &amp;quot;Get candidates for PREFIX company completion using `pcomplete'.&amp;quot;
  ;; When prefix is: &amp;quot;~/Down&amp;quot; and completion is &amp;quot;Downloads&amp;quot;, need
  ;; to find common string and join into &amp;quot;~/Downloads/&amp;quot;.
  (-map (lambda (item)
          (if (s-starts-with? prefix item)
              item
            (concat prefix (company-pcomplete--overlap-tail prefix item))))
        (all-completions prefix (pcomplete-completions))))

(defun company-pcomplete (command &amp;amp;optional arg &amp;amp;rest ignored)
  &amp;quot;Complete using pcomplete. See `company''s COMMAND ARG and IGNORED for details.&amp;quot;
  (interactive (list 'interactive))
  (case command
    (interactive (company-begin-backend 'company-pcomplete))
    (prefix (company-grab-symbol))
    (candidates
     (company-pcomplete--candidates arg))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don't forget to add &lt;em&gt;company-pcomplete&lt;/em&gt; to &lt;em&gt;company-backends,&lt;/em&gt; and if you want an explicit binding, use something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(bind-key &amp;quot;&amp;lt;backtab&amp;gt;&amp;quot; #'company-complete eshell-mode-map)
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 01 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/eshell-pcomplete-company-completion</guid></item><item><title>Challenger Bank</title><link>https://www.craigpardey.com/post/2017-11-01-challenger-bank/</link><description>&lt;p&gt;When I first heard about the so-called UK Challenger Banks like &lt;a href="https://monzo.com/"&gt;Monzo&lt;/a&gt; and &lt;a href="https://www.atombank.co.uk/"&gt;Atom&lt;/a&gt;, I was amazed that there wasn&amp;rsquo;t a similar offering in Canada.  The Canadian retail banking sector desperately needs new players bring compelling products to the market but nobody was doing it. There are some options like &lt;a href="https://www.pcfinancial.ca/"&gt;PC Financial&lt;/a&gt; and &lt;a href="http://tangerine.ca"&gt;Tangerine&lt;/a&gt; but they&amp;rsquo;re both backed by one of the Big Banks (CIBC and Scotiabank, respectively).  Nobody was attempting a ground-up rebuild of a bank using modern technology and practices.&lt;/p&gt;</description><author>Craig Pardey</author><pubDate>Wed, 01 Nov 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.craigpardey.com/post/2017-11-01-challenger-bank/</guid></item><item><title>Postgres - the non-code bits</title><link>/2017/10/31/Postgres-the-non-code-bits/</link><description>&lt;p&gt;Postgres is an interesting open source project. It&amp;rsquo;s truly one of a kind, it has its own license to prove it as opposed to falling under something like Apache or GPL. The Postgres community structure is something that is pretty well defined if you&amp;rsquo;re involved in the community, but to those outside it&amp;rsquo;s likely a little less clear. In case you&amp;rsquo;re curious to learn more about the community here&amp;rsquo;s a rundown of a few various aspects of it:&lt;/p&gt;
&lt;h3 id="postgresql-license"&gt;
&lt;div&gt;
PostgreSQL License
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s start with the legal part first. &lt;em&gt;First IANAL&lt;/em&gt;. PostgreSQL is under its own license. For those who don&amp;rsquo;t regularly follow software licensing it&amp;rsquo;s extremely liberal and flexible. You can take Postgres, fork it, change it, package it up, and resell it. This is actually one of the reasons you see Postgres at the core of so many other databases like Par Accel, Asterdata, etc. That and that it&amp;rsquo;s such a solid code base that is capable of being extended. &lt;em&gt;I once heard someone describe how they don&amp;rsquo;t really like writing C, but they enjoy writing Postgres C ;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A thing you can&amp;rsquo;t do is profit off the PostgreSQL logo without any approval from the core team.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="the-people"&gt;
&lt;div&gt;
The people
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Within the Postgres community there are 2 major sets of people.&lt;/p&gt;
&lt;h3 id="the-core-team"&gt;
&lt;div&gt;
The core team
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The core team is a smaller team within the Postgres community. The core team is effectively a &lt;a href="https://www.postgresql.org/developer/core/"&gt;steering committee&lt;/a&gt; for Postgres. They&amp;rsquo;re responsible for coordinating releases, handling confidential issues (read: security issues), managing permissions around PostgreSQL code and infrastructure, defining policy.&lt;/p&gt;
&lt;p&gt;The core team is a very small list of people, at the moment 5 individuals.&lt;/p&gt;
&lt;h3 id="contributors"&gt;
&lt;div&gt;
Contributors
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Yes, anyone can contribute to Postgres, and with each release there are a laundry of people that write some code that goes into Postgres. If fact Postgres 10 had &lt;a href="https://www.postgresql.org/docs/current/static/release-10.html#idm46046833759776"&gt;325 people&lt;/a&gt; that contributed in some form. That said there is a hierarchy that exists. The two biggest ones are committers and major contributors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Committers&lt;/strong&gt; gain access after years of contributing to Postgres showing sustained commitment to the project. New committers are voted on each year at PgCon which happens in March/April in Ottawa. If you&amp;rsquo;re ever curious for a conference of what&amp;rsquo;s coming and being deep in the internals of Postgres it&amp;rsquo;s one to check out. Once you do gain your commit bit you&amp;rsquo;re expected to contribute every couple of years to the project. And of course there are a &lt;a href="https://wiki.postgresql.org/wiki/Committers"&gt;number of qualifications&lt;/a&gt; such as contributing high quality code and perhaps most key is helping review others contributions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Major contributors&lt;/strong&gt; are another notable group. Major contributors don&amp;rsquo;t have full sole commit access, but are held in a higher regard from consistently contributing major features as well as providing review for others.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contributors&lt;/strong&gt; in general are another area worth calling out. While they may not have a flagship feature to their name like the major contributors, Postgres is what it is because of the contributions of everyone.&lt;/p&gt;
&lt;h3 id="postgresql-the-company"&gt;
&lt;div&gt;
PostgreSQL the company
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Well, it turns out there isn&amp;rsquo;t a company behind Postgres, it&amp;rsquo;s one thing that makes it unique–no one can ever &amp;ldquo;own it&amp;rdquo;. There are some official PostgreSQL non-profits though in particular the US non-profit and the EU non-profit. These non-profits ensure that the core guidelines are enforced and also give coverage for the community to help put on official community conferences. A few of these happen each year which include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pgcon.org/2018/"&gt;PGCon&lt;/a&gt; - The hackers conference&lt;/li&gt;
&lt;li&gt;&lt;a href="https://2017.postgresopen.org/"&gt;PostgresOpen SV&lt;/a&gt; - A consolidation of PostgresOpen and PGConf Silicon Valley&lt;/li&gt;
&lt;li&gt;&lt;a href="https://postgresopen.org/"&gt;PGConf EU&lt;/a&gt; - The largest PG European Conference which moves around each year&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;re looking for a way to support the PostgreSQL non-profit organization I&amp;rsquo;d encourage you to consider joining &lt;a href="https://postgresql.us/"&gt;PostgreSQL.us&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="engaging"&gt;
&lt;div&gt;
Engaging
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;So you want to jump into the community, where do you even start? The first place I&amp;rsquo;d encourage is to subscribe to the &lt;a href="https://www.postgresql.org/list/"&gt;mailing list&lt;/a&gt; or check out the &lt;a href="http://postgres-slack.herokuapp.com/"&gt;slack channel&lt;/a&gt;. The users mailing is a great one to just jump in and help answer questions and see what people need help with. The hackers list is where you go to get a peek at all the fun debates/discussions/development.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re thinking about contributing it&amp;rsquo;s a good idea to lurk on the hackers list for a bit first. Then when the commitfest comes chip in and help review some patches and do some testing. Oh and of course, you can always blog about what you&amp;rsquo;re doing with Postgres and will aim to get it included into &lt;a href="https://www.postgresweekly.com"&gt;Postgres Weekly&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>Tue, 31 Oct 2017 22:55:56 GMT</pubDate><guid isPermaLink="true">/2017/10/31/Postgres-the-non-code-bits/</guid></item><item><title>The Internet worm of 1988: A Tour of the Worm</title><link>https://jmthornton.net/blog/p/worm-of-1988</link><description>On the evening of November 2, 1988, a self-replicating program was released upon the Internet. Within the space of hours this program had spread across the US.</description><author>Blog by Jade Michael Thornton</author><pubDate>Tue, 31 Oct 2017 17:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/worm-of-1988</guid></item><item><title>PDO vs MySQLi speed comparison</title><link>https://www.jimwestergren.com/pdo-versus-mysqli</link><description>My conclusion Based on my testing and the advantages of PDO (info) I recommend the following: Use PDO with PDO::ATTR_EMULATE_PREPARES set to TRUE and use the charset=utf8mb4 in the dsn (to be equally safe as if emulation was turned off). The speed increase is around 80% and this is not the default with for example &amp;#91;...&amp;#93;</description><author>Jim Westergren</author><pubDate>Tue, 31 Oct 2017 10:34:00 GMT</pubDate><guid isPermaLink="true">https://www.jimwestergren.com/pdo-versus-mysqli</guid></item><item><title>reMarkable review</title><link>https://michael.mior.ca/blog/remarkable-review/</link><description>&lt;p&gt;As an academic, I spend a lot of time reading papers.
I generally hate the idea of printing out a paper for a one-time read since it feels wasteful, but I also don’t enjoy the reading experience of viewing papers on a desktop screen.
I’ve always liked the look of the &lt;a href="https://www.sony.com/electronics/digital-paper-notepads/dpt-rp1"&gt;Sony Digital Paper&lt;/a&gt; that my advisor uses but it’s rather expensive and not easy to find.
I used a &lt;a href="http://www.samsung.com/consumer/mobile-devices/tablets/others/GT-P5100ZWAXEF/"&gt;Samsung Galaxy Tab 3&lt;/a&gt; for several years which freed me from my desk and made note-taking easier, but still wasn’t as nice as paper.&lt;/p&gt;
&lt;p&gt;This is why I was excited to hear about the &lt;a href="https://remarkable.com/"&gt;reMarkable&lt;/a&gt;.
The stated goal of reMarkable is to be a tablet for paper lovers.
The cost is still fairly significant for a grad student, and I actually cancelled my first preorder before changing my mind and committing.
While I did experience shipping delays that seem inevitable with crowd funded projects, I finally got my device this past Thursday.&lt;/p&gt;
&lt;p&gt;So far, I’m pretty impressed by the hardware and the writing experience.
There’s definitely no perceivable latency when writing and most other actions happen quite quickly as well.
The software still needs a lot of work (especially the &lt;a href="https://play.google.com/store/apps/details?id=com.remarkable.mobile"&gt;Android app&lt;/a&gt;) and I’ve had some issues with syncing not working correctly.
My biggest disappointment so far, is that the Wi-Fi on the device doesn’t currently support networks which use usernames and passwords for authentication, which means I can’t use wireless connectivity in the office.
This is a pretty big drawback, but there’s already a promise to fix this in a future software update.
Overall, I’m looking forward to seeing what happens.&lt;/p&gt;</description><author>Michael Mior</author><pubDate>Tue, 31 Oct 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://michael.mior.ca/blog/remarkable-review/</guid></item><item><title>The Gym</title><link>https://martinrue.com/the-gym/</link><description>Anyone who knows me will know that the gym is a fairly big part of my life. While my goal certainly isn't to become the next Eddie Hall or Phil Heath, during the last 3 years the gym has been a valuable source of discipline and improvement for me.</description><author>Martin Rue</author><pubDate>Tue, 31 Oct 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://martinrue.com/the-gym/</guid></item><item><title>Born to Run</title><link>https://nindalf.com/posts/born-to-run/</link><description>Born to Run is a low-quality pseudo-science book that pushes the agenda of barefoot running without disclosing the lack of conclusive evidence.</description><author>Krishna's blog</author><pubDate>Tue, 31 Oct 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/born-to-run/</guid></item><item><title>A VIM User's Experiments With GUI Code Editors</title><link>https://www.mattcrampton.com/blog/a_vim_users_experiments_with_gui_code_editors/</link><description>When You Pry It From My Cold, Dead Hands... I've been a die hard VIM user since the days of co-founding the Kalamazoo Linux Users Group back in 1998. It's a clean command line editor with a simple user interface and once you've mastered the admittedly steep learning curve of its robust keyboard shortcuts, I haven't found any substitutes that measure up for raw horsepower coding. But... Relatively recently there's been a lot of advancement around pairing code editors with debugging utilities which has started to leave editors like VIM behind. The ability to instantly set break points in React code and have that matched in real time with your browser is starting to make me want to lift my head out of my Ubuntu VM and see what all the cool kids are using these days. Visual Studio Code Chrome debugging If you're like me and hail back to the old school days of awk, grep and sed, you might be cringing and the very thought of a mouse click as an integral part of your coding flow, but let's...</description><author>MattCrampton.com</author><pubDate>Mon, 30 Oct 2017 07:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/a_vim_users_experiments_with_gui_code_editors/</guid></item><item><title>Repubblica: crappy journalism from The Usual Suspects</title><link>https://stop.zona-m.net/2017/10/repubblica-crappy-journalism-from-the-usual-suspects/</link><description>&lt;p&gt;Do you remember &amp;ldquo;Who is Keyser Soze?&amp;rdquo;? That was the recurring line of a great movie, which is now related to another question: who, in the staff of italian newspaper Repubblica (and many other newspapers too, of course) still makes, or allows, crap like &lt;a href="http://www.repubblica.it/spettacoli/cinema/2017/10/30/news/l_attore_premio_oscar_kevin_spacey_rivela_si_sono_gay_-179735175/?rss"&gt;this&lt;/a&gt;?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 30 Oct 2017 04:50:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/repubblica-crappy-journalism-from-the-usual-suspects/</guid></item><item><title>Light mallet</title><link>https://june.kim/light-mallet/</link><author>june.kim</author><pubDate>Mon, 30 Oct 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/light-mallet/</guid></item><item><title>How to Become Invincible</title><link>https://www.danstroot.com/posts/2017-10-30-how-to-become-invincible</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/truth.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Do you want to become invincible? I mean “rock solid”; impenetrable; bullet-proof? The answer is simple: strive to **be the truth**.&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2017-10-30-how-to-become-invincible"&gt;How to Become Invincible&lt;/a&gt; first appeared on &lt;a href="https://www.danstroot.com"&gt;Dan Stroot's Blog&lt;/a&gt;</description><author>Dan Stroot</author><pubDate>Mon, 30 Oct 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2017-10-30-how-to-become-invincible</guid></item><item><title>Builders vs Maintainers</title><link>https://bytesizetheories.com/posts/builders-vs-maintainers/</link><description>I have found that software engineers tend to divide themselves into 2 broad categories:
 Builders (selfish) Maintainers (selfless)  This is of course an oversimplification. Most of the time we do a bit of both, but in my experience engineers tend to lean towards one or the other.
The beef I have with this is that maintainers rarely do this consciously. They also enjoy building, it&amp;rsquo;s just that they typically have some trait (perfectionism, humility, shyness, &amp;hellip;) that prevents them from pushing to get the opportunity to be a builder.</description><author>Byte Size Theories</author><pubDate>Sun, 29 Oct 2017 23:44:17 GMT</pubDate><guid isPermaLink="true">https://bytesizetheories.com/posts/builders-vs-maintainers/</guid></item><item><title>Quick Dive into React</title><link>https://josh.works/quick-dive-into-react</link><description>&lt;p&gt;&lt;em&gt;As usual, this is a work in progress. At a high level, I’m familiarizing myself with Phoenix/Elixir, and need to sharpen my React knowledge along the way.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After &lt;a href="_posts/2017-10-28-elixir-phoenix-part-deux.md"&gt;working through part 1&lt;/a&gt; of a &lt;a href="https://medium.com/@benhansen/lets-build-a-slack-clone-with-elixir-phoenix-and-react-part-1-project-setup-3252ae780a1"&gt;slack clone in Elixir/Phoenix tutorial&lt;/a&gt;, I ran into some errors getting the React app up and running.&lt;/p&gt;

&lt;p&gt;I expect errors, but don’t have enough familiarity with React to effectively debug, so I’m going to take a quick spin through the tool, see what I can quickly learn, and then debug the errors I saw.&lt;/p&gt;

&lt;!--more--&gt;</description><author>Josh Thompson</author><pubDate>Sun, 29 Oct 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/quick-dive-into-react</guid></item><item><title>Robots displacing humans... or humans becoming robots?</title><link>https://stop.zona-m.net/2017/10/robots-displacing-humans...-or-humans-becoming-robots/</link><description>&lt;p&gt;There is lot of fear around about robots, or more exactly software-powered automation, destroying jobs by the millions. But maybe there is still not enough awareness, and concern, about software creating jobs that &lt;strong&gt;only a robot&lt;/strong&gt; would be happy, and fit, to do.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 29 Oct 2017 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/robots-displacing-humans...-or-humans-becoming-robots/</guid></item><item><title>Tips for a successful WooCommerce project</title><link>https://daniel.do/article/tips-for-a-successful-woocommerce-build</link><description>Building your first WooCommerce site? Here are 4 things to consider.</description><author>Daniel Immke</author><pubDate>Sun, 29 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/tips-for-a-successful-woocommerce-build</guid></item><item><title>Elixir/Phoenix part deux</title><link>https://josh.works/elixir-phoenix-part-deux</link><description>&lt;p&gt;I planned on working through &lt;a href="https://medium.com/@benhansen/lets-build-a-slack-clone-with-elixir-phoenix-and-react-part-1-project-setup-3252ae780a1"&gt;this&lt;/a&gt; tutorial for building a slack clone, but half-way through the set-up instructions, after I installed Elixir and Phoenix, I &lt;a href="_posts/2017-10-27-intro_elixir.md"&gt;took a long detour&lt;/a&gt; through the basic set-up guide. Built some custom routes, along with controllers/views/templates, etc.&lt;/p&gt;

&lt;p&gt;I’m now a bit more comfortable with the basics of the framework and language, so I’ll now be working through the tutorial, and &lt;a href="https://www.wikiwand.com/en/Rubber_duck_debugging"&gt;Rubber Duck Debugging&lt;/a&gt; by writing about it as I go.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will be a bit of a work-in-progress. Onward.&lt;/em&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;OK. Basic setup done. Scaffolded the Phoenix and React app, made the &lt;a href="https://github.com/josh-works/sling_clone"&gt;initial commit&lt;/a&gt;, and we’re cooking with gas.&lt;/p&gt;

&lt;p&gt;The setup is pretty straight forward - a quick note on the &lt;em&gt;React/Redux Boilerplate&lt;/em&gt; section: I’ve had only passing experience with React/Redux, so I might take a detour through some resources for those tools sometime during this tutorial.&lt;/p&gt;

&lt;p&gt;I don’t find much value in blindly following guides without having a good idea of what’s going on. This desire is tempered by me knowing that I cannot absorb everything my first pass, and things will become clear on my third and fourth exposure to a topic that I simply cannot pick up my first or second.&lt;/p&gt;

&lt;p&gt;OK, down to the bottom of the first tutorial section, and the React App is not working as expected. &lt;a href="https://github.com/josh-works/sling_clone/commit/43084b18f7fb8050c313bf857dc19f65f6ea3d68"&gt;Here’s where I’m at right now&lt;/a&gt;, and while it’s compiling successfully, I’ve got lots of errors:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Broadcast.js:104 Uncaught TypeError: Cannot read property 'object' of undefined
    at Object../node_modules/react-broadcast/Broadcast.js (Broadcast.js:104)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object../node_modules/react-broadcast/index.js (index.js:6)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object../node_modules/react-router/Broadcasts.js (Broadcasts.js:12)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object../node_modules/react-router/Link.js (Link.js:13)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object../node_modules/react-router/index.js (index.js:6)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object../src/containers/App/index.js (index.js:11)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object../src/index.js (index.js:7)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at fn (bootstrap 4fb1954d0e8840de1bbc:87)
    at Object.0 (index.js:11)
    at __webpack_require__ (bootstrap 4fb1954d0e8840de1bbc:669)
    at bootstrap 4fb1954d0e8840de1bbc:715
    at bundle.js:719
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As I mentioned earlier, I don’t have tons of React experience, so I’m going to go take a quick dive into the world of React. I expect, on the other end, to have a better framework for debugging and understanding the design decisions the tutorial author is making.&lt;/p&gt;

&lt;p&gt;I think part of the challenge is this guide was written in January 2017, or approaching a year ago. React changes quickly, and in Ruby/Rails, I’ve always been able to fill in the info gaps when debugging problems, but React (and Elixir) I’m not yet there.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href="/quick-dive-into-react"&gt;Quick pass through React&lt;/a&gt;&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Sat, 28 Oct 2017 10:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/elixir-phoenix-part-deux</guid></item><item><title>Once more: online or e-voting? No. Just no</title><link>https://stop.zona-m.net/2017/10/once-more-online-or-e-voting-no.-just-no/</link><description>&lt;p&gt;OK, let&amp;rsquo;s summarize this again.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 28 Oct 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/once-more-online-or-e-voting-no.-just-no/</guid></item><item><title>The Long Road to Async/Await in JavaScript at NodeConfAr17</title><link>https://thomashunter.name/posts/2017-10-28-async-await-javascript-nodeconfar17</link><author>Thomas Hunter II</author><pubDate>Sat, 28 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-10-28-async-await-javascript-nodeconfar17</guid></item><item><title>Hidden Hope For Control</title><link>https://venam.net/blog/psychology/2017/10/28/will-for-control.html</link><description>This article is about a rarely discussed component that resides in the background of our lives.  No word clearly describes this phenomenon as it's a fusion of different ideas.  We blueprint ourselves according to media that display extravagant versions of winners and losers. The profiles on social media are facade created around individuals — Profile being a well-chosen word as it misses the other angles. All across those there's an implicit demand of mechanized efficiency which slipped from our workplace to our interaction with ourselves. We are our own employee and are expecting results.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sat, 28 Oct 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2017/10/28/will-for-control.html</guid></item><item><title>First pass with Elixir/Phoenix</title><link>https://josh.works/first-pass-elixir-phoenix</link><description>&lt;p&gt;I’m digging into Elixir and Phoenix. I’m working through &lt;a href="https://medium.com/@benhansen/lets-build-a-slack-clone-with-elixir-phoenix-and-react-part-1-project-setup-3252ae780a1"&gt;this tutorial to cloning Slack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The tutorial author says&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;At the time of writing, I have ~1 week experience with Phoenix. Similar to &lt;a href="https://www.wikiwand.com/en/Rubber_duck_debugging"&gt;Rubber Ducky Debugging&lt;/a&gt;, I am writing this blog post to force myself to think differently about the problems I am solving and therefore gain a better understanding of the language and framework.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Couldn’t agree more myself. This post serves as &lt;em&gt;my&lt;/em&gt; Rubber Ducky Debugging process for getting started with Elixir/Phoenix.&lt;/p&gt;

&lt;p&gt;Similar to the author, I come from a Ruby/Rails background, but undoubtedly less experienced than the author. So, this article will capture tidbits and pieces useful to me as I work through the tutorial.&lt;/p&gt;

&lt;p&gt;I’m &lt;a href="/learning-how-to-learn"&gt;intentional in how I learn&lt;/a&gt;, as well as in &lt;a href="/better-questions"&gt;how I ask questions&lt;/a&gt;, so this is just me, doing what I do, to learn things.&lt;/p&gt;

&lt;p&gt;Onward!&lt;/p&gt;

&lt;h1 id="installing-elixir-and-phoenix"&gt;Installing Elixir and Phoenix&lt;/h1&gt;

&lt;p&gt;Installation is super easy.&lt;/p&gt;

&lt;p&gt;The recommended tutorials + some clicking around was all I needed. Brew handled most of it, and &lt;a href="https://elixir-lang.org/install.html"&gt;elixir-lang’s installation guide&lt;/a&gt; pairs well with &lt;a href="https://hexdocs.pm/phoenix/installation.html"&gt;the same for phoenix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just &lt;code class="language-plaintext highlighter-rouge"&gt;cd&lt;/code&gt;‘ed into &lt;code class="language-plaintext highlighter-rouge"&gt;workspace/elixir&lt;/code&gt; (where my otherwise homeless bits of code lives) and test-drove Phoenix’s equivalent of &lt;code class="language-plaintext highlighter-rouge"&gt;rails new&lt;/code&gt;. I’m taking a quick detour through &lt;a href="https://hexdocs.pm/phoenix/up_and_running.html"&gt;this guide&lt;/a&gt; at the moment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OK, it was more than a quick detour. The rest of this post is me familiarizing myself with the above guide. Read &lt;a href="/elixir-phoenix-part-deux"&gt;Elixir/Phoenix part deux&lt;/a&gt; for more&lt;/em&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;$ mix phx.new hellow&lt;/code&gt; gives us a bunch of output, and eventually a new project.&lt;/p&gt;

&lt;p&gt;(I tend to intentionally misspell variables and such when following tutorials - helps me detangle the language/framework’s nomenclature from my own, and tunes me in a bit closer to ways to make errors. So, this project is named “hellow”, and any further code snippets will reflect that. Be wary, this strategy has led me into more than a little debugging as I walk through tutorials. But I come out stronger on the other end…)&lt;/p&gt;

&lt;p&gt;The directory structure looks familiar:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;.
├── README.md
├── _build
├── assets
├── config
├── deps
├── lib
├── mix.exs
├── mix.lock
├── priv
└── test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;deps&lt;/code&gt; is foreign to me, though. Inside of that directory is a bunch of other directories, all looking greek to me.&lt;/p&gt;

&lt;p&gt;Poking around a bit, I’m seeing files with &lt;code class="language-plaintext highlighter-rouge"&gt;.ex&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;.exs&lt;/code&gt; extensions. &lt;a href="https://stackoverflow.com/questions/36292620/elixir-when-to-use-ex-and-when-exs-files"&gt;StackOverflow&lt;/a&gt; says &lt;code class="language-plaintext highlighter-rouge"&gt;.ex&lt;/code&gt; is for “compiled” Elixir code, while &lt;code class="language-plaintext highlighter-rouge"&gt;.exs&lt;/code&gt; is “scripting” Elixir code. Elixir is my first brush with a functional programming language, which is &lt;em&gt;also&lt;/em&gt; my first exposure to compiled languages, so I’m putting a flag in this as Significant.&lt;/p&gt;

&lt;p&gt;Ah, and &lt;code class="language-plaintext highlighter-rouge"&gt;.eex&lt;/code&gt; is “embedded Elixir”, or in my Rails-centric background “elixir’s version of embedded ruby/.erb”. Good, because no one wants to write raw HTML.&lt;/p&gt;

&lt;p&gt;If Elixir doesn’t have some version of &lt;code class="language-plaintext highlighter-rouge"&gt;pry&lt;/code&gt;, I’m going to be sad.&lt;/p&gt;

&lt;p&gt;Per the instructions, &lt;code class="language-plaintext highlighter-rouge"&gt;$ mix ecto.create&lt;/code&gt;, a few missing dependencies (say &lt;code class="language-plaintext highlighter-rouge"&gt;Y&lt;/code&gt;), and&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;=&amp;gt; The database for Hellow.Repo has been created
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wahoo.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;$ mix phx.server&lt;/code&gt; seems to be &lt;code class="language-plaintext highlighter-rouge"&gt;rails server&lt;/code&gt;. So handy having a mental framework to hang new info on.&lt;/p&gt;

&lt;p&gt;A quick check of &lt;code class="language-plaintext highlighter-rouge"&gt;localhost:4000&lt;/code&gt; and we’re in business:&lt;/p&gt;

&lt;p&gt;&lt;img alt="terminal goodies + localhost" src="/images/2017-10-27-elixir_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;On to &lt;a href="https://hexdocs.pm/phoenix/adding_pages.html"&gt;part 2&lt;/a&gt; of the intro guide:&lt;/p&gt;

&lt;p&gt;The writeup mentions that most of our work will live in the &lt;code class="language-plaintext highlighter-rouge"&gt;/lib&lt;/code&gt; directory&lt;/p&gt;

&lt;p&gt;Lots of interesting stuff that seems quite familiar after working with a MVC model, but we’ll dig into it all later.&lt;/p&gt;

&lt;h1 id="routes"&gt;Routes&lt;/h1&gt;

&lt;p&gt;Ah, routes. Makes me nostalgic for &lt;code class="language-plaintext highlighter-rouge"&gt;config/routes.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Elixir’s equivalent lives in &lt;code class="language-plaintext highlighter-rouge"&gt;hellow/lib/hellow_web/router.ex&lt;/code&gt;, which we know is a compiled file (I think?).&lt;/p&gt;

&lt;p&gt;By default, it looks pretty manageable:&lt;/p&gt;

&lt;div class="language-elixir highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Router&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:router&lt;/span&gt;

  &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:browser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:accepts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:fetch_session&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:fetch_flash&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:protect_from_forgery&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:put_secure_browser_headers&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;plug&lt;/span&gt; &lt;span class="ss"&gt;:accepts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"json"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:browser&lt;/span&gt; &lt;span class="c1"&gt;# Use the default browser stack&lt;/span&gt;

    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PageController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As soon as seeing the reference to PageController, I had to see if there was an associated test.&lt;/p&gt;

&lt;p&gt;Ah, software. It even reads just like RSpec. :)&lt;/p&gt;

&lt;div class="language-elixir highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test/hellow_web/controllers/page_controller_test.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PageControllerTest&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ConnCase&lt;/span&gt;

  &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"GET /"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;conn:&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;html_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="s2"&gt;"Welcome to Phoenix!"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="testing"&gt;Testing&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;We interrupt current programming to figure out how to run tests in Elixir&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Looks like &lt;code class="language-plaintext highlighter-rouge"&gt;Mix&lt;/code&gt; is an Elixir build tool. We’ll be using it a lot.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ExUnit&lt;/code&gt; seems to be Elixir’s test-unit framework. AKA RSpec/Minitest. (&lt;a href="https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html"&gt;source&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;And &lt;a href="https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html#running-tests"&gt;tests&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks like &lt;code class="language-plaintext highlighter-rouge"&gt;$ mix test&lt;/code&gt; does it.&lt;/p&gt;

&lt;p&gt;Holy cow… There’s a ton of deprecation warnings and the test took ages. (Er, it passed by the way. )&lt;/p&gt;

&lt;p&gt;Looks like this is a &lt;a href="https://www.bountysource.com/issues/43427732-fix-elixir-1-5-deprecation-warnings"&gt;new and fixed issue&lt;/a&gt;, so the recommended fix is to use a more recent version of &lt;a href="https://github.com/devinus/poison"&gt;poison&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jumping into &lt;code class="language-plaintext highlighter-rouge"&gt;mix.exs&lt;/code&gt; (aka Rail’s &lt;code class="language-plaintext highlighter-rouge"&gt;Gemfile&lt;/code&gt;), adding the newest version of poison:&lt;/p&gt;

&lt;div class="language-elixir highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:poison&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 3.1"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:phoenix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.3.0"&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="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and updating dependencies:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;$ mix deps.get&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and lets run the tests again:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;$ mix test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ah, lovely. No more dependency problems.&lt;/p&gt;

&lt;p&gt;Two other notable events, though - I think the first time I ran the tests, Mix had a ton of compiling to do.&lt;/p&gt;

&lt;p&gt;This is the output from the first test run:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c"&gt;# all of the many deprecation warnings removed&lt;/span&gt;
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; connection
Compiling 1 file &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated connection app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; gettext
Compiling 1 file &lt;span class="o"&gt;(&lt;/span&gt;.erl&lt;span class="o"&gt;)&lt;/span&gt;
Compiling 20 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated gettext app
&lt;span class="o"&gt;===&amp;gt;&lt;/span&gt; Compiling ranch
&lt;span class="o"&gt;===&amp;gt;&lt;/span&gt; Compiling poolboy
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; decimal
Compiling 1 file &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated decimal app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; poison
Generated poison app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; db_connection
Compiling 23 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated db_connection app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; phoenix_pubsub
Compiling 12 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated phoenix_pubsub app
&lt;span class="o"&gt;===&amp;gt;&lt;/span&gt; Compiling cowlib
&lt;span class="o"&gt;===&amp;gt;&lt;/span&gt; Compiling cowboy
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; mime
Compiling 1 file &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated mime app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; plug
Compiling 1 file &lt;span class="o"&gt;(&lt;/span&gt;.erl&lt;span class="o"&gt;)&lt;/span&gt;
Compiling 44 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated plug app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; phoenix_html
Compiling 8 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated phoenix_html app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; phoenix
Compiling 74 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated phoenix app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; postgrex
Compiling 62 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated postgrex app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; ecto
Compiling 70 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated ecto app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; phoenix_ecto
Compiling 6 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated phoenix_ecto app
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; hellow
Compiling 16 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated hellow app
....

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.1 seconds
4 tests, 0 failures

Randomized with seed 769269
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second time I ran it, not only were there no deprecation warnings, there was basically no set-up:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mix &lt;span class="nb"&gt;test
&lt;/span&gt;Compiling 16 files &lt;span class="o"&gt;(&lt;/span&gt;.ex&lt;span class="o"&gt;)&lt;/span&gt;
Generated hellow app
....

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.06 seconds
4 tests, 0 failures

Randomized with seed 608206
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;OK, again, I feel like all the setup steps are Significant, but don’t yet know why.&lt;/p&gt;

&lt;p&gt;Onward!&lt;/p&gt;

&lt;h2 id="back-to-routesrouting"&gt;Back to Routes/Routing&lt;/h2&gt;

&lt;p&gt;Lets add:&lt;/p&gt;

&lt;div class="language-elixir highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;pipe_through&lt;/span&gt; &lt;span class="ss"&gt;:browser&lt;/span&gt; &lt;span class="c1"&gt;# Use the default browser stack&lt;/span&gt;

    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PageController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;HellowController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt; &lt;span class="c1"&gt;# Adding this bad boy&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When visiting &lt;code class="language-plaintext highlighter-rouge"&gt;localhost:4000/hello&lt;/code&gt;, we get a very Rails-esque error code, saying “I cannot find the controller you’re asking for”. Which is great, because &lt;code class="language-plaintext highlighter-rouge"&gt;HellowController&lt;/code&gt; doesn’t exist.&lt;/p&gt;

&lt;h3 id="a-new-controller"&gt;A new Controller&lt;/h3&gt;

&lt;p&gt;Jumping in to make a new controller file moves us along in error-driven development (EDD):&lt;/p&gt;

&lt;div class="language-elixir highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/hellow_web/controllers/hellow_controller.ex&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;HellowController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;HellowWeb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"index.html"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we 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;UndefinedFunctionError at GET /hello
function HellowWeb.HellowView.render/2 is undefined (module HellowWeb.HellowView is not available)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Perfect. We are (I suspect) calling a non-existent file to render stuff to the browser. Phoenix complains.&lt;/p&gt;

&lt;h3 id="a-new-view"&gt;A new View&lt;/h3&gt;

&lt;p&gt;I put together a quick view, templated off an existing view, and for the first time my MVC background failed me. I assumed views would be for presentation, but it seems like Views in Phoenix are more analagous to Models in Rails.&lt;/p&gt;

&lt;p&gt;There’s a &lt;code class="language-plaintext highlighter-rouge"&gt;/templates&lt;/code&gt; directory that contains presentation-related data, so I’ll just run with “view == models” for now.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Phoenix views have several important jobs. They render templates. They also act as a presentation layer for raw data from the controller, preparing it for use in a template. Functions which perform this transformation should go in a view. (&lt;a href="https://hexdocs.pm/phoenix/adding_pages.html#a-new-view"&gt;hexdocks&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="templates"&gt;Templates&lt;/h3&gt;

&lt;p&gt;Ah, interesting. As soon as I created &lt;code class="language-plaintext highlighter-rouge"&gt;lib/hellow_web/templates/hellow/index.html.eex&lt;/code&gt;, the errors in Mix went away, and I’m now loading an empty page.&lt;/p&gt;

&lt;p&gt;(Even though the file is empty)&lt;/p&gt;

&lt;p&gt;So, Phenix has live code-reloading (when I made the file, I saw the logs from &lt;code class="language-plaintext highlighter-rouge"&gt;mix phx.server&lt;/code&gt; show compiling and rendering data. The red went away.)&lt;/p&gt;

&lt;p&gt;Also, the view is obviously embedded inside of an application layout, because the header/footer/things-that-make-HTML-work-on-the-internet kicked in and rendered my three lines of HTML.&lt;/p&gt;

&lt;p&gt;A quick peek at &lt;code class="language-plaintext highlighter-rouge"&gt;lib/hellow_web/templates/layout/app.html.eex&lt;/code&gt;, and it’s almost indistinguishable from &lt;code class="language-plaintext highlighter-rouge"&gt;app/views/layouts/application.html.erb&lt;/code&gt; in Rails.&lt;/p&gt;

&lt;h3 id="a-second-new-page"&gt;A second new page&lt;/h3&gt;

&lt;p&gt;The universally sound advice for education and training applies here quite well:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do it again, faster&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, I did a quick trip through &lt;a href="https://hexdocs.pm/phoenix/adding_pages.html#another-new-page"&gt;adding another page&lt;/a&gt;, to do a standard “handle a dynamic URL and present the value from the URL in the browser”. This is like the “hello world” of dynamic routing.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;That’s the end of the tiny “getting started” tutorial. I’m ending this post here, and will continue with the slack clone in &lt;a href="/elixir-phoenix-part-deux"&gt;part 2&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Fri, 27 Oct 2017 10:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/first-pass-elixir-phoenix</guid></item><item><title>Everything And More, a short review</title><link>https://faingezicht.com/articles/2017/10/27/infinity/</link><description>The first time I heard about David Foster Wallace was during my sophomore year of college. My girlfriend was powering through _Infinite Jest_, and was surprised I had never heard about the book or its author. I told her it sounded unbearable. A few years later, a friend picked &lt;a href="https://www.rollingstone.com/politics/features/david-foster-wallace-on-john-mccain-2000-rolling-stone-story-w493273"&gt;The Weasel, Twelve Monkeys and the Shrub&lt;/a&gt; as reading material for our article club[^1], and I had no choice - I read it and hated it. Then this year, I was talking about &lt;a href="https://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach"&gt;GEB&lt;/a&gt; with my boss's boss's boss and he insisted that even if I hated DFW's writing, I had to read his book on infinity. I followed his advice.

_Everything and More_ walks a thin line between being too technical for the untrained reader and too dumbed down for the expert. For better or for worse, I fall somewhere in between. I enjoyed reading about Mr. Chicken, the rooster who _inductively_ figured out that _t_(man + sack)=food, only to end up dead in the sack himself a few weeks later. I also enjoyed figuring out the inner workings of $$\aleph _{0}$$ and drudging through proofs of how certain kinds of infinities are greater than others. As someone without a pure math background, it seems like DFW did a good job of exposing the reader to a wide set of ideas. How thoroughly he explains them is a different issue. From some quick research it seems like the book got a lot of well-deserved flak for it's accuracy (or lack thereof) upon release. Regardless, it is worth reading not so much for its comprehensive proofs, but for the way it illuminates the development of modern mathematics.

Early on, DFW explains that, in math, paradoxes arise from expressing logical systems as natural language. For example, halve the distance between two sidewalks enough times, and with a bit of rhetoric and pomp even the smartest people start to believe that &lt;a href="https://en.wikipedia.org/wiki/Zeno%27s_paradoxes"&gt;crossing a street is impossible&lt;/a&gt;. Thanks, infinite regress! The whole book is peppered with the histories of these paradoxes, and of mathematicians trying to overcome them. From the Greeks to Galileo, over time there is a growing gap between the theorists (dealing in abstraction) and the engineers and physicists (dealing with reality). The two can't be easily reconciled, but that only concerns one of the two groups. The issue is especially exacerbated with the discovery of calculus in the 17th century, and the explotion of its applications in construction, warfare, navigation, astronomy, etc:

&gt; The situation of mathematics after 1700 is intensely weird [...] mathematical discoveries enabled scientific advances, which themselves motivated further math discoveries. [This] created for math a situation that resembled a tree with great lush proliferant systems of branches but no real roots. There were still no grounded, rigorous definitions of the differential, derivative, integral, limit, or convergent/divergent series. Not even of the function. There was constant controversy, and yet at the same time nobody seemed to care.
&gt;
&gt; David Foster Wallace - Everything and More, §5a

For roughly a century and a half people solved a panoply of life-changing human problems via calculus, without understanding its underpinnings. Later on, the book compares this disparity to a market bubble. The appearance of analysis, set theory, and modern mathematics, as explained by DFW, are the response to this chaos, set in motion by the discovery of calculus. The rigor that these new branches of math brought to the field eventually became the foundation that powered the technological advances of the 19th and early 20th century.

What is most striking is how much of a parallel we can draw between the development of calculus and today's state of the art in computer science, with machine learning being particularly pertinent - the whole field is based on empiricism and induction. The eighteenth and nineteenth century engineers treated the methods of calculus as black boxes, and trusted them enough to use their answers to construct buildings, to predict the movement of stars, and to sail across the Atlantic. _Whole complex human systems based on the output of black boxes._ Read that again and tell me that there isn't a parallel to software engineering and machine learning. It makes one wonder where our technology today might be headed.

Notice that this is not a dis on the Bengios and Hintons of the world, nor on my peers who are practitioners in the field. To the contrary. If anything its a comparison to Newton and Leibniz kicking off this transformation, and to the Boyles and the Watts who put the knowledge in motion.

What DFW's book in a sense revealed to me is that while today anyone can download Tensorflow and feed the black box with some data to solve real problems, there's a lot still to uncover. The frontier of knowledge is ever expanding, and it has not disappointed us so far. Perhaps all we need is our own Karl Weierstrass to come and wake us up from the stupor, and a George Cantor to lead the way forward. Computer science is as alive as ever, and for the last fifty years has driven the greatest technological revolution in history. Just imagine where we'll be when we move past the black box.

[^1]: Article club? That's a story for another time.

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: by me, previously posted on &lt;a href="/photos/2016/10/31/napa/"&gt;Napa&lt;/a&gt;.&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Fri, 27 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/10/27/infinity/</guid></item><item><title>The shifting sweet spot for media</title><link>http://dimitarsimeonov.com/2017/10/27/the-shifting-sweet-spot-for-media</link><description>&lt;p&gt;How informative is media really. The incentives on any media
organization are like the incentives on any other company - to make
profits.  Media also aims to make people informed on
important facts.  That’s how people perceive the value of
media. That, and entertainment. All media wants people to consume it,
in order to get revenue from subscriptions, or from advertisement.&lt;/p&gt;

&lt;p&gt;Let’s temporary make a distinction between media as a business, and
media as an informer. Every media outlet has a bipolar disorder
between these two. The decision makers in each media sometimes decide
with their business hat, and sometimes they do it with their informant
hat.&lt;/p&gt;

&lt;p&gt;It makes sense to balance the two. If the media spends too much
resources on developing the content, the final product will be of
higher quality, but more expensive. But the slight increase in
quality, would not justify a steep increase in price, for the
customers. Most of them would stop using it, and that would make it
not viable financially.  Instead, if the media spends too little
resources, then the quality of the content will go down, and customers
will flee for the opposite reason.&lt;/p&gt;

&lt;p&gt;Each media business needs to find a sweet spot in terms of price and
quality.  And that sweet spot derives from the current market
conditions and the ability of the management and employees.&lt;/p&gt;

&lt;p&gt;Internet affects the sweet spots in a profound way. Some might say
“disruptive”. On the Internet, the distribution cost of media is a lot
lower than before. They can move over to low-precision low cost land
for their facts supply. I think it is great to have such choice.
It improves market efficiency, but by adding a new lowest sweet spot, it
triggers a gradual reconfiguration of all existing sweets spots before.&lt;/p&gt;

&lt;p&gt;As some people flock to the low precision land for their supply of
“facts”, this changes the demographics of those who remain willing to
pay for high precision media. With fewer and fewer customers, there
are more biases in their overall views. And each media, consciously or
subconsciously will start tending more and more to the tastes of this
population. And thus, each media becomes more and more biased.&lt;/p&gt;

&lt;p&gt;But it’s not purely the media’s fault. It’s ours as well. We all tend
to believe more the facts which agree with our opinions, and ignore
the facts which disagree. And media feeds us only what we like to
digest. The tasty facts. By forcing media to adapt to our tastes, we
increasingly fake-ify it. Media had objectivity and coverage issues
before, but now these are exacerbated, and much more fundamental to
media’s existence.&lt;/p&gt;

&lt;p&gt;It’s not clear how the media landscape will develop, and whether there
will be a high precision, high recall media in the future. This
depends on market conditions, and technology improvements. What we can
do meanwhile is to apply pressure on media to be more objective, but
not merely by complaining to the media about facts we don’t like.&lt;/p&gt;

&lt;p&gt;No, each of us needs to be a little bit more critical of facts that
seem too good or too bad to be true, and to more often look at facts
we disagree with, with a little bit of benefit of the doubt.  Just
like we all know that a single unrecycld cardboard box trash won’t
damage the environment, but if everyone recycles then we are much
better off, we will all be better off if we are more critical about
our media’s objectivity.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 27 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/10/27/the-shifting-sweet-spot-for-media</guid></item><item><title>Are you a robot?</title><link>https://yasha.solutions/are-you-a-robot/</link><description>Automation is coming.
It is affecting nearly all industries.
And it would be stupid to ignore it.
But aren’t we taking the frenzy a tad too far?
(Disclaimer:
This article is a bit messy – I have tried my best to give it a decent shape – but if we are to be honnest, it needs some serious re-writing – which I will probably do – but I wanted to get this out now anyway – so take it as a work in progress with maybe a few unfinished thoughts / sentence here and there…)</description><author>Yasha Solutions</author><pubDate>Fri, 27 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/are-you-a-robot/</guid></item><item><title>Two design articles</title><link>https://muffinman.io/blog/design-articles/</link><description>&lt;article class="article"&gt;&lt;p&gt;Just wanted to share two articles that helped me understand visual design better.
I was already aware of the most of these things, but having someone explain it how and why was really helpful.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@erikdkennedy/7-rules-for-creating-gorgeous-ui-part-1-559d4e805cda"&gt;7 Rules for Creating Gorgeous UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.muz.li/optical-effects-9fca82b4cd9a"&gt;Optical Effects in User Interfaces (for True Nerds)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="learn-more-about-design"&gt;Learn more about design &lt;a class="anchor-link" href="#learn-more-about-design"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When asked how to learn more about design as a developer,
design partner in my company recommended studying work of these two designers.
I haven&amp;#x27;t taken my time to do it, but it is on my todo list.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Massimo_Vignelli"&gt;Massimo Vignelli&lt;/a&gt; - author of NYC subway map&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Paul_Rand"&gt;Paul Rand&lt;/a&gt; - author of IBM logo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Frontend developers should have at least basic understanding of visual design.
Because great products are symbiosis of both great design and great tech.
Hopefully, these links will help you in that regard.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 27 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/design-articles/</guid></item><item><title>Misleading advice in Europol's cybercrime page</title><link>https://stop.zona-m.net/2017/10/misleading-advice-in-europols-cybercrime-page/</link><description>&lt;p&gt;Europol is the &lt;a href="https://www.europol.europa.eu/about-europol"&gt;EU&amp;rsquo;s law enforcement agency&lt;/a&gt;, whose main goal is &amp;ldquo;to  achieve a safer Europe for the benefit of all the EU citizens&amp;rdquo;. The Europol &lt;a href="https://www.europol.europa.eu/activities-services/public-awareness-and-prevention-guides/cyber-crime-vs-cyber-security-what-will-you-choose"&gt;page&lt;/a&gt; about public awareness and prevention mixes good advice with a few&amp;hellip; misleading bits of information.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 26 Oct 2017 11:10:34 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/misleading-advice-in-europols-cybercrime-page/</guid></item><item><title>Evaluating New Tools</title><link>https://blog.harterrt.com/new_tools.html</link><description>&lt;p&gt;At Mozilla, we're still relatively early in our data science journey.
As such, we're always evaluating new tools to improve our analysis workflow
(&lt;a href="http://jupyter.org/"&gt;jupyter&lt;/a&gt; vs. &lt;a href="http://rmarkdown.rstudio.com/"&gt;Rmd&lt;/a&gt;),
or make our infrastructure more usable
(our home-rolled &lt;a href="https://github.com/mozilla/telemetry-analysis-service"&gt;ATMO&lt;/a&gt;
vs. &lt;a href="https://databricks.com/"&gt;databricks&lt;/a&gt;),
or scale our knowledge
(&lt;a href="https://medium.com/airbnb-engineering/scaling-knowledge-at-airbnb-875d73eff091"&gt;knoledge-repo&lt;/a&gt;.
vs. &lt;a href="https://www.gitbook.com/"&gt;gitbook&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Most of these tools look like …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 26 Oct 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/new_tools.html</guid></item><item><title>Wall Street Journal Live Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/wsj_live_interview/</link><description>Wall Street Journal Live Interview with Matt Crampton On 10/8/2014 I did an interview with The Wall Street Journal talking about Gigwalk and the larger economy Wall Street Journal Live Interview with Matt Crampton Download Interview Video File size: 53.8 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/wsj_live_interview/</guid></item><item><title>Techcrunch Interview on Gigwalk with Matt Crampton</title><link>https://www.mattcrampton.com/blog/techcrunch_interview/</link><description>Techcrunch Interview on Gigwalk with Matt Crampton On Feb 20, 2013 I was interviewed by Sarah Perez at TechCrunch on Gigwalk and the Gig Economy Read Article The interiew is pasted below as well... Gigwalk, the mobile temp agency that allows users to get assigned jobs (or “gigs”) from companies in need of real-world data or market research, is today upgrading its business-facing platform as the service grows to accomodate larger-scale job assignments from customers like Microsoft, Mercedes-Benz, TomTom, eBay, and others. It’s also adding another big-name brand to its roster – Reckitt Benckiser, home to hundreds of household products including things like Lysol, Finish, Easy Off, Jet Dry, Woolite, Vanish, Vicks and many more. The company, which is something like a Mechanical Turk for the real world, recently raised a $6 million Series A from August Capital, Greylock, Harrison Metal, SoftTech VC, Founder Collective and others. It now reaches 220,000 workers, up from 200,000 in October...</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/techcrunch_interview/</guid></item><item><title>Salon.com Labormetrics Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/salon_labormetrics_interview/</link><description>Salon.com Labormetrics Interview with Matt Crampton On 08-16-2013 I was interviewed by Andrew Leonard for Salon.com on labor and the Gig economy. Read Article The interiew is pasted below as well... The scary new labormetrics of work Gigwalk will get you a job through your smartphone, and that’s cool. But don’t dawdle about answering your email ANDREW LEONARD 08.16.2013•4:44 AM Matt Crampton is pushing back against my charge that his company, Gigwalk, is contributing to class stratification in the United States. And to be perfectly fair, I've got to admit that Crampton doesn't look much like the embodiment of Silicon Valley income inequality. Sitting across a table from me at a Berkeley cafe, sporting a long bushy red beard, the co-founder and CTO of Gigwalk looks more like a Brooklyn hipster on his way to Burning Man than a paradigm-busting pioneer on the new frontier of work. "We are creating kinds of work that have never existed before," says Crampton. "The average person who dow...</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/salon_labormetrics_interview/</guid></item><item><title>NBC Press Here interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/nbc_press_here/</link><description>NBC Press Here interview with Matt Crampton I did an interview with NBC Press Here on August 29, 2013 with Chris Preimesberger and Levi Sumagaysay Download Interview Video File size: 26.3 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/nbc_press_here/</guid></item><item><title>Mobile Monday Silicon Valley panel with Matt Crampton</title><link>https://www.mattcrampton.com/blog/mobile_monday_panel/</link><description>Mobile Monday Silicon Valley panel with Matt Crampton On Nov 22, 2016 I spoke at the Mobile Monday Silicon Valley panel on Challenges in Starting an On Demand Service Download Video File size: 833.3 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/mobile_monday_panel/</guid></item><item><title>Human Cloud panel with Matt Crampton</title><link>https://www.mattcrampton.com/blog/human_cloud_panel/</link><description>Human Cloud panel with Matt Crampton In December 2014 I participated in a panel discussion focused on Online Staffing and Human Cloud Platforms Download Video File size: 732.0 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/human_cloud_panel/</guid></item><item><title>Huffington Post Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/huffington_going_against_the_flow/</link><description>Huffington Post Interview with Matt Crampton On 03/16/2015 I was interviewed by Charu Sharma for The Huffington Post on Gigwalk and going against the flow. Read Article The interiew is pasted below as well... Matt Crampton is the Cofounder and CTO of Gigwalk. He originally founded Gigwalk to create a marketplace to help businesses mobilize people to get work done. Since launching in May 2011, Gigwalk has grown into a local visibility software platform that facilitates brand and retailer collaboration with the world’s largest on-demand mobile workforce, also known as Gigwalkers. Prior to Gigwalk, Matt lead software development teams at Yahoo! Buzz, and HotJobs (starting in 2005), and lead front end development for AOL Shopping and Alerts (starting in 2000). Q: What does entrepreneurship mean to you, and what underlying characteristics do you see in successful entrepreneurs? MC: To me, entrepreneurship means creating something that has a life of its own; building value for everyone in...</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/huffington_going_against_the_flow/</guid></item><item><title>Fox Business Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/fox_business_interview/</link><description>Fox Business Interview with Matt Crampton On Jul 23, 2013 I did an interview with Fox Business talking about Gigwalk and the larger economy Fox Business Interview with Matt Crampton Download Interview Video File size: 24.2 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/fox_business_interview/</guid></item><item><title>Fox Business interview on furloughed government workers with Matt Crampton</title><link>https://www.mattcrampton.com/blog/fox_business_furloughed_workers_interview/</link><description>Fox Business interview on furloughed government workers with Matt Crampton On Oct. 15, 2013 I did an interview with Fox Business talking about online apps that furloughed government workers can use to make extra money Fox Business interview on furloughed government workers with Matt Crampton Download Interview Video File size: 110.8 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/fox_business_furloughed_workers_interview/</guid></item><item><title>Fortune Magazine Live Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/fortune_magazine_interview/</link><description>Fortune Magazine Live Interview with Matt Crampton On May 5, 2015 I did an interview with Fortune Magazine talking about Gigwalk and the larger economy. It was titled &amp;quot;Own a smartphone? You can work for some of the world's biggest brands&amp;quot; See the original interview here (Note flash is required to view the video embedded below)</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/fortune_magazine_interview/</guid></item><item><title>CCTV Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/cctv_interview_with_matt_crampton/</link><description>CCTV Interview with Matt Crampton On Apr 12, 2013 I spoke with anchor Michelle Makori on CCTV on how PC companies will survive in a business environment shifting toward mobile devices. CCTV Interview with Matt Crampton Download Interview Video File size: 40.6 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/cctv_interview_with_matt_crampton/</guid></item><item><title>CBS Pulse Interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/cbs_pulse_article/</link><description>CBS Pulse Interview with Matt Crampton On April 11, 2016, I published an article on CBS Pulse about on-demand workers and the Gig Economy. Read Article The interiew is pasted below as well... The Rising Gig Professional By Matt Crampton of Gigwalk In recent months, news of on-demand workers undertaking jobs that have low barriers to entry has dominated the headlines as high-profile lawsuits against Uber, Lyft, GrubHub, Washio, Handy and others continue to pile up. All are charging such companies with miscategorizing their workers as independent contractors instead of employees, an important distinction because contractors by law have greater freedom and flexibility than employees without the same legal and financial protections. Behind the media spotlight, however, there’s another trend quietly emerging, one that suggests that on-demand work technologies have more to offer than just right-time right-place labor. In fact, a survey conducted by Gigwalk found that the highest percentag...</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/cbs_pulse_article/</guid></item><item><title>8th and Walton show interview with Matt Crampton</title><link>https://www.mattcrampton.com/blog/8th_walton_interview/</link><description>8th and Walton show interview with Matt Crampton On 10/26/2017 I did an interview with the 8th and Walton show talking about Gigwalk and the larger economy 8th and Walton show interview with Matt Crampton Download Interview Video File size: 84.9 MiB</description><author>MattCrampton.com</author><pubDate>Thu, 26 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/8th_walton_interview/</guid></item><item><title>Eh, Docker, we have a problem here…</title><link>https://lambdaland.org/posts/2017-10-26-eh-blog-we-have-a-problem-here/</link><description>&lt;p&gt;&lt;em&gt;Quick note for those who don’t know about Docker:&lt;/em&gt; &lt;a class="link-external" href="https://www.docker.com/what-docker" rel="external"&gt;Docker&lt;/a&gt; is a program that lets me take packaged-up programs (called &lt;em&gt;images&lt;/em&gt; or &lt;em&gt;containers&lt;/em&gt;) and run them without having to worry much about dependencies.&lt;/p&gt;
&lt;p&gt;Today I decided to upgrade my version of &lt;a class="link-external" href="https://ghost.org/" rel="external"&gt;Ghost Blog&lt;/a&gt;. I’m using the &lt;a class="link-external" href="https://hub.docker.com/_/ghost/" rel="external"&gt;Docker image&lt;/a&gt; on a Digital Ocean droplet. Updating should be simple, I thought. I would take down the blog then spin it back up again after pulling down the latest Docker image. I ran &lt;code&gt;docker stop ghost-blog&lt;/code&gt;, removed the container with &lt;code&gt;docker rm ghost-blog&lt;/code&gt; then ran &lt;code&gt;docker pull ghost:latest&lt;/code&gt;. The container came down without a problem.&lt;/p&gt;
&lt;p&gt;Then the trouble began.&lt;/p&gt;
&lt;p&gt;I tried restarting the image:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;docker run -d --name ghost-blog -p 80:2368 -v /home/ghost/blog-data:/var/lib/ghost/content ghost&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But when I ran &lt;code&gt;docker ps&lt;/code&gt;, no docker containers were running. I tried looking at the log of the &lt;code&gt;ghost-blog&lt;/code&gt; container and was greeted with this message:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;tar: /var/lib/ghost/content.orig: Cannot open: No such file or directory&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;tar: Error is not recoverable: exiting now&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;tar: This does not look like a tar archive&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;tar: Exiting with failure status due to previous errors&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hhmmm… I tried creating &lt;code&gt;/var/lib/ghost/content.orig&lt;/code&gt;, but that didn’t help. I then copied my &lt;code&gt;blog-data/&lt;/code&gt; folder, blew the old folder away, then tried running again, but to no avail.&lt;/p&gt;
&lt;p&gt;I was out of ideas, so I decided to inquire at the great oracle of &lt;a class="link-external" href="https://duckduckgo.com/?q=docker+ghost+tar%3A+%2Fvar%2Flib%2Fghost%2Fcontent.orig%3A+Cannot+open%3A+No+such+file+or+directory+tar%3A+Error+is+not+recoverable%3A+exiting+now+tar%3A+This+does+not+look+like+a+tar+archive+tar%3A+Exiting+with+failure+status+due+to+previous+errors&amp;amp;bext=msl&amp;amp;atb=v43-6_s&amp;amp;ia=web" rel="external"&gt;DuckDuckGo&lt;/a&gt;. The &lt;a class="link-external" href="https://github.com/docker-library/ghost/issues/69" rel="external"&gt;first result&lt;/a&gt; was this lovely issue on GitHub that covered &lt;em&gt;exactly&lt;/em&gt; the problem I was facing.&lt;/p&gt;
&lt;p&gt;I created the directory specified and was able to fire up the docker container without a problem. I think I must have made an incompatible upgrade. ¯_(ツ)_/¯&lt;/p&gt;
&lt;h2 id="backup-woes"&gt;Backup Woes&lt;/h2&gt;
&lt;p&gt;Running around as the root user of a system is always dangerous. I was painfully reminded of that today when I accidentally deleted my backup folder instead of moving its contents to the original location. 🤦🏻‍♂️Oops.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fortunately&lt;/em&gt;, I had made another backup of all my content saved as a JSON file on my laptop. I fired up the docker container, opened to the website in a web browser, and imported all my old files. Day saved. 😌&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unfortunately&lt;/em&gt; I lost all my configurations. Not that there was a &lt;em&gt;lot&lt;/em&gt;, but I did loose the Disqus integration as well as some settings for me as an administrator. Alas. I’ll fix the comments sometime later. Probably &lt;em&gt;after&lt;/em&gt; midterms…&lt;/p&gt;
&lt;p&gt;So, lessons: make backups. Then don’t delete the backups.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;am&lt;/em&gt; enjoying the Ghost blog. It’s pretty minimal and doesn’t get in my way. I just wish I had been a little more careful today.&lt;/p&gt;</description><author>Lambda Land</author><pubDate>Thu, 26 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2017-10-26-eh-blog-we-have-a-problem-here/</guid></item><item><title>Namaste India</title><link>https://codeexplainer.wordpress.com/2017/10/25/namaste-india/</link><description>This obfuscated piece of C code prints the map of India to the standard output. Who wrote this code? The author is unknown.  I have found the code on Quora while searching the web for interesting code snippets.  (If you &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2017/10/25/namaste-india/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Wed, 25 Oct 2017 23:10:09 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2017/10/25/namaste-india/</guid></item><item><title>How I Plan to Learn Rust</title><link>https://peterlyons.com/problog/2017/10/how-i-plan-to-learn-rust/</link><description>&lt;p&gt;So the week after next I start the Winter 1 2017 half-batch of &lt;a href="https://www.recurse.com/"&gt;the Recurse Center&lt;/a&gt;. My primary project will be learning rust and systems programming. My secondary project will be some SQL modeling and reporting stuff.&lt;/p&gt;
&lt;p&gt;Here's my plan to learn rust.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✓ Read &lt;a href="https://doc.rust-lang.org/stable/book/second-edition"&gt;The Rust Programming Language&lt;/a&gt; Book, 2nd edition
&lt;ul&gt;
&lt;li&gt;✓ Do all &lt;a href="https://github.com/focusaurus/rust-basics"&gt;exercises&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;✓ Watch any interesting conference videos from the most recent Rust Conf&lt;/li&gt;
&lt;li&gt;✓ Implement &lt;a href="https://github.com/focusaurus/rust-basics/tree/master/hex_dump"&gt;the unix hexdump utility in rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;✓Listen to &lt;a href="http://www.newrustacean.com/"&gt;The New Rustacean Podcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;✓ Listen to &lt;a href="https://request-for-explanation.github.io/podcast/"&gt;The Request for Explanation Podcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Read and do all activities in &lt;a href="https://rustbyexample.com/custom_types.html"&gt;Rust by Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Do the &lt;a href="https://github.com/carols10cents/rustlings"&gt;rustlings&lt;/a&gt; exercises&lt;/li&gt;
&lt;li&gt;Maybe read &lt;a href="https://www.safaribooksonline.com/library/view/programming-rust/9781491927274/titlepage01.html"&gt;Programming Rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Maybe &lt;a href="https://hackernoon.com/learn-blockchains-by-building-one-117428612f46"&gt;build a simple blockchain in rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Read &lt;a href="https://github.com/ayasin/rust-talk"&gt;High Performance JavaScript with Rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Do some embedded work via &lt;a href="https://japaric.github.io/discovery/"&gt;Discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Watch the &lt;a href="http://intorust.com/"&gt;Into Rust&lt;/a&gt; screencasts&lt;/li&gt;
&lt;li&gt;Do &lt;a href="http://cglab.ca/~abeinges/blah/too-many-lists/book/"&gt;Learning Rust With Entirely Too Many Linked Lists&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately my final project type thing might be a crypto helper program in the spirit of &lt;a href="https://github.com/elastic/tealess"&gt;tealess&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Got any suggestions for me? Leave a disqus comment below or tweet me or whatever.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 25 Oct 2017 19:04:24 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/10/how-i-plan-to-learn-rust/</guid></item><item><title>Remove an element from an Array in Javascript</title><link>https://jmthornton.net/blog/p/array-removeelement</link><description>A new Javascript function to remove any element from an Array in an intuitive way, with support for negative indexing.</description><author>Blog by Jade Michael Thornton</author><pubDate>Wed, 25 Oct 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/array-removeelement</guid></item><item><title>Web Mining: is that bad?</title><link>https://danielpecos.com/2017/10/25/web-mining-is-that-bad/</link><description>&lt;p&gt;&lt;img alt="Cryptocurrency Mining" class="size-medium alignleft" height="218" src="https://danielpecos.com/assets/2017/10/cryptocurrency-mining.jpeg" width="300" /&gt;There has been a lot of noise around &lt;a href="https://en.wikipedia.org/wiki/Monero_(cryptocurrency)"&gt;Monero&lt;/a&gt; and &lt;a href="https://coinhive.com/"&gt;Coinhive&lt;/a&gt; lately, or web mining in general, and don’t quite agree with most of what I’m hearing.&lt;/p&gt;
&lt;p&gt;It all started with &lt;a href="https://thepiratebay.org/"&gt;The Pirate Bay&lt;/a&gt; adding a web mining script to their site, so whenever you’d visit them, your CPU would be used to mine some Monero for them. That was made without any notice to the user, just “stealing” their power. That was probably the best ad Coinhive (which is the service hosting the mining script and providing the required infrastructure to mine Monero) could get, as it appeared all over the news (even some local newspaper got noticed). And, as it was to expect, plenty of sites added the same piece of script so they could also benefit from their users base.&lt;/p&gt;
&lt;p&gt;But something really interesting followed to this: most ad-block extensions started to block Coinhive, frustrating all the efforts of these people getting reach.&lt;/p&gt;
&lt;p&gt;Let’s stop for a second and analyze what happened:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Website owners use their users’ computers to mine (earn)  some (crypto-) money.&lt;/li&gt;
&lt;li&gt;Ad-blockers think that’s an abuse and not legitimate and start blocking that mining.&lt;/li&gt;
&lt;li&gt;Lots of news about how evil these people are written all over the internet.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Really? So I, as a content creator, &lt;strong&gt;willingly giving that content to the community&lt;/strong&gt;, am an evil person for &lt;strong&gt;trying to monetize that content / time&lt;/strong&gt; with the cost of the electricity the user spends while being on my site. Because everything on Internet must be free of cost, and those evil people trying, not to live from it, but just to get a little money for their time, should be ashamed of even trying.&lt;/p&gt;
&lt;img alt="Mining Blockers" class="size-medium alignright" height="188" src="https://danielpecos.com/assets/2017/10/miner-blockers.png" width="300" /&gt;
&lt;p&gt;Well, a similar thing happened with ads, and when sites started abusing of them, making the user experience a pain, is when ad blockers started flourishing, and well-behaved content creators getting their incomes cut. And the same should happen to those who mine under the hood, without the user approval, or those who mine using too much CPU time, making user’s computer unusable.&lt;/p&gt;
&lt;p&gt;But we have not given yet the chance to make of web mining a legitimate way to monetize content. And why? Probably not because you’re abusing your users CPU or because users are not aware, &lt;strong&gt;but because you’re making money without taking into account Adsense or other gigantic ad platforms that could run into serious problems if this becomes a trend.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Why otherwise would &lt;a href="https://www.bleepingcomputer.com/news/google/google-chrome-may-add-a-permission-to-stop-in-browser-cryptocurrency-miners/"&gt;Chrome’s team have worried so much and so fast&lt;/a&gt; about this, proposing even the &lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=766068#c13"&gt;creation of a throttle down inside the browser itself&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I don’t think this recent noise is all about mining itself but about those ad platforms losing their control over Internet content monetization&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: as you would probably have noticed when loaded this post, a popup appeared asking for your permission to mine using your CPU. It’s totally up to you to decide if should get some of your time or not.&lt;/em&gt;&lt;/p&gt;
&lt;img alt="Coinhive" class="aligncenter size-medium" height="300" src="https://danielpecos.com/assets/2017/10/Screenshot_20171025_111416.png" width="274" /&gt;</description><author>GeekWare - Daniel Pecos Martínez</author><pubDate>Wed, 25 Oct 2017 11:20:46 GMT</pubDate><guid isPermaLink="true">https://danielpecos.com/2017/10/25/web-mining-is-that-bad/</guid></item><item><title>A suggestion for on-demand public transit, from Fiumicino to Los Angeles</title><link>https://stop.zona-m.net/2017/10/a-suggestion-for-on-demand-public-transit-from-fiumicino-to-los-angeles/</link><description>&lt;p&gt;Five years ago I &lt;a href="https://stop.zona-m.net/2017/02/that-digital-divide-in-fiumicino-airport"&gt;wrote&lt;/a&gt; that &lt;strong&gt;all&lt;/strong&gt; of precarious workers of the Fiumicino airport should partner and tell, to the many private bus companies that move tourists in and out of the same airport:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 25 Oct 2017 11:10:34 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/a-suggestion-for-on-demand-public-transit-from-fiumicino-to-los-angeles/</guid></item><item><title>Links - October 25, 2017</title><link>https://faingezicht.com/links/2017/10/25/links/</link><description/><author>Avy Faingezicht</author><pubDate>Wed, 25 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/10/25/links/</guid></item><item><title>Applying syntax in Sublime based on the first file line</title><link>https://smcleod.net/2017/10/applying-syntax-in-sublime-based-on-the-first-file-line/</link><description>&lt;p&gt;In vim, you can add a comment at the top of files to set the syntax, e.g.:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# vim: syntax=ruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In SublimeText there are &lt;em&gt;many&lt;/em&gt; ways to detect syntax, one interesting approach I&amp;rsquo;ve recently found useful is to match on the top line in the file.
For example, with Puppet there is a file called &lt;code&gt;Puppetfile&lt;/code&gt;, it has no extension but it&amp;rsquo;s really Ruby syntax, so it&amp;rsquo;s useful to add linting incase you
miss something simple like a &lt;code&gt;,&lt;/code&gt; and break deployments.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Wed, 25 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/10/applying-syntax-in-sublime-based-on-the-first-file-line/</guid></item><item><title>I’ve just found your blog, and it’s inspirational to see someone who works so freely and happily. I’m currently a CS student, and I’d like to know what it is that you did to succeed, other than passing all the exams.</title><link>https://yieldthought.com/post/166746818675</link><description>&lt;p&gt;I got very lucky - my final year project supervisor started a company and asked me to join him. Fifteen years later we were acquired by Arm! Taking the advice of people who got lucky is like taking the advice of lottery winners. “Everyone said I was crazy but I kept on believing!”&lt;/p&gt;&lt;p&gt;In terms of the blog: the best writing advice I ever got was to spend ten minutes every day writing non-stop. It doesn’t matter if you write “I don’t know what to write I don’t know what to write” over and over, just get into the habit. I did not follow this advice, which is probably why there are so few blog posts. YMMV!&lt;/p&gt;&lt;p&gt;My advice for a CS student today: make sure you are training neural networks (Keras my only recommended framework). A lot of interesting problems will be solved with AI soon.&lt;/p&gt;</description><author>Yield Thought</author><pubDate>Tue, 24 Oct 2017 17:49:03 GMT</pubDate><guid isPermaLink="true">https://yieldthought.com/post/166746818675</guid></item><item><title>Do you still work from a mobile device after your new laptop has arrived? I think about going iPad for coding on the go, Mac Mini at the desk. Can’t afford to waste money on a laptop which I only use 5–10% of the time, but don’t know if my work will be doable.</title><link>https://yieldthought.com/post/166746724250</link><description>&lt;p&gt;These days I work on a company MacBook Pro - I don’t have the flexibility to do work on a Linode outside the company firewall now I’m part of a megacorp! I’m also playing around with mobile prototype boards and various Raspberry Pi versions, so the mobile iPad life doesn’t fit my day-to-day work very well.&lt;/p&gt;</description><author>Yield Thought</author><pubDate>Tue, 24 Oct 2017 17:45:09 GMT</pubDate><guid isPermaLink="true">https://yieldthought.com/post/166746724250</guid></item><item><title>Hey I wanted to give this a whirl myself and wondered what you did security-wise? I was using plain ssh, but my sysops friend recommended setting up a vpn so I can firewall every other port.</title><link>https://yieldthought.com/post/166746638100</link><description>&lt;p&gt;I use UFW to firewall all the ports on my Linode and redirect SSH to a specific non-standard port. I also configured a service (I forget which) to blacklist repeated login / port-scan attempts. Hasn’t been a problem so far!&lt;/p&gt;</description><author>Yield Thought</author><pubDate>Tue, 24 Oct 2017 17:41:19 GMT</pubDate><guid isPermaLink="true">https://yieldthought.com/post/166746638100</guid></item><item><title>6 First Aid Items You Need On Your Next Camping Trip</title><link>https://www.mattcrampton.com/blog/6_first_aid_items_you_need_on_your_next_camping_trip/</link><description>A camping trip can be quickly ruined if there's a medical issue with someone in your group and noone remembered to bring along a properly stocked first aid kit. Here's a list of items you need to remember to bring the next time you're on an excursion... Adventure Medical Kits Ultralight &amp;amp; Watertight .5 KT TAPE PRO Kinesiology Sports Tape The most advanced kinesiology tape, made from 100% synthetic fabric to last far longer than other brands. Lightweight, latex free, comfortable, provides both support &amp; mobility, and includes safety reflective print &amp; carry case.</description><author>MattCrampton.com</author><pubDate>Tue, 24 Oct 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/6_first_aid_items_you_need_on_your_next_camping_trip/</guid></item><item><title>The Long Game</title><link>https://bastibe.de/2017-10-24-the-long-game.html</link><description>&lt;p&gt;Here's a thing I do: I write open source libraries that solve my problems. &lt;em&gt;Bad&lt;/em&gt; libraries. And then, over the course of a year or two, I slowly improve them, until they are not so bad any more.&lt;/p&gt;
&lt;p&gt;I have gone through this pattern a few times now. &lt;a href="https://github.com/bastibe/PySoundFile"&gt;SoundFile&lt;/a&gt; started out buggy and slow. &lt;a href="https://github.com/bastibe/transplant"&gt;Transplant&lt;/a&gt; crashed and froze very often. &lt;a href="https://github.com/bastibe/org-journal"&gt;Org-Journal&lt;/a&gt; deleted journal entries every now and then. But then users found errors, and errors were fixed. And slowly, over time, these libraries transformed from buggy prototypes into dependable tools. After a year or so, I saw Github Issues gradually drying up, and feedback changing from &amp;quot;X is broken&amp;quot; to &amp;quot;How can I do X?&amp;quot;. It is an oddly gratifying process.&lt;/p&gt;
&lt;p&gt;Interestingly though, I rarely hear people talking about this, that building a thing is only the beginning, and the meat of open source development is sticking with it for a long time, and gradually, slowly, weeding out the bugs. All great open source libraries I know evolved this way, yet it is rarely written about.&lt;/p&gt;
&lt;p&gt;Playing the long game means anticipating and managing the amount of maintenance I am going to do on a project. When releasing a new library, the first few months and users will shake out bugs, and create work for the maintainers. This can be a dangerous source of stress and anxiety. I've had my brush with burnout in the past, and my only defense to this is to be honest about my availability. Often, this means stating outright that I probably won't have the time to work on a thing.&lt;/p&gt;
&lt;p&gt;However, I have also learned that it is OK to defer issues to the future. There have been many problems that I didn't have the time to address when they first came up, but &lt;em&gt;did&lt;/em&gt; address a few months later, probably in response to a separate bug report. Important problems have a way of getting fixed eventually. Other times, a solution just takes a long time to mature. There have been multiple issues that lay dormant for months until I stumbled upon a good solution.&lt;/p&gt;
&lt;p&gt;And good solutions are important for open source software: If a bug fix adds too much complexity, it will inevitably lead to &lt;em&gt;more&lt;/em&gt; bugs. This can easily snowball into a situation where each hour I invest into a project creates &lt;em&gt;more hours&lt;/em&gt; of future maintenance burden. A situation like this feels hopeless and terrible. It feels like work. It is therefore important for my sanity to control the complexity of my projects, even if that means not adding features or not addressing problems. Open source development is not beholden to the dollar sign, and gives you the freedom to do it &lt;em&gt;right&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is not universally understood by programmers or users. And it doesn't just involve technical questions: Some users have expected me to provide commercial-grade support, and got surprisingly unpleasant when I didn't. But it is crucial to realize that publishing open source software &lt;em&gt;does not imply an obligation to fix every issue right now&lt;/em&gt;. Quite on the contrary, many open source developers necessarily work on their own schedule, and part of the enjoyment of open source development is derived from this exact freedom!&lt;/p&gt;
&lt;p&gt;At this point, my Github lists a bunch of open source projects. Some of them have gotten attention, which lead to bug reports, and, over time, let them grow to maturity. Some turned out to be &lt;a href="https://github.com/bastibe/annotate.el"&gt;useful&lt;/a&gt; &lt;a href="https://github.com/bastibe/twilight"&gt;to&lt;/a&gt; &lt;a href="https://github.com/bastibe/org-static-blog"&gt;me&lt;/a&gt;, but not to others. Some are useful &lt;a href="https://github.com/bastibe/Violinplot-Matlab"&gt;to&lt;/a&gt; &lt;a href="https://github.com/bastibe/lunatic-python"&gt;others&lt;/a&gt;, but not to me. Some turned out to be not useful &lt;a href="https://github.com/bastibe/MatlabCodeAnalyzer"&gt;at all&lt;/a&gt;, and are now largely abandoned. And some of them, like &lt;a href="https://github.com/bastibe/RunForrest"&gt;RunForrest&lt;/a&gt; and &lt;a href="https://github.com/bastibe/SoundCard"&gt;SoundCard&lt;/a&gt;, are still new and raw and terrible, but will mature over time.&lt;/p&gt;
&lt;p&gt;That's a thing I do: I write open source libraries. &lt;em&gt;Good&lt;/em&gt; libraries, but as a &lt;a href="https://en.wikiquote.org/wiki/Piet_Hein"&gt;wise man&lt;/a&gt; once said &amp;quot;When you feel how depressingly / slowly you climb, / it's well to remember that / Things Take Time&amp;quot;. Working on open source grants you this freedom, and is joyful for it.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Tue, 24 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-10-24-the-long-game.html</guid></item><item><title>Animate between two react components</title><link>https://muffinman.io/blog/animate-between-two-react-components/</link><description>&lt;article class="article"&gt;&lt;p&gt;Just a quick proof of concept I made for transitioning between two react components.
It animates height (of the parent) and fades components into each other.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;componentWillReceiveProps&lt;/code&gt; it checks if &lt;code&gt;children&lt;/code&gt; prop has changed.
When that happens, it will save currently rendered children and the height of the wrapper.&lt;/p&gt;
&lt;p&gt;Then it will animate wrapper&amp;#x27;s height to a new component&amp;#x27;s height,
fade out previous component and fade in the new one.
Finally when animation is finished it will reset wrapper&amp;#x27;s height to &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I might release it as a standalone npm component, but it needs some polishing before I do so.
If you make use out of it, please share in the comments.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Tue, 24 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/animate-between-two-react-components/</guid></item><item><title>Running tests and getting coverage reports on server deployment in SnailLife</title><link>https://liza.io/running-tests-and-getting-coverage-reports-on-server-deployment-in-snaillife/</link><description>&lt;p&gt;Yesterday I added tests to server deployment in my &lt;code&gt;deployServer.sh&lt;/code&gt; script:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo "Running tests"
cd ../../server/lib

set -e
echo "mode: set" &amp;gt; allcoverage.out

for d in $(go list ./... | grep -v vendor); do
    parentdir=`dirname "$d"`
    subdir=`basename "$d"`
    echo "subdir: " $subdir
    if [[ $subdir == "tests" ]]; then
        go test -cover -coverpkg=$parentdir -coverprofile=profile.out $d
    else
        go test -cover -coverprofile=profile.out $d
    fi

    if [ -f profile.out ]; then
        tail -n+2 profile.out &amp;gt;&amp;gt; allcoverage.out
        rm profile.out
    fi
done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Basically this goes into the root where all of my server packages live. Then for each found package we get the subdirectory name and the full path of the parent directory. If the subdirectory is named &amp;ldquo;tests&amp;rdquo; (most of my tests are in packages under the package I&amp;rsquo;m actually testing), we run &lt;code&gt;go test -cover&lt;/code&gt; with &lt;code&gt;-coverpkg&lt;/code&gt; specified as the parent dir of the test dir. Otherwise we do not specify &lt;code&gt;-coverpkg&lt;/code&gt; because it is in the same directory as the test.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Mon, 23 Oct 2017 19:56:38 GMT</pubDate><guid isPermaLink="true">https://liza.io/running-tests-and-getting-coverage-reports-on-server-deployment-in-snaillife/</guid></item><item><title>How Danish students may become savvy Internet users</title><link>https://stop.zona-m.net/2017/10/how-danish-students-may-become-savvy-internet-users/</link><description>&lt;p&gt;It looks like Denmark is &lt;a href="https://geekreply.com/technology/2017/10/20/denmark-students-allow-teachers-see-laptops-contents"&gt;discussing a proposal &amp;ldquo;to encourages students to grant schools access to their personal laptops&amp;rdquo;&lt;/a&gt; in order to avoid cheating at exams. I like it because it is so &lt;strong&gt;DUMB&lt;/strong&gt; that it may achieve a very positive effect anyway, albeit one totally unforeseen by its authors.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 23 Oct 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/how-danish-students-may-become-savvy-internet-users/</guid></item><item><title>How to build waifu2x command-line version on osx</title><link>http://blog.pythonaro.com/2017/07/how-to-build-waifu2x-command-line.html</link><description>&lt;div&gt;&lt;b&gt;UPDATE 23/10/2017:&lt;/b&gt; recent changes seem to be incompatible with clang. I have updated the steps below to check out the last commit that is known as working. &lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://waifu2x.udp.jp/index.html" target="_blank"&gt;Waifu2x&lt;/a&gt; is a popular image converter backed by neural-network models, typically used to upscale images from &lt;i&gt;anime&lt;/i&gt;. The various web versions are easy to use but typically don't allow for batch-processing, because it's a relatively intensive operation. However, there is a command-line version that is fairly easy to compile on Windows and Linux. OSX support was notably absent... until now.&lt;/div&gt;
&lt;div&gt;
These are the steps required to get it working on Mac:
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;brew tap science &amp;amp;&amp;amp; brew install opencv3&lt;/code&gt;&lt;br /&gt;(if you don't have &lt;a href="https://brew.sh/" target="_blank"&gt;Homebrew&lt;/a&gt;, go install it now - it's wonderful)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git clone https://github.com/DeadSix27/waifu2x-converter-cpp.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd waifu2x-converter-cpp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git checkout d69313040b0784662465fb1d2eca81a2b1ebccb2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cmake -DOVERRIDE_OPENCV=1 -DOPENCV_PREFIX=/usr/local/Cellar/opencv3/&amp;lt;your version here&amp;gt; .&lt;/code&gt; (remember the dot at the end!)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make -j4&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
At this point, you have the executable &lt;code&gt;waifu2x-converter-cpp&lt;/code&gt; in the directory; you can &lt;code&gt;make install&lt;/code&gt; if you really want to (I prefer to keep custom stuff in my home dir). To test it's working, the following command should return info on your system:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;./waifu2x-converter-cpp --list-processor&lt;/code&gt;
&lt;/div&gt;
&lt;br /&gt;
If you need some images to test, &lt;a href="https://imgur.com/gallery/dSpHk" target="_blank"&gt;here&lt;/a&gt; you can get quite a few stills from the gorgeous 5 Centimeters Per Second. Note: you might have to rename the folder "models_rgb" into "models" before converting.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
BONUS: Qt GUI&lt;/h3&gt;
&lt;div&gt;
If you hate the command-line, there is &lt;a href="https://github.com/toyg/waifu2x-converter-qt" target="_blank"&gt;a simple QT wrapper&lt;/a&gt;. To compile it you will need Qt-Creator and Qt installed and configured. This used to be very complicated, but both items have now been packaged for Homebrew so it's all awesomely simple (well, compared to what it was, at least). Note that you still have to do the steps above - the wrapper needs the waifu2x executable to be already compiled.&lt;/div&gt;
&lt;br /&gt;
&lt;h4&gt;
Install and configure Qt and Qt-Creator&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;brew install qt &amp;amp;&amp;amp; brew cask install qt-creator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Launch &lt;i&gt;Qt Creator &lt;/i&gt;from Launchpad, then go to &lt;i&gt;Qt Creator -&amp;gt; Preferences&lt;/i&gt; (Command + ,)&lt;/li&gt;
&lt;li&gt;Select &lt;i&gt;Build &amp;amp; Run&lt;/i&gt;, then the &lt;i&gt;Qt Versions&lt;/i&gt; tab&lt;/li&gt;
&lt;li&gt;Click on &lt;i&gt;Add...&lt;/i&gt; and select “Macintosh HD”&lt;/li&gt;
&lt;li&gt;Press Command + Shift + . to show hidden directories&lt;/li&gt;
&lt;li&gt;select &lt;code&gt;/usr/local/Cellar/qt5/&amp;lt;your version&amp;gt;/bin/qmake&lt;/code&gt; then OK and OK again to close the Preferences window&lt;/li&gt;
&lt;li&gt;Reopen &lt;i&gt;Preferences -&amp;gt; Build &amp;amp; Run&lt;/i&gt;, select the Kits tab and click Add&lt;/li&gt;
&lt;li&gt;Set the following options:
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;Name&lt;/i&gt; to something like "Qt CLang Desktop"&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Both &lt;i&gt;Compiler&lt;/i&gt; options to Clang X86 64bit&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Qt Version&lt;/i&gt; to the version you just created&lt;/li&gt;
&lt;li&gt;Click on &lt;i&gt;Make Default&lt;/i&gt; then OK to close Preferences.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
Compile waifu2x-converter-qt&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git clone https://github.com/toyg/waifu2x-converter-qt.git&lt;/code&gt; (&lt;a href="https://github.com/khws4v1/waifu2x-converter-qt"&gt;the original repo&lt;/a&gt; looks abandoned, so I forked it and tweaked it a bit)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd waifu-converter-qt &amp;amp;&amp;amp; open waifu2x-converter-qt.pro&lt;/code&gt; (this should open Qt Creator; if it doesn't, launch it manually and &lt;i&gt;File -&amp;gt; Open Project&lt;/i&gt; -&amp;gt; select the .pro file).&lt;/li&gt;
&lt;li&gt;Select &lt;i&gt;Build -&amp;gt; Run&lt;/i&gt; (or Command + R). The resulting .app bundle should now be in a folder called &lt;code&gt;build-waifu2x-converter-qt-&amp;lt;something something&amp;gt;&lt;/code&gt;, just beside your main project folder.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
When you first launch the GUI, you should probably go to Preferences and set the path to your waifu2x-converter-cpp executable.&lt;/div&gt;</description><author>Subclassed</author><pubDate>Mon, 23 Oct 2017 05:49:54 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2017/07/how-to-build-waifu2x-command-line.html</guid></item><item><title>About</title><link>https://bytesizetheories.com/about/</link><description>This website contains theories and thoughts that I have theorized and thought.</description><author>Byte Size Theories</author><pubDate>Mon, 23 Oct 2017 02:19:38 GMT</pubDate><guid isPermaLink="true">https://bytesizetheories.com/about/</guid></item><item><title>First thought</title><link>https://bytesizetheories.com/posts/first-post/</link><description>Hello everybody 🔗For as long as I can remember, my family and friends have been telling me
 &amp;ldquo;Your theories are ridiculous, and wrong&amp;rdquo;.
 So I decided to share them more broadly.</description><author>Byte Size Theories</author><pubDate>Sun, 22 Oct 2017 21:54:44 GMT</pubDate><guid isPermaLink="true">https://bytesizetheories.com/posts/first-post/</guid></item><item><title>Logos and Artworks in the Unix World</title><link>https://venam.net/blog/unix/2017/10/22/logos-and-artworks-on-unix.html</link><description>Logos and artworks in the Unix world, where do those come from.  We'll try to analyse a bunch of popular Unix mascots and logos.  Throughout my research I could distinct two groups of mascots and logos. Even though it's not fun to have a binomial vision of the world, black and white, but this is what I found and this is mostly what it is.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 22 Oct 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/10/22/logos-and-artworks-on-unix.html</guid></item><item><title>Static Analysis: It's Simply Critical</title><link>https://donatstudios.com/StaticAnalysis</link><description>&lt;p&gt;I am someone who spends large portions of their time working in weakly typed languages. Namely, PHP and JavaScript. I argue that static analysis is a &lt;strong&gt;must-have&lt;/strong&gt; when working with any weakly typed language. It is nearly impossible to make reliable code without it. &lt;/p&gt;
&lt;p&gt;Static analysis makes up for the missing type system and allows you to scale.&lt;/p&gt;
&lt;p&gt;I recently got in an argument with another developer over static analysis. It's been an ongoing point of contention. He was angry that code that &lt;em&gt;works fine&lt;/em&gt; but didn't document its undetectable return types was failing CI. He argued that if the code works, it should pass. He argued that if the code works, it is &amp;quot;correct&amp;quot;.&lt;/p&gt;
&lt;p&gt;I put forward the exact opposite position. Code that &lt;em&gt;works&lt;/em&gt; but doesn't &lt;em&gt;statically analyze&lt;/em&gt; is incorrect. Code that is &lt;strong&gt;correct&lt;/strong&gt; has no potential of runtime error. &lt;/p&gt;
&lt;p&gt;My intentions are not only to sell you on the idea that you should be statically analyzing your code, but to convince you that it is fundamental to responsible reliable development.&lt;/p&gt;
&lt;p&gt;Humans are fallible; code written by humans doubly so. By it's very nature that code is broken until &lt;strong&gt;proven otherwise.&lt;/strong&gt; If it cannot be statically analyzed, it &lt;strong&gt;cannot be&lt;/strong&gt; &lt;strong&gt;proven&lt;/strong&gt; correct.&lt;/p&gt;
&lt;p&gt;If code &lt;strong&gt;runs&lt;/strong&gt; as expected, this only proves it correct in the &lt;em&gt;limited scope&lt;/em&gt; it's been ran it within. Be that ones, tens or even hundreds of thousands of parameter combinations, it's always limited. There therefore &lt;strong&gt;must&lt;/strong&gt; be zero expectation of it continuing to work.&lt;/p&gt;
&lt;p&gt;To the contrary, if code statically analyzes unerring, it will run without runtime error in &lt;strong&gt;all&lt;/strong&gt; &lt;strong&gt;cases&lt;/strong&gt;, save a failure of the analyzer. This code &lt;strong&gt;is proven&lt;/strong&gt;. This code is &lt;strong&gt;correct&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Code which &amp;quot;works&amp;quot; does nothing to prove that it's used as you expect. In particular elsewhere within the project. It does nothing to prove it will remain correctly used in all cases in the future.&lt;/p&gt;
&lt;p&gt;I know what you are thinking &amp;quot;But… but… my code runs correctly within my expected domain&amp;quot;, and that's fine. That is what's expected of it. But throw exceptions if it happen it doesn't know how to handle, things that creep outside the expected domain. It lets the future developers, the analyzer, and the program itself know the intended domain and when it steps outside it. &lt;/p&gt;
&lt;p&gt;No amount of fuzz testing can account for another developer doing something you never expected.&lt;/p&gt;
&lt;p&gt;To give a trivial but near real life example, consider the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function getUserById( userId ) {
    if(userId &amp;gt; 0) {
        return new User($userId);
    }

    return null;
}

var user = getUserById( input.value );
console.log( "Hello userId: " + user.getId() );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code may work throughout &lt;strong&gt;all&lt;/strong&gt; your testing. Every place you use it, every time you try it, everything your application throws at it - success. &lt;/p&gt;
&lt;p&gt;This code &lt;strong&gt;works&lt;/strong&gt;, and yet this code &lt;strong&gt;is broken.&lt;/strong&gt; This code does not handle the potential &lt;strong&gt;null,&lt;/strong&gt; and has the potential to trigger a runtime error. This code has the capability of a runtime error, and is therefore &lt;strong&gt;incorrect&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Making this code &lt;strong&gt;correct&lt;/strong&gt; would be as simple as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var user = getUserById( input.value );

if(!user instanceof User) {
    throw new Error("User not found");
}

console.log( "Hello userId: " + user.getId() );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An Exception, as opposed to a runtime error, is something the code and coder anticipates. It's an easy way to show you've thought about the domain of your code. Even unhandled, it's clear the developer considered the possibility. It's easily recoverable. Throwing an exception here is &lt;strong&gt;correct&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Obviously you'd probably want to handle that Error in the example somewhere, but that's outside the scope of this writing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The trivial case above is reasonably obvious and easy to spot. Let's instead imagine the function to get a user is deep in your codebase. While we are at it, let's also say that the logical &lt;code&gt;User|null&lt;/code&gt; union we've created gets passed around. Passed several levels deep, rather than using it immediately where it's fetched. It rapidly becomes &lt;em&gt;much&lt;/em&gt; less obvious, nigh impossible, to notice that there is an issue. A call 8 methods deep has no idea it might be receiving a null. This is &lt;strong&gt;exactly&lt;/strong&gt; the kind of thing a static analysis is for.&lt;/p&gt;
&lt;p&gt;A static analyzer knows the full scope and range of possible values. It is able to pinpoint problems a human fails to notice. Noting all function calls within the scope of a project and knowing all possible.&lt;/p&gt;
&lt;p&gt;All this withstanding, static analysis cannot prove the logic is correct. That's not what static analysis is for. Unit tests and other testing prove that. Static analysis proves that the code itself executes free of unhandled &lt;strong&gt;runtime errors&lt;/strong&gt;. It &lt;strong&gt;is&lt;/strong&gt; the &lt;strong&gt;type checker your language forgot&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Arguable the better solution is to switch to a type safe language; one with compile time type checks and ideally union types. That's not always an option for most people though, consider the recent meteoric growth of JavaScript. &lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; is without a doubt the best option for JavaScript. I highly recommend it — consider it static analysis on steroids. It's JavaScript with the addition of strong typing. There's no reason to be writing straight JavaScript anymore. TypeScript is really a wonderful all in one solution.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; is a neat alternative but a completely different paradigm. While it compiles to JavaScript, it's completely foreign and more of an all-in situation. It borrows much of its syntax from Haskell, and offers the aforementioned union types. &lt;/p&gt;
&lt;p&gt;For PHP on the other hand I recommend a handful of tools. &lt;a href="https://scrutinizer-ci.com/"&gt;Scrutinizer&lt;/a&gt; is in my experience the most &lt;em&gt;feature complete&lt;/em&gt; of the hosted CI services. I make extensive use of &lt;a href="https://github.com/squizlabs/PHP_CodeSniffer"&gt;PHP CodeSniffer&lt;/a&gt; which is an amazing tool based around a PHP tokenizer. It's a lot of fun writing your own sniffs in my experience. I have begun experimenting with &lt;a href="https://github.com/phan/phan"&gt;Phan&lt;/a&gt; - it's a little unforgiving, in a good way… And of course &lt;a href="https://blog.jetbrains.com/phpstorm/"&gt;PHPStorm&lt;/a&gt; has a pretty decent analyzer built in.&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Sat, 21 Oct 2017 10:59:24 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/StaticAnalysis</guid></item><item><title>Lua Gotchas</title><link>https://blog.varunramesh.net/posts/lua-gotchas/</link><description>Lua is an awesome language, but it has some annoying features that have caused endless frustration for me.</description><author>Varun Ramesh's Blog</author><pubDate>Fri, 20 Oct 2017 14:06:05 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/lua-gotchas/</guid></item><item><title>2017-10-20/01</title><link>https://ho.dges.online/pictures/2017-10-20-01/</link><description/><author>ho.dges.online</author><pubDate>Fri, 20 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-10-20-01/</guid></item><item><title>2017-10-20/02</title><link>https://ho.dges.online/pictures/2017-10-20-02/</link><description/><author>ho.dges.online</author><pubDate>Fri, 20 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-10-20-02/</guid></item><item><title>Didact Fiber: Incremental reconciliation</title><link>https://medium.com/hexacta-engineering/didact-fiber-incremental-reconciliation-b2fe028dcaec</link><description>Build your own React, this time with fibers</description><author>Rodrigo Pombo</author><pubDate>Thu, 19 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/didact-fiber-incremental-reconciliation-b2fe028dcaec</guid></item><item><title>50 shades of truth</title><link>https://yasha.solutions/50-shades-of-truth/</link><description>Most people would rather be certain they’re miserable, than risk being happy. (R. Anthony)
Certainty is cool.
We love when we can feel confident.
It makes our world emotionaly safer.
 Also – we hate it when we have to issue a correction about a statement we made that turned out wrong.
 Certainty is a certain form of safety.
 Complexity leads to mistakes – which leads to lack of certainty…</description><author>Yasha Solutions</author><pubDate>Thu, 19 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/50-shades-of-truth/</guid></item><item><title>Ubuntu 17.10 Release Party</title><link>https://kyrofa.com/posts/ubuntu-17-10-release-party/</link><description>Were you busy today? Did you forget that Ubuntu 17.10 was released today (no way)? Perhaps you agree that Thursdays are lame for a party anyway? Walla Walla University&amp;rsquo;s ACM club is having their kick-off event, a joint retro video game and Ubuntu 17.10 release party, on Sunday, October 22nd from 3pm to 5pm!
This event will be taking place in room 348 of Kretschmar Hall on the Walla Walla University campus in Walla Walla, WA.</description><author>kyrofa's blog</author><pubDate>Thu, 19 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ubuntu-17-10-release-party/</guid></item><item><title>Upgrading PostgreSQL Using Homebrew</title><link>https://blog.tafkas.net/2017/10/19/upgrading-postgresql-using-homebrew/</link><description>On October 5th the PostgreSQL Global Development Group announced the release of PostgreSQL 10. It comes with tremendous amount of new features like
 Table partitioning Logical replication Improved parallel queries Stronger password hashing Durable Hash Indexes and more.  A nice list, including explanations can be found on Robert Haas&amp;rsquo; blog.
This post explains how to upgrade to the latest version of PostgreSQL on macOS using Homebrew. At the time of this writing I was using macOS 10.</description><author>Tafkas Blog</author><pubDate>Thu, 19 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/2017/10/19/upgrading-postgresql-using-homebrew/</guid></item><item><title>Born a Crime</title><link>https://nindalf.com/posts/born-a-crime/</link><description>'Born a Crime' by Trevor Noah is a hilarious and thought-provoking memoir about his childhood in South Africa.</description><author>Krishna's blog</author><pubDate>Thu, 19 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/born-a-crime/</guid></item><item><title>Using cgroups to limit I/O</title><link>https://andrestc.com/post/cgroups-io/</link><description>&lt;p&gt;Developers running their apps on &lt;a href="https://github.com/tsuru/tsuru"&gt;tsuru&lt;/a&gt; can choose plans based on memory and cpu usage. We were looking at adding I/O usage as one of the plan&amp;rsquo;s features, so one could choose how many I/O operations per second or bytes per second a container may be able to read/write.&lt;/p&gt;
&lt;p&gt;Being able to limit I/O is particulary important when running a diverse cloud, where applications with different workloads and needs are running together sharing multiple resources. We need to make sure that an application that starts to behave badly does not interfere with others.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Thu, 19 Oct 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/cgroups-io/</guid></item><item><title>The KISS principle in machine learning</title><link>https://bastian.rieck.me/blog/2017/kiss_machine_learning/</link><description>&lt;p&gt;Software developers are already familiar with the &lt;a href="https://en.wikipedia.org/wiki/KISS_principle"&gt;KISS principle&lt;/a&gt;.
Roughly speaking, it refers to the old wisdom that simple solutions are to be
preferred, while &lt;em&gt;unnecessary&lt;/em&gt; complexity should be avoided. In machine
learning, this means that one should increase the complexity iteratively,
starting from simple models and—if necessary—working upwards to more
complicated ones. I was recently reminded and humbled by the wisdom of KISS
while working on a novel topology-based kernel for machine learning.&lt;/p&gt;
&lt;h1 id="prelude-a-paper-on-deep-graph-kernels"&gt;Prelude: A Paper on Deep Graph Kernels&lt;/h1&gt;
&lt;p&gt;A &lt;a href="https://users.soe.ucsc.edu/~vishy/pubs/YanVis15.pdf"&gt;recent paper by Yanardag and Vishwanathan&lt;/a&gt; introduced a way of combining graph kernels with deep learning techniques. The new framework basically yields a way of using graph kernels, such as &lt;a href="http://proceedings.mlr.press/v5/shervashidze09a/shervashidze09a.pdf"&gt;&lt;em&gt;graphlet kernels&lt;/em&gt;&lt;/a&gt; in a regular deep learning setting.&lt;/p&gt;
&lt;p&gt;The two researchers used some interesting data sets for their publication.  Most
notably, they extracted a set of co-occurrence networks (more about that in
a minute) from &lt;a href="https://www.reddit.com"&gt;Reddit&lt;/a&gt;, a content aggregation and
discussion site. Reddit consists of different communities, the &lt;em&gt;subreddits&lt;/em&gt;.
Each subreddit deals with a different topic, ranging from archaeology to
zoology. The posting style of these subreddits varies a lot. There are several
subreddits that are based on a question–answer format, while others are
more centred around individual discussions.&lt;/p&gt;
&lt;p&gt;Yanardag and Vishwanathan hence crawled the top submissions from the subreddits
&lt;a href="https://www.reddit.com/r/IAmA"&gt;&lt;em&gt;IamA&lt;/em&gt;&lt;/a&gt;,
&lt;a href="https://www.reddit.com/r/AskReddit"&gt;&lt;em&gt;AskReddit&lt;/em&gt;&lt;/a&gt;, both of which are based on
questions and answers, as well as from
&lt;a href="https://www.reddit.com/r/TrollXChromosomes"&gt;&lt;em&gt;TrollXChromosomes&lt;/em&gt;&lt;/a&gt;, and
&lt;a href="https://www.reddit.com/r/atheism"&gt;&lt;em&gt;atheism&lt;/em&gt;&lt;/a&gt;, which are discussion-based
subreddits. From every submission, a graph was created by taking all the
commenters of a thread as nodes and connecting two nodes by an edge if one user
responds to the comment of another user. We can see that this is an extremely
simple model—it represents only a fraction of the information available in
every discussion. Nonetheless, there is some hope that qualitatively different
behaviours will emerge. More precisely, the assumption of Yanardag and
Vishwanathan is that there is some quantifiable difference between
question–answer subreddits and discussion-based subreddits. Their paper
aims to &lt;em&gt;learn&lt;/em&gt; the correct classification for each thread. Hence, given
a graph, we want to teach the computer to tell us whether the graph is more
likely to arise from a question–answer subreddit or from
a discussion-based one.&lt;/p&gt;
&lt;p&gt;The two researchers refer to this data set as &lt;em&gt;REDDIT-BINARY&lt;/em&gt;. It is now
available in &lt;a href="https://ls11-www.cs.tu-dortmund.de/staff/morris/graphkerneldatasets"&gt;a repository of benchmark data sets for graph
kernels&lt;/a&gt;,
gracefully provided and lovingly curated by the &lt;a href="https://ls11-www.cs.tu-dortmund.de/start"&gt;CS department of Dortmund
University&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="interlude-looking-at-the-data"&gt;Interlude: Looking at the Data&lt;/h1&gt;
&lt;p&gt;Prior to actually &lt;em&gt;working&lt;/em&gt; with the data, let us first take a look at it in
order to get a feel for its inherent patterns. To this end, I used &lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph, my
library for topological data analysis&lt;/a&gt;
read and convert the individual graphs of every discussion to the simpler &lt;a href="https://gephi.org/users/supported-graph-formats/gml-format"&gt;GML
format&lt;/a&gt;. See below
if you are also interested in the data. Next, I used &lt;a href="https://gephi.org"&gt;Gephi&lt;/a&gt;
to obtain a force-directed visualization of some of the networks.&lt;/p&gt;
&lt;p&gt;A look at a question–answer subreddit shows a central &lt;em&gt;core&lt;/em&gt; structure of
the data set, from which numerous strands—each corresponding most probably
to smaller discussions—emerge:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/graph_qa_subreddit.png"&gt;&lt;img alt="A graph visualization of Q&amp;amp;A subreddits" src="https://bastian.rieck.me/images/graph_qa_subreddit.png" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;The discussion-based subreddit graph, on the other hand, exhibits a larger
&lt;em&gt;depth&lt;/em&gt;, manifesting themselves in a few long strands. Nonetheless, a similar
central core structure is observable as well.&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/graph_discussion_subreddit.png"&gt;&lt;img alt="A graph visualization of discussion-based subreddits" src="https://bastian.rieck.me/images/graph_discussion_subreddit.png" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Keep in mind that the selected examples are not necessarily
representative—I merely picked two of the large graphs in the data set to
obtain an idea of how the data looks.&lt;/p&gt;
&lt;h1 id="a-complex-classification"&gt;A Complex Classification&lt;/h1&gt;
&lt;p&gt;A straightforward way to classify those networks would be to use graph kernels,
such as the &lt;a href="http://proceedings.mlr.press/v5/shervashidze09a/shervashidze09a.pdf"&gt;&lt;em&gt;graphlet
kernels&lt;/em&gt;&lt;/a&gt;.
The basic idea behind these kernels is to measure a dissimilarity between two
graphs by means of, for example, the presence or absence of certain subgraphs.
At least this is the strategy pursued by the &lt;em&gt;graphlet kernel&lt;/em&gt;. Other kernels
may instead opt for comparing &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Random_walk"&gt;&amp;ldquo;random walks&amp;rdquo;&lt;/a&gt;&lt;/em&gt;
on both graphs. A common theme of these kernels is that they are rather
expensive to compute. In many applications, they are the only hope of obtaining
suitable dissimilarity information without having to solve the graph isomorphism
problem, which is even more computationally expensive. Hence, graph kernels are
often the only suitable way of assessing the dissimilarity between graphs. They
are quite flexible and, as the authors show, can even be integrated into a deep
learning framework.&lt;/p&gt;
&lt;p&gt;As for their performance, Yanardag and Vishwanathan report an accuracy of
77.34% (standard deviation 0.18) for graphlet kernels and
78.04% (standard deviation 0.39) for &lt;em&gt;deep&lt;/em&gt; graphlet kernels, which is very
good considering the baseline for random guessing is 50%.&lt;/p&gt;
&lt;h1 id="a-simple-classification"&gt;A Simple Classification&lt;/h1&gt;
&lt;p&gt;In line with the KISS principle, I wanted to figure out alternative ways of
achieving similar accuracy values with a better performance, if possible. This
suggests a feature-based approach with features that can be calculated easily.
There are numerous potential options for choosing these features. I figured that
good choices include the &lt;a href="https://en.wikipedia.org/wiki/Clustering_coefficient"&gt;&amp;ldquo;average clustering coefficient&amp;rdquo;&lt;/a&gt; of the graph, the &lt;a href="https://en.wikipedia.org/wiki/Degree_(graph_theory)"&gt;&amp;ldquo;average degree&amp;rdquo;&lt;/a&gt;, the average shortest path length, the &lt;a href="https://en.wikipedia.org/wiki/Dense_graph"&gt;&amp;ldquo;density&amp;rdquo;&lt;/a&gt;, and the &lt;a href="https://en.wikipedia.org/wiki/Distance_(graph_theory)"&gt;&amp;ldquo;diameter&amp;rdquo;&lt;/a&gt; of the graph. Among these, the average shortest path length
and the diameter take longest to compute because they essentially have to
enumerate all shortest paths in the graph. So I only used the remaining three
features, all of which are computable in polynomial time.&lt;/p&gt;
&lt;p&gt;I used the excellent &lt;a href="https://networkx.github.io"&gt;NetworkX package&lt;/a&gt; for Python
to do most of the heavy lifting. Reading a graph and calculating its features is
as easy as it gets:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;networkx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;nx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_gml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;average_clustering_coefficient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;average_clustering&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;average_degree&lt;/span&gt;                 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;degree&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;degree&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;degree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;density&lt;/span&gt;                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;density&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I collect these values in a &lt;code&gt;pandas.DataFrame&lt;/code&gt; to simplify their handling. Now
we have to choose some classifiers. I selected &lt;a href="http://scikit-learn.org/stable/modules/tree.html"&gt;&lt;em&gt;decision trees&lt;/em&gt;&lt;/a&gt;, &lt;a href="http://scikit-learn.org/stable/modules/svm.html"&gt;&lt;em&gt;support vector machines&lt;/em&gt;&lt;/a&gt;, and &lt;a href="http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html"&gt;&lt;em&gt;logistic regression&lt;/em&gt;&lt;/a&gt;. Next, let us train and test each of these classifiers by means of 10-fold &lt;a href="https://en.wikipedia.org/wiki/Cross-validation_(statistics)"&gt;&amp;ldquo;cross-validation&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;classifiers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;DecisionTreeClassifier&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;LinearSVC&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;LogisticRegression&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;clf&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;classifiers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cross_val_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Accuracy: &lt;/span&gt;&lt;span class="si"&gt;%0.4f&lt;/span&gt;&lt;span class="s2"&gt; (+/- &lt;/span&gt;&lt;span class="si"&gt;%0.2f&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, I am using the &lt;em&gt;default values&lt;/em&gt; for every classifier—no
grid search or other technique for finding better hyperparameters for now.
Instead, I want to see how these classifiers perform out of the box.&lt;/p&gt;
&lt;h1 id="astonishing-results"&gt;Astonishing Results&lt;/h1&gt;
&lt;p&gt;The initial test resulted in the following accuracy values:
77.84% (standard deviation 0.16) for &lt;em&gt;decision trees&lt;/em&gt;,
64.14% (standard deviation 0.45) for &lt;em&gt;support vector machines&lt;/em&gt;, and
55.54% (standard deviation 0.49) for &lt;em&gt;logistic regression&lt;/em&gt;. At least the
first result is highly astonishing—without any adjustments to the
classifier &lt;em&gt;whatsoever&lt;/em&gt;, we obtain a performance that is en par with more
complex learning strategies! Recall that Yanardag and Vishwanathan adjusted the
hyperparameters during training, while this approach merely used the default
values.&lt;/p&gt;
&lt;p&gt;Let us thus focus on the decision tree classifier first and figure out
&lt;em&gt;why&lt;/em&gt; it performs the way it did. To this end, let us take a look at
what the selected features look like and how important they are. To do
this, I just added a single training instance, based on standard
test–train split of the decision tree classifier:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X_test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;clf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DecisionTreeClassifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feature_importances_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This results in &lt;code&gt;[ 0.18874114  0.34113588  0.47012298 ]&lt;/code&gt;, meaning that
all three features are somewhat important, with &lt;em&gt;density&lt;/em&gt; accounting for
almost 50% of the purity of a node—if you are unfamiliar with
decision trees, the idea is to obtain nodes that are as
“pure” as possible, meaning that there should be as few
differences in class labels as possible. The &lt;em&gt;density&lt;/em&gt; attribute appears
to be important for splitting up impure nodes correctly.&lt;/p&gt;
&lt;p&gt;To get a better feeling of the feature space, let us briefly visualize
it using &lt;a href="https://en.wikipedia.org/wiki/Principal_component_analysis"&gt;&amp;ldquo;principal component analysis&amp;rdquo;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;clf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PCA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;X_&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit_transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&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;label&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&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;X_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&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;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This results in the following image:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/decision_tree_features_pca.svg"&gt;&lt;img alt="A PCA visualization of the features used in the decision tree classifier" src="https://bastian.rieck.me/images/decision_tree_features_pca.svg" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Every dot in the image represents an individual graph, whereas distances
in the plot roughly correspond to distances between features. The large
amount of overlaps between graphs with different labels thus seems to
suggest that the features are &lt;em&gt;insufficient&lt;/em&gt; to separate the individual
graphs. How does the decision tree manage to separate them, nonetheless?
As it turns out, by creating a &lt;em&gt;very&lt;/em&gt; deep and wide tree. To see this,
let us export the decision tree classifier:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/tmp/clf.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;export_graphviz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is a small depiction of the resulting tree:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/decision_tree_complete.png"&gt;&lt;img alt="A small version of the resulting decision tree" src="https://bastian.rieck.me/images/decision_tree_complete.png" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;There is also a &lt;a href="https://bastian.rieck.me/images/decision_tree_complete.svg"&gt;larger variant of this
tree&lt;/a&gt; for you to play around
with. As you can see, the tree looks relatively complicated, so it is
very much tailored to the given problem. That is not to say that the
tree is necessarily suffering from &lt;em&gt;overfitting&lt;/em&gt;—we explicitly
used cross-validation to prevent this. What it &lt;em&gt;does&lt;/em&gt; show is that the
simple feature space with three features, while yielding very good
classification results, is not detecting the true underlying structure
of the problem. The rules generated by the decision tree are artificial
in the sense that they do not help us understand what makes the two
groups of graphs different from each other.&lt;/p&gt;
&lt;h1 id="coda"&gt;Coda&lt;/h1&gt;
&lt;p&gt;So, where does this leave us? We saw that we were able to perform as
well as state-of-the-art methods by merely picking a simple feature
space, consisting of three features, and a simple decision tree
classifier. I would say that &lt;em&gt;any&lt;/em&gt; classifier with a higher complexity
should yield significant improvements over this simple baseline, both in
terms of average accuracy and in terms of standard deviation. Hence, the
&lt;a href="https://en.wikipedia.org/wiki/KISS_principle"&gt;KISS principle&lt;/a&gt; in machine learning: start simple and only
add more complex building blocks, i.e. models, if you have established
a useful baseline.&lt;/p&gt;
&lt;p&gt;You can find both the code and the data in my &lt;a href="https://github.com/Pseudomanifold/TML"&gt;repository on topological
machine learning&lt;/a&gt;. To run the
analysis described in this blog post, just execute&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./simple_network_analysis.py GML/????.gml Labels.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in the &lt;code&gt;REDDIT-BINARY&lt;/code&gt; subfolder of the repository.&lt;/p&gt;
&lt;p&gt;That is all for now, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Wed, 18 Oct 2017 17:04:36 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/kiss_machine_learning/</guid></item><item><title>Copyleft is Dead. Long live Copyleft!</title><link>https://purpleidea.com/blog/2017/10/17/copyleft-is-dead-long-live-copyleft/</link><description>&lt;p&gt;As you may have noticed, we recently re-licensed &lt;a href="https://github.com/purpleidea/mgmt/"&gt;mgmt&lt;/a&gt; from the &lt;a href="https://www.gnu.org/licenses/why-affero-gpl.html"&gt;AGPL&lt;/a&gt; (&lt;em&gt;Affero&lt;/em&gt; General Public License) to the regular &lt;a href="https://www.gnu.org/licenses/quick-guide-gplv3.html"&gt;GPL&lt;/a&gt;. This is a post explaining the decision and which hopefully includes some insights at the intersection of technology and legal issues.&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Disclaimer&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;I am not a lawyer, and these are not necessarily the opinions of my employer. I think I&amp;rsquo;m knowledgeable in this area, but I&amp;rsquo;m happy to be corrected in the comments. I&amp;rsquo;m friends with a number of lawyers, and they like to include disclaimer sections, so I&amp;rsquo;ll include this so that I blend in better.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Wed, 18 Oct 2017 00:22:05 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/10/17/copyleft-is-dead-long-live-copyleft/</guid></item><item><title>Privacy is very recent? So what?</title><link>https://stop.zona-m.net/2017/10/privacy-is-very-recent-so-what/</link><description>&lt;p&gt;There&amp;rsquo;s a Medium post about &lt;a href="https://medium.com/the-ferenstein-wire/the-birth-and-death-of-privacy-3-000-years-of-history-in-50-images-614c26059e"&gt;&amp;ldquo;The Birth and Death of Privacy&amp;rdquo;&lt;/a&gt; that in my opinion is great&amp;hellip; except for its very last paragraph.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 17 Oct 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/privacy-is-very-recent-so-what/</guid></item><item><title>BBQ with a Dutch ICT/start up Delegation</title><link>https://boyter.org/2017/10/bbq-dutch-ictstart-delegation/</link><description>&lt;p&gt;So a few weeks back I received an interesting email that at first thought looked like a scam.&lt;/p&gt;
&lt;p&gt;In short I was being invited to a BBQ at the Consul General&amp;rsquo;s residence in Sydney to meet an ICT/start up delegation from the Netherlands. Let me straight up say I have no idea why I would receive something like this. I am not dutch, have no dutch ancestry (that I am aware of) and while &lt;a href="https://searchcode.com"&gt;searchcode.com&lt;/a&gt; somehow is listed on the &lt;a href="http://www.startupranking.com/top/australia"&gt;top startups in Sydney&lt;/a&gt; somehow its not as though it has lots of press coverage or is a real start-up (its more a hobby side business at the moment).&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 17 Oct 2017 03:22:18 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/10/bbq-dutch-ictstart-delegation/</guid></item><item><title>Review: Moto G5s Plus</title><link>https://solomon.io/moto-g5s-plus-smartphone-review/</link><description>I have spent the last month with the Moto G5s Plus and can say that it is an exceptional phone.</description><author>Sam Solomon</author><pubDate>Tue, 17 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/moto-g5s-plus-smartphone-review/</guid></item><item><title>How to post with WP-CLI</title><link>https://yasha.solutions/how-to-post-with-wp-cli/</link><description>Right, so this is probably not for everyone – but I just wanted to share.
  Vim plugin – not this time Before you just say – “hey there is a plugin for that” – (If you don’t know, Vim as a bunch of plugin and I would advise you check VimAwesome to get an idea of how many things you can do with this tiny piece of software.) So obviously among all the plugins, there are a few dedicated to manage your WordPress blog directly in VIM.</description><author>Yasha Solutions</author><pubDate>Tue, 17 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/how-to-post-with-wp-cli/</guid></item><item><title>The Crusades: The Authoritative History of the War for the Holy Land</title><link>https://nindalf.com/posts/the-crusades/</link><description>Discover the truth about the Crusades and why invoking them today is misguided, in this well-researched and engaging book.</description><author>Krishna's blog</author><pubDate>Tue, 17 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/the-crusades/</guid></item><item><title>The Vertical Human Decimeter</title><link>https://rybakov.com/blog/vertical-human-decimeter/</link><description>&lt;p&gt;Mira Hirtz has a good write-up on &lt;a href="http://mirahirtz.de/post/ten/"&gt;how abstractions and representations of things become the things they meant to represent&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With regards to representations, one phenomenon that I particularly like is what I call &lt;em&gt;interference&lt;/em&gt;. It happens when something, through its idiosyncratic existence, leaves traces in the outside world. Traces that show some of the object&amp;rsquo;s properties in a concise way.&lt;/p&gt;
&lt;p&gt;Just look at these photographs:&lt;/p&gt;
&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/rabbits_RYB7377.jpg" /&gt;




&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;Taken in Karlsruhe.&lt;br /&gt;
And the next one in the Alps, but that doesn&amp;rsquo;t matter that much:&lt;/p&gt;
&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/cows_P2M0157vv.jpg" /&gt;




&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;The top one I call &lt;em&gt;Rabbits&lt;/em&gt;, while the lower one is called &lt;em&gt;Cows&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This kind of cow and rabbit representation contains no information about their fur or their big faithful eyes - or any of the stuff that would be discernible from an animal drawing. Instead, it offers a one-dimensional but precise documentation that the animals are present, they are hungry, they eat tree leaves and are just around this tall.&lt;/p&gt;
&lt;p&gt;Mira also made a point that &lt;em&gt;illustration of female sexual organs shape the idea of what [female] pleasure should be like&lt;/em&gt;.&lt;br /&gt;
I guess, the most suitable metaphor for the general understanding of female genitals I ever encountered is the &lt;a href="http://www.atlasobscura.com/places/vertical-earth-kilometer"&gt;Vertical Earth Kilometer&lt;/a&gt; in Kassel.
It is an artwork by Walter De Maria - a two-inch thick solid brass rod that extend one kilometer down into the earth.&lt;/p&gt;
&lt;p&gt;On any arbitrary point on this planet a Vertical Earth Kilometer exists, though it is not perceived as such. Only through its measurement, through a penetration of earth by a thick rod, is it getting a representation that can be communicated easily.
Furthermore, the existence of the rod is purely speculative at this point in time. Sure, there must be eye witnesses that observed the rod being driven into the earth over 29 days, or, to put it differently, over a full moon cycle. But the visitors have no means to verify it: the rod is hidden from view. Yet even the theoretical existence of the rod is enough for a Vertical Earth Kilometer to exist.&lt;/p&gt;
&lt;p&gt;Comparing this situation to the general understanding of male and female genitalia is left as an excercise to the reader.&lt;/p&gt;
&lt;p&gt;What can not be represented, does not exist conceptually. Luckily, &lt;a href="https://www.theguardian.com/commentisfree/2016/sep/15/3d-model-clitoris-sexual-revolution-sex-education-womens-sexuality"&gt;with new imaging techniques&lt;/a&gt;, female sexual organs are starting to be represented not as &lt;em&gt;absence of a rod&lt;/em&gt; but as complex three-dimensional organs they are.&lt;/p&gt;
&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/clitori.jpg" /&gt;



&lt;figcaption&gt;
	Results for &amp;lsquo;clitoris 3d&amp;rsquo; on google image search.
&lt;/figcaption&gt;


&lt;/figure&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Mon, 16 Oct 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/vertical-human-decimeter/</guid></item><item><title>Why the ESV is both excellent and terrible</title><link>https://honza.pokorny.ca/2017/10/why-the-esv-is-both-excellent-and-terrible/</link><description>&lt;p&gt;In conservative Christian circles, the English Standard Version seems to be the
Bible translation of choice.  Many Calvinistic and Reformed leaders endorse this
translation, and use it in their books and articles.  I have personally used
this translation for many years, and have enjoyed it.  However, no translation
is perfect.  This isn&amp;rsquo;t a superficial comment meant to appease those who prefer
other translations.  Every translation of the Scriptures has deep flaws.  You
are then left with a choice of a set of flaws that you prefer.  In this article,
I&amp;rsquo;d like to point out why the ESV is both the best translation I know of, and a
terrible one at the same time.&lt;/p&gt;
&lt;p&gt;Many people have written accounts of their churches switching to the ESV.  In
this article, I&amp;rsquo;ll use Kevin DeYoung&amp;rsquo;s summary.&lt;/p&gt;
&lt;h2 id="genitives"&gt;Genitives&lt;/h2&gt;
&lt;p&gt;DeYoung says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[T]he ESV leaves interpretive ambiguities unresolved so that the reader or
preacher or student, rather than the translator, can determine which meaning
is best. &lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This sounds wonderful.  We should certainly allow the Scriptures to speak as
freely as possible in English.  The example that DeYoung gives is that of the
Greek genitive.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The phrase &amp;ldquo;the love of Christ&amp;rdquo; translates the Greek &lt;em&gt;agape tou Christou&lt;/em&gt;
which is, grammatically, a nominative noun followed by a genitive noun. The
love of Christ could mean the love Christ has for us, or the love we have
for Christ, or both.  All three are possible from the Greek and from the ESV
translation. The NIV, however, translates 2 Corinthians 5:14 &amp;ldquo;For Christ&amp;rsquo;s
love compels us &amp;hellip;&amp;rdquo;  This may be what the Greek phrase means (or it may not
be), but the NIV has settled the matter for us&amp;mdash;&lt;em&gt;agape tou Christou&lt;/em&gt; means
the love Christ has for us (i.e., &amp;ldquo;Christ’s love&amp;rdquo;)&amp;mdash;and has not allowed the
reader to come to his own conclusion. &lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a great example, and I fully agree with the decision that the ESV makes.
The translation is being faithful to the original by using the same level of
ambiguity.  The problem, however, is that it only works in isolated examples
like this one.&lt;/p&gt;
&lt;p&gt;Mark Strauss, one of the translators of the New International Version, has
written an article encouraging the wider Christian community to not allow the
ESV to become the standard English translation.  One of his criticisms of the
ESV is its treatment of Greek genitives.  The ESV follows the above ambiguity of
the Greek genitive too far in many cases.&lt;/p&gt;
&lt;p&gt;For example, the ESV renders Hebrews 1:3 as &amp;ldquo;he upholds the universe by the word
of his power&amp;rdquo;.  Strauss comments:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nonsensical (word that his power possesses?). This is an attributive
genitive, meaning &amp;ldquo;his powerful word&amp;rdquo; &lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or Romans 6:4 is translated as &amp;ldquo;we too might walk in newness of life&amp;rdquo; in the
ESV.  Again Strauss says that this is an attributed genitive meaning &amp;ldquo;a new
life&amp;rdquo;. &lt;sup id="fnref:4"&gt;&lt;a class="footnote-ref" href="#fn:4"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id="archaisms"&gt;Archaisms&lt;/h2&gt;
&lt;p&gt;DeYoung praises the ESV for its commitment to literary beauty:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[T]he essentially literal approach of the ESV in the book of Proverbs often
sounds more, well, proverbial.  The NIV often turns the aphoristic sound of
proverbs into everyday conversation. Which sounds like a proverb and which
sounds prosaic?  The difference between the two translations is the
difference between &amp;ldquo;A stitch in time saves nine&amp;rdquo; and &amp;ldquo;If you stitch
something now, you’ll save yourself nine stitches later.&amp;rdquo; Proverbs are
supposed to sound different from everyday speech. &lt;sup id="fnref:5"&gt;&lt;a class="footnote-ref" href="#fn:5"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He then compares the rendering of Proverbs 27:6 in the ESV and the NIV:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ESV: &amp;ldquo;Faithful are the wounds of a friend; profuse are the kisses of an enemy.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;NIV: &amp;ldquo;Wounds from a friend can be trusted, but an enemy multiplies kisses.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I agree with DeYoung&amp;rsquo;s assessment that the ESV often translates the Proverbs
and Psalms better than other translations.  The ESV seems to sound more
reverent to my ears, and more like ancient literature. &lt;sup id="fnref:6"&gt;&lt;a class="footnote-ref" href="#fn:6"&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The problem with the commitment to literary beauty, however, is that it often
leads to awkward language, and the proliferation of archaisms.  Let&amp;rsquo;s look at a
few examples from Mark Strauss again:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Matthew 1:18:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESV&lt;/strong&gt;: &amp;hellip; she was found to be with child&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Comment&lt;/strong&gt;: The ESV is not literal here (the Greek idiom is &amp;ldquo;having in
belly&amp;rdquo;), so this can only be classified as an archaism. Of course I would
never say today my wife is &amp;ldquo;with child&amp;rdquo; unless I were trying to sound
archaic and &amp;ldquo;biblical&amp;rdquo;. &lt;sup id="fnref:7"&gt;&lt;a class="footnote-ref" href="#fn:7"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really can&amp;rsquo;t understand why the ESV uses this kind of language.  What do we
gain by refusing to say &lt;em&gt;pregnant&lt;/em&gt;?  More:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Matthew 5:2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESV&lt;/strong&gt;: And he opened his mouth and taught them, saying:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Comment&lt;/strong&gt;: The ESV has missed the Greek idiom, which does not indicate two
actions, but one&amp;mdash;an introduction to a speech. No one speaking English would
say, &amp;ldquo;The teacher opened her mouth and taught the students, saying&amp;hellip;&amp;quot; &lt;sup id="fnref:8"&gt;&lt;a class="footnote-ref" href="#fn:8"&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="prepositions-and-conjunctions"&gt;Prepositions and conjunctions&lt;/h2&gt;
&lt;p&gt;Another area where the ESV shines is its treatment of conjunctions.  Careful
exegesis must depend on how clauses within an argument relate to each other.
The NIV often omits these small words to make the text flow better, or sound
more natural.  But my argument is that it often leads to loss of meaning that is
present in the original text.&lt;/p&gt;
&lt;p&gt;Here is an excellent example from Bill Mounce:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Take for example Heb 6:4. The author has been saying that he wants to leave
the basic, rudimentary doctrines of the Christian faith and move on to more
meaty, theological matters. And then, verses 4 to 6.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;It is impossible for those who have once been enlightened, who have tasted
the heavenly gift, who have shared in the Holy Spirit, who have tasted the
goodness of the word of God and the powers of the coming age and who have
fallen away, to be brought back to repentance&amp;rdquo; (NIV).&lt;/p&gt;
&lt;p&gt;Notice that there is no introductory conjunction in the NIV, so what is the
connection of verse four to the preceding? The fact that verse four begins a
new paragraph suggests that we are moving on to a new topic. And yet the
careful Greek student sees that verse four begins with γάρ. Is there a
connection that is obscured by the simple new paragraph?&lt;/p&gt;
&lt;p&gt;Absolutely. The flow of thought is clear. The reason that the author wants
to move on to meatier matters is because of the people&amp;rsquo;s ignorance of the
doctrine of necessary perseverance. And so he says that they should move on,
and the reason, introduced by γάρ, is that if they do not persevere, they
will never return to repentance.&lt;/p&gt;
&lt;p&gt;This is why translations like the ESV translate the γάρ: “/For/ it is
impossible.” &lt;sup id="fnref:9"&gt;&lt;a class="footnote-ref" href="#fn:9"&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another example comes from a rather funny and serious &lt;a href="https://www.youtube.com/watch?v=Xdc10WJVtZs"&gt;video&lt;/a&gt; by John Piper
where he says you should get a Bible with all the words.  Piper bemoans the
likes of NIV for leaving out words from their text that they seem to not know
what to do with.  His text is John 4:43&amp;ndash;45:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After the two days he departed for Galilee. (&lt;em&gt;For&lt;/em&gt; Jesus himself had
testified that a prophet has no honor in his own hometown.) &lt;em&gt;So&lt;/em&gt; when he
came to Galilee, the Galileans welcomed him, having seen all that he had
done in Jerusalem at the feast. For they too had gone to the feast. (ESV)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have highlighted the two conjunctions missing in the NIV.  Here, the reason
for Jesus&amp;rsquo;s leaving is that there is no honor for a prophet in his home town.
You cannot make that same argument from the NIV.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Every translation must make hard decisions.  It is absolutely impossible to
convert text in one language to another without losing some meaning.  It&amp;rsquo;s true
that the NIV often sounds more modern and normal.  But it can be imprecise, use
over-translation and under-translation, and it can obscure the flow of an
argument.  The ESV, on the other hand, is much more precise, tries to give you
all the words, but it can often sounds too archaic, awkward, and &amp;ldquo;biblical&amp;rdquo;.
Given these sets of flaws (as discussed in the introduction), I think I still
prefer the ESV.&lt;/p&gt;
&lt;p&gt;I hope this illustrates the need to consult many translations during serious
study.  Hopefully, the diligent student of the Scriptures can indulge in at
least a rudimentary understanding of Greek and Hebrew.&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Kevin DeYoung, &lt;em&gt;Why our church switched to the ESV&lt;/em&gt; (Wheaton, IL: Crossway, 2011), 11&amp;#160;&lt;a class="footnote-backref" href="#fnref:1"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Ibid., 11&amp;#160;&lt;a class="footnote-backref" href="#fnref:2"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Mark L. Strauss, &lt;em&gt;Why the English Standard Version (ESV)
Should not become the Standard English Version&lt;/em&gt;,
&lt;a href="http://zondervan.typepad.com/files/improvingesv2.pdf"&gt;http://zondervan.typepad.com/files/improvingesv2.pdf&lt;/a&gt; (Accessed October
14, 2017), 30&amp;#160;&lt;a class="footnote-backref" href="#fnref:3"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;Ibid., 30&amp;#160;&lt;a class="footnote-backref" href="#fnref:4"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;DeYoung, &lt;em&gt;Why our church switched to the ESV&lt;/em&gt;, 23-24&amp;#160;&lt;a class="footnote-backref" href="#fnref:5"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;Yes, I know, this is subjective.&amp;#160;&lt;a class="footnote-backref" href="#fnref:6"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;Strauss, &lt;em&gt;Why the English Standard Version (ESV)
Should not become the Standard English Version&lt;/em&gt;, 18&amp;#160;&lt;a class="footnote-backref" href="#fnref:7"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:8"&gt;
&lt;p&gt;Ibid., 5&amp;#160;&lt;a class="footnote-backref" href="#fnref:8"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:9"&gt;
&lt;p&gt;Bill Mounce, &lt;em&gt;γάρ and Paragraph Divisions&lt;/em&gt;,
&lt;a href="https://billmounce.com/monday-with-mounce/%CE%B3%CE%AC%CF%81-and-paragraph-divisions"&gt;https://billmounce.com/monday-with-mounce/%CE%B3%CE%AC%CF%81-and-paragraph-divisions&lt;/a&gt;
(Accessed October 16, 2017)&amp;#160;&lt;a class="footnote-backref" href="#fnref:9"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><author>Honza Pokorný</author><pubDate>Mon, 16 Oct 2017 16:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/10/why-the-esv-is-both-excellent-and-terrible/</guid></item><item><title>The Internet should host ALL voices! No, wait...</title><link>https://stop.zona-m.net/2017/10/the-internet-should-host-all-voices-no-wait.../</link><description>&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Unintended_consequences"&gt;&amp;ldquo;Law of Unintended Consequences&amp;rdquo;&lt;/a&gt; states that &lt;em&gt;&amp;ldquo;an intervention in a complex system tends to create unanticipated and often undesirable outcomes&amp;rdquo;&lt;/em&gt;. I wonder if some 100% legitimate aspirations and well-intentioned proposals to &lt;a href="https://www.theguardian.com/commentisfree/2017/oct/05/internet-white-western-google-wikipedia-skewed"&gt;make the internet less &amp;ldquo;white and western&amp;rdquo;&lt;/a&gt; may have just such consequences.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 16 Oct 2017 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/the-internet-should-host-all-voices-no-wait.../</guid></item><item><title>Hacktoberfest 2017</title><link>https://www.mikekasberg.com/blog/2017/10/15/hacktoberfest-2017.html</link><description>&lt;p&gt;&lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt; is a project sponsored
by Digital Ocean and Github that encourages contributions to open source
software. Anyone who contributes at least 4 pull requests to open source
projects on Github during the month of October will get a free Hacktoberfest
shirt for their participation.&lt;/p&gt;

&lt;p&gt;This year, I participated in Hacktoberfest for the first time as a project
maintainer.  After learning about the event, I decided to create several issues
in my &lt;a href="https://mkasberg.github.io/container-immersion/"&gt;Container Immersion&lt;/a&gt;
project (which I &lt;a href="https://www.mikekasberg.com/blog/2017/02/11/so-you-want-to-learn-docker.html"&gt;wrote
about&lt;/a&gt; in February) with the
Hacktoberfest label, inviting new developers to help out.  Initially, I was
surprised by the quick response of several people willing to help.  This is
probably the best benefit of Hacktoberfest - it creates an environment where
people are actively looking for projects to work on, and projects that normally
wouldn’t receive much attention are given a chance to gain exposure and receive
contributions from the community.&lt;/p&gt;

&lt;!--more--&gt;
&lt;h2 id="outcomes"&gt;Outcomes&lt;/h2&gt;

&lt;p&gt;Hacktoberfest proved very beneficial for Container Immersion. I focused my
requests for help on styling improvements for the site, and the results are
great! Before Hacktoberfest, Container Immersion’s styling was a little rough around the edges:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Container Immersion Before Hacktoberfest
2017" src="https://www.mikekasberg.com/images/hacktoberfest-2017/Before_Hacktoberfest.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;After Hacktoberfest, the site looks much more polished:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Container Immersion After Hacktoberfest
2017" src="https://www.mikekasberg.com/images/hacktoberfest-2017/After_Hacktoberfest.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;We added a Github ribbon, improved the navigation buttons, improved the style of
code samples, and made the site more mobile-friendly. Each of those improvements
was contributed by someone participating in Hacktoberfest - evidence of
Hacktoberfest’s success at motivating the open source community.&lt;/p&gt;

&lt;h2 id="insights"&gt;Insights&lt;/h2&gt;

&lt;p&gt;While participating in Hacktoberfest, I learned several lessons that are also
applicable to open source development in general. At the time when I first asked for
contributions by adding the Hacktoberfest label to some of my Github issues, the
documentation for Container Immersion was somewhat lacking. Although the project
had a README, a few of the initial contributors struggled a little bit to get
the site running locally (via Jekyll). It was also not clear to some
contributors what the site’s architecture was - that is, where the HTML and CSS
that Jekyll uses to build the site were located. While things like this might
seem obvious to really experienced developers, they were not obvious to newer
developers who wanted to get their feet wet, and it’s easy for more experienced
developers to overlook problems like this.&lt;/p&gt;

&lt;p&gt;Of course, the remedy is simple. I added additional information to the readme
about how to run the site locally for the first time. I also added a new section
about how the site is built using Jekyll, and where different components of the
site can be found in the project’s directories.&lt;/p&gt;

&lt;h2 id="open-source-community"&gt;Open Source Community&lt;/h2&gt;

&lt;p&gt;Based on my experience with Hacktoberfest, I think that it’s really important
for open source projects that want to develop a strong community to make it
really easy to set up a development environment and get coding. It can be quite
difficult and intimidating for relatively new developers to contribute to
projects when they don’t receive much guidance from the maintainers. Open source
projects that support and mentor new developers will likely see more
contributions and will be able to build stronger communities. I’ve seen the
benefits of Hacktoberfest on Container Immersion, and I’m sure many other open
source projects are getting a lot of work contributed due to this event. Thank
you &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt;, for sponsoring open source
events like this one.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Mon, 16 Oct 2017 06:28:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/10/15/hacktoberfest-2017.html</guid></item><item><title>Links - October 16, 2017</title><link>https://faingezicht.com/links/2017/10/16/links/</link><description>I read a bunch of stuff this weekend. Most of the things I read were about the interactions between tech and policy. There is a strange techno-skeptic somber mood that makes me feel weird about the future, and I am trying to read and write a lot about it to clear my thoughts.

I'm part of a generation that never knew the world before the internet. Did it always feel like we're in a dystopia?</description><author>Avy Faingezicht</author><pubDate>Mon, 16 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/10/16/links/</guid></item><item><title>Finally: Some Sane Password Advice</title><link>https://www.danstroot.com/posts/2017-10-17-finally-some-good-password-advice</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/password.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;In every organization I have worked with managing user authentication and passwords was a huge challenge.  The key issue was that the "old" password best practices were **failed attempts to fix the user, not the system**. &lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2017-10-17-finally-some-good-password-advice"&gt;Finally: Some Sane Password Advice&lt;/a&gt; first appeared on &lt;a href="https://www.danstroot.com"&gt;Dan Stroot's Blog&lt;/a&gt;</description><author>Dan Stroot</author><pubDate>Mon, 16 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2017-10-17-finally-some-good-password-advice</guid></item><item><title>Simple unit tests with C++ and CMake</title><link>https://bastian.rieck.me/blog/2017/simple_unit_tests/</link><description>&lt;p&gt;A warning upfront: this post is sort of an advertisement for
&lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, my C++ library for
topological data analysis. In this blog post I do not want to cover any
of the mathematical algorithms present in Aleph—I rather want to
focus on small but integral part of the project, viz. &lt;em&gt;unit tests&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If
you are not familiar with the concept of unit testing, the idea
is (roughly) to write a small, self-sufficient test for every new
piece of functionality that you write. Proponents of the methodology of
&lt;em&gt;test-driven development&lt;/em&gt; (TDD) even go so far as to require you to
write the unit tests &lt;em&gt;before&lt;/em&gt; you write your actual code. In this
mindset, you first think of the results your code should achieve and
which outputs you expect prior to writing any “real” code.
I am putting the word &lt;em&gt;real&lt;/em&gt; in quotation marks here because it may seem
strange to focus on the tests before doing the heavy lifting.&lt;/p&gt;
&lt;p&gt;However, this way of approaching software development may actually be
quite beneficial, in particular if you are working on algorithms with
a nice mathematical flavour. Here, thinking about the results you want
to achieve with your code ensures that at least a few known examples are
processed correctly by your code, making it more probable that the code
will perform well in real-world scenarios.&lt;/p&gt;
&lt;p&gt;When I started writing Aleph in 2016, I also wanted to add some unit
tests, but I did not think that the size of the library warranted the
inclusion of one of the big players, such as &lt;a href="https://github.com/google/googletest"&gt;Google
Test&lt;/a&gt; or
&lt;a href="http://www.boost.org/doc/libs/release/libs/test"&gt;&lt;code&gt;Boost.Test&lt;/code&gt;&lt;/a&gt;. While
arguably extremely powerful and teeming with more features than I could
possibly imagine, they are also quite heavy and require non-trivial
adjustments to any project.&lt;/p&gt;
&lt;p&gt;Thus, in the best tradition of the
&lt;a href="http://wiki.c2.com/?NotInventedHere"&gt;&lt;em&gt;not-invented-here-syndrome&lt;/em&gt;&lt;/a&gt;,
I decided to roll my own testing framework, base on pure &lt;code&gt;CMake&lt;/code&gt; and
small dash of &lt;code&gt;C++&lt;/code&gt;. My design decisions were rather simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;CTest&lt;/code&gt;, the testing framework of &lt;code&gt;CMake&lt;/code&gt; to run the tests. This
framework is rather simple and just uses the return type of a unit
test program to decide whether the test worked correctly.&lt;/li&gt;
&lt;li&gt;Provide a set of routines to check the correctness of certain
calculations within a unit test, throwing an error if something
unexpected happened.&lt;/li&gt;
&lt;li&gt;Collect unit tests for the “larger” parts of the project
in a single executable program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, you read that right—my approach actually opts for throwing an
error in order to crash the unit test program. Bear with me, though, for
I think that this is actually a rather sane way of approaching unit
tests. After all, if the tests fails, I am usually not interested in
whether other parts of a test program—that may potentially depend
on previous calculations—run through or not. As a consequence,
adding a unit test to Aleph is as simple as adding the following lines
to a &lt;code&gt;CMakeLists.txt&lt;/code&gt; file, located in the &lt;code&gt;tests&lt;/code&gt; subdirectory of the project:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ADD_EXECUTABLE( test_io_gml test_io_gml.cc )
ADD_TEST(            io_gml test_io_gml    )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While in the main &lt;code&gt;CMakeLists.txt&lt;/code&gt;, I added the following lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ENABLE_TESTING()
ADD_SUBDIRECTORY( tests )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far, so good. A test now looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;tests/Base.hh&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testBasic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="c1"&gt;// do some nice calculation; store the results in `foo` and `bar`,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="c1"&gt;// respectively
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;ALEPH_ASSERT_THROW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;ALEPH_ASSERT_EQUAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;ALEPH_ASSERT_EQUAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testAdvanced&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="c1"&gt;// a more advanced test
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;testBasic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;testAdvanced&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That is basically the whole recipe for a simple unit test. Upon
execution, &lt;code&gt;main()&lt;/code&gt; will ensure that all larger-scale test routines,
i.e. &lt;code&gt;testSimple()&lt;/code&gt; and &lt;code&gt;testAdvanced()&lt;/code&gt; are called. Within each of
these routines, the calls to the corresponding macros—more on that
in a minute— ensure that conditions are met, or certain values are
equal to other values. Else, an error will be thrown, the test will
abort, and &lt;code&gt;CMake&lt;/code&gt; will throw an error upon test execution.&lt;/p&gt;
&lt;p&gt;So, how do the macros look like? Here is a copy of the current version of Aleph:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#define ALEPH_ASSERT_THROW( condition )                             \
{                                                                   \
  if( !( condition ) )                                              \
  {                                                                 \
    throw std::runtime_error(   std::string( __FILE__ )             \
                              + std::string( &amp;quot;:&amp;quot; )                  \
                              + std::to_string( __LINE__ )          \
                              + std::string( &amp;quot; in &amp;quot; )               \
                              + std::string( __PRETTY_FUNCTION__ )  \
    );                                                              \
  }                                                                 \
}

#define ALEPH_ASSERT_EQUAL( x, y )                                  \
{                                                                   \
  if( ( x ) != ( y ) )                                              \
  {                                                                 \
    throw std::runtime_error(   std::string( __FILE__ )             \
                              + std::string( &amp;quot;:&amp;quot; )                  \
                              + std::to_string( __LINE__ )          \
                              + std::string( &amp;quot; in &amp;quot; )               \
                              + std::string( __PRETTY_FUNCTION__ )  \
                              + std::string( &amp;quot;: &amp;quot; )                 \
                              + std::to_string( ( x ) )             \
                              + std::string( &amp;quot; != &amp;quot; )               \
                              + std::to_string( ( y ) )             \
    );                                                              \
  }                                                                 \
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty simple, I would say. The &lt;code&gt;ALEPH_ASSERT_EQUAL&lt;/code&gt; macro actually
tries to convert the corresponding values to strings, which may not
always work. Of course, you could use more complicated string conversion
routines, as
&lt;a href="http://www.boost.org/doc/libs/release/libs/test"&gt;&lt;code&gt;Boost.Test&lt;/code&gt;&lt;/a&gt; does.
For now, though, these macros are sufficient to make up the unit test
framework of Aleph, which at the time of me writing this, encompasses
more than 4000 lines of code.&lt;/p&gt;
&lt;p&gt;The only remaining question is how this framework is used in practice.
By setting &lt;code&gt;ENABLE_TESTING()&lt;/code&gt;, &lt;code&gt;CMake&lt;/code&gt; actually exposes a new target
called &lt;code&gt;test&lt;/code&gt;. Hence, in order to run those tests, a simple &lt;code&gt;make test&lt;/code&gt;
is sufficient in the build directory. This is what the result may look
like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ make test
Running tests...
Test project /home/bastian/Projects/Aleph/build
      Start  1: barycentric_subdivision
 1/36 Test  #1: barycentric_subdivision ............   Passed    0.00 sec
      Start  2: beta_skeleton

      [...]

34/36 Test #34: union_find .........................   Passed    0.00 sec
      Start 35: witness_complex
35/36 Test #35: witness_complex ....................   Passed    1.82 sec
      Start 36: python_integration
36/36 Test #36: python_integration .................   Passed    0.07 sec

100% tests passed, 0 tests failed out of 36

Total Test time (real) =   5.74 sec
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition to being rather lean, this framework can easily be
integrated into an existing &lt;a href="https://travis-ci.org"&gt;Travis CI&lt;/a&gt; workflow
by adding&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- make test
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;as an additional step to the &lt;code&gt;script&lt;/code&gt; target in your &lt;code&gt;.travis.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;If you are interested in using this testing framework, please take
a look at the following files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Pseudomanifold/Aleph/tree/master/tests"&gt;The &lt;code&gt;tests&lt;/code&gt; subdirectory of
&lt;code&gt;Aleph&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Pseudomanifold/Aleph/blob/master/tests/Base.hh.in"&gt;The basic configuration file of all unit
tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Pseudomanifold/Aleph/blob/master/tests/test_union_find.cc"&gt;A simple example of a unit test for a single
class&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is all for now, until next time—may your unit tests always
work the way you expect them to!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 15 Oct 2017 23:36:15 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/simple_unit_tests/</guid></item><item><title>Talk @ RFC's We Love: CoAPing with the Internet of Things</title><link>https://www.anmolsarma.in/post/coap-talk/</link><description>&lt;p&gt;Gave an introductory talk on CoAP at the &lt;a href="https://www.iiesoc.in/single-post/2017/11/02/RFCs-We-Love-HMAC-CoAP-Edition"&gt;5th RFC&amp;rsquo;s We Love meetup&lt;/a&gt;. Turnout was low, probably owing to the rains and the festive season. It was still fun and had great discussions.&lt;/p&gt;</description><author>Anmol Sarma</author><pubDate>Sat, 14 Oct 2017 09:26:27 GMT</pubDate><guid isPermaLink="true">https://www.anmolsarma.in/post/coap-talk/</guid></item><item><title>Links - October 14, 2017</title><link>https://faingezicht.com/links/2017/10/14/links/</link><description/><author>Avy Faingezicht</author><pubDate>Sat, 14 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/10/14/links/</guid></item><item><title>How to explain git in simple words?</title><link>https://xosh.org/explain-git-in-simple-words/</link><description>&lt;p&gt;A few years ago I started hearing about Git here and there and its various strange words like branch, index, tree, commit, clone, fork, master, origin, head, check out, check in, push and pull etc. Available tutorials were difficult to understand because they jumped straight to git commands. I approached &lt;a href="https://www.quora.com/How-do-you-explain-the-basics-of-Git-in-simple-words-What-does-branch-index-tree-commit-clone-fork-master-origin-head-check-out-check-in-etc-mean"&gt;Quora&lt;/a&gt; in hope for something more visual and easier to understand, then answered it myself getting most upvotes. Now posting it here on my own blog with hopefully even better explanation :)&lt;/p&gt;</description><author>XOSH.ORG</author><pubDate>Sat, 14 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xosh.org/explain-git-in-simple-words/</guid></item><item><title>There is NO free speech inside Facebook</title><link>https://stop.zona-m.net/2017/10/there-is-no-free-speech-inside-facebook/</link><description>&lt;p&gt;A few weeks ago, one of my Facebook contacts, whom I&amp;rsquo;ll call &amp;ldquo;Jane&amp;rdquo;, complained on her wall that Facebook had blocked one of her posts. Facebook and free speech myths ensued.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 13 Oct 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/there-is-no-free-speech-inside-facebook/</guid></item><item><title>Broadcom, Or How I Learned To Start Worrying And Drop The Packet</title><link>https://smcleod.net/2017/10/broadcom-or-how-i-learned-to-start-worrying-and-drop-the-packet/</link><description>&lt;p&gt;&lt;img src="https://smcleod.net/2017/10/broadcom-or-how-i-learned-to-start-worrying-and-drop-the-packet/office-space-broadcom.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Earlier this week we started the process to upgrade one of our hypervisor compute clusters when we encountered a rather painful bug with HP&amp;rsquo;s Broadcom NIC chipsets.&lt;/p&gt;
&lt;p&gt;We were part way through a routine rolling pool upgrade of our hypervisor (XenServer) cluster when we observed unexpected and intermittent loss of connectivity between several VMs, then entire XenServer hosts.&lt;/p&gt;
&lt;p&gt;The problems appeared to impact hosts that hadn&amp;rsquo;t yet upgraded to XenServer 7.2. We now attribute this to a symptom of extreme packet loss between the hosts in the pool and thanks to buggy firmware from Broadcom and HP.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Fri, 13 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/10/broadcom-or-how-i-learned-to-start-worrying-and-drop-the-packet/</guid></item><item><title>Dear Postgres</title><link>/2017/10/12/Dear-Postgres/</link><description>&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;Dear Postgres,&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve always felt an affinity for you in my 9 years of working with you. I know others have known you longer, but that doesn&amp;rsquo;t mean they love you more. Years ago when others complained about your rigidness or that you weren&amp;rsquo;t as accommodating as others I found solace in your steadfast values:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Don&amp;rsquo;t lose data&lt;/li&gt;
&lt;li&gt;Adhere to standards&lt;/li&gt;
&lt;li&gt;Move forward with a balancing act between new fads of the day while still continuously improving&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You&amp;rsquo;ve been there and seen it all. Years ago you were being disrupted by XML databases. As companies made heavy investment into what such a document database would do for their organization you proceeded to &amp;ldquo;simply&amp;rdquo; add a datatype that accomplished the same and brought your years of progress along with it.&lt;/p&gt;
&lt;p&gt;In the early years you had the standard format of index &lt;em&gt;b-tree&lt;/em&gt; that most database engines leveraged. Then quietly but confidently you started adding more. Then came K-nearest neighbor, generalized inverted indexes (GIN), and generalized search-tree (GiST), only to be followed by space partitioned GiST and block range indexes (BRIN). Now the only question is which do I use?&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;All the while there was this other camp using for something that felt cool but outside my world: GIS. GIS, geographical information systems, I thought was something only civil engineers used. Then GPS came along, then the iPhone and location based devices came along and suddenly I wanted to find out the nearest path to my Peets, or manage geographical region for my grocery delivery service. PostGIS had been there all along building up this powerful feature set, sadly to this day I still mostly marvel from the sideline at this whole other feature set I long to take advantage of&amp;hellip; &lt;em&gt;one day&amp;hellip; one day&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A little over 5 years ago I fell in love with your fastly improving analytical capabilities. No you weren&amp;rsquo;t an MPP system yet, but here came window functions and CTEs, then I almost understood recursive CTEs &lt;em&gt;(still working on that one)&lt;/em&gt;. I can iterate over data in a recursive fashion without PL/PgSQL? Yes please! I only want to use it more.&lt;/p&gt;
&lt;p&gt;And then five years ago, document stores start taking over the world. I feel like I&amp;rsquo;ve seen this story before, wasn&amp;rsquo;t XML going to change the internet? Enter JSON, the JSON datatype, and JSONB. Wow, this is really nice to mix relational, document storage, join against things. I suddenly don&amp;rsquo;t get why more don&amp;rsquo;t take this flexible approach to building on a good foundation and layering on the refinements.&lt;/p&gt;
&lt;p&gt;Extensions! Where have you been all my life? There’s &lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt;, and &lt;a href="https://github.com/aggregateknowledge/postgresql-hll"&gt;HyperLogLog&lt;/a&gt;, and &lt;a href="https://www.zombodb.com/"&gt;ZomboDB&lt;/a&gt;, with each I can add functionality to Postgres without it being limited to the standard release, they can be in C or not. Wait, all along so much has been built on this foundation? PostGIS, full-text search, hstore? I like all those things, why didn&amp;rsquo;t you tell me all along about this foundation? Postgres, I like what I&amp;rsquo;m seeing how you&amp;rsquo;re allowing others to do more without having it be in the core of Postgres. This extension stuff is really kinda cool that it&amp;rsquo;s Postgres and then some, kinda like C and then ++, wait nevermind scratch that analogy.&lt;/p&gt;
&lt;p&gt;Sorry, I&amp;rsquo;ve rambled a bit. You&amp;rsquo;re a little over twenty years old now. I&amp;rsquo;ve known you for nearly ten of those years so I know there&amp;rsquo;s so much about your background I don&amp;rsquo;t know, I hope we get to spend the time together to share it all. This 10 release is really an exciting one to me. We&amp;rsquo;ve spent all this time together and I feel like each passing year the bond grows fonder.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ve brought me better parallelism so I can further utilize my system resources. I now have partitioning. Thank you! I don&amp;rsquo;t have to roll my own hacks to help age out old data for my time series database. Logical replication will make so many other things possible, such as more online upgrades and integration with other systems.&lt;/p&gt;
&lt;p&gt;Postgres, I just want to say thank you for the past ten years together. Thank you for all you’ve done and for all you’ll continue to do in the future.&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, 12 Oct 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/10/12/Dear-Postgres/</guid></item><item><title>Breach Handling &amp;amp; The High Ground</title><link>https://blog.eutopian.io/breach-handling-the-high-ground/</link><description>1600 words, 8 minutes.
You&amp;rsquo;ve suffered a breach. Your security was circumvented. Data was lost and the public, shareholders, media, and perhaps regulator must soon be informed. A chain of events has begun. What you do next will determine in large part where that chain leads. In this post I&amp;rsquo;m going to talk about a tactic I&amp;rsquo;ve seen used to successfully re-frame a bad situation and nudge the narrative in your favour.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 12 Oct 2017 21:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/breach-handling-the-high-ground/</guid></item><item><title>When is a Dollar not a Dollar?</title><link>https://www.codingvc.com/p/when-is-a-dollar-not-a-dollar</link><description>&amp;#8220;All dollars are equal, but some dollars are more equal than others.&amp;#8221;</description><author>Coding VC</author><pubDate>Thu, 12 Oct 2017 05:40:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/when-is-a-dollar-not-a-dollar</guid></item><item><title>Opportunities at the crossroad</title><link>http://dimitarsimeonov.com/2017/10/12/opportunities-at-the-crossroad</link><description>&lt;p&gt;&lt;img alt="crossroads_in_the_mountain" class="img-responsive" src="/assets/image/20171012_crossroad/pirin_tevno.jpg" /&gt;
&lt;span style="color: grey;"&gt;photo credit (pirinmountain.wordpress.com)[https://pirinmountain.wordpress.com/2013/04/18/%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B8-%D0%B8-%D0%BA%D0%B0%D1%80%D1%82%D0%B8/]&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;I was talking to a friend of mine, catching up on what each of us has
been doing, and we had an interesting observation about the role of
crossroads in life.&lt;/p&gt;

&lt;p&gt;My friend went on a multi-day hike, but as luck would have it, his
tent broke after three days. This restricted his mobility and ability
to go to more remote places, so instead, he went to a somewhat
centrally located hut. The idea there was that from the hut, he can do
day-hikes in multiple directions, and remain flexible in case the
weather changes and he needs to change the planned route for the day.&lt;/p&gt;

&lt;p&gt;The hut, being centrally located, and a popular destination of itself,
is in a somewhat of a crossroad. There are several nice peaks next to
it, a lake, and paths which go in all directions. It’s also really
cozy inside, and it’s a favorite place for many to stay, with it’s
warm carpet and traditional furnishings. It’s a place that invites you
to stay longer.&lt;/p&gt;

&lt;p&gt;It has a small capacity, and all the guests tend to meet each
other. My friend met a traveling engineer, and she told him that she
can fix his tent with duct tape. But neither of them had a duct tape
with them. But as luck would have it, on the next day another tourist
was passing by who did have duct tape. And so my friend got his tent
fixed, and based on the new weather forecast picked a new route for
the remainder of his trek.&lt;/p&gt;

&lt;p&gt;My friend was lucky, that’s for sure, but he would’ve been less likely
to be lucky if he wasn’t staying in a hut that was a crossroads
hut. Crossroads provide more freedom, and tend to attract more people,
resources and opportunities. In times of uncertainty, reflection or
planning, it’s good to be at the crossroads, to be able to take
advantage of these crossroads properties.&lt;/p&gt;

&lt;p&gt;I think that trekking through the mountain is an interesting metaphor
for life. Everyone’s going in different directions, and intends to
climb different peaks or chill by different lakes. We go in groups, or
by ourselves on our paths, and we all can experience good or bad luck
at times. We start from different places and see the mountain and its
beauty and ugliness from different angles. And each of us walks on
their own pace.&lt;/p&gt;

&lt;p&gt;As much as a mountain is a reasonable metaphor for life, we can
transplant the idea of crossroads to our own personal journeys. A
personal crossroad has ample freedom and opportunities. It’s a
beneficial place to be, whenever we have uncertainty about our path,
or we are missing some of the resources we need for our next goal and
mission.&lt;/p&gt;

&lt;p&gt;For a person who just graduated high school, an university can be that
crossroad. There, the person can gather the “education” resource, and
also meet people who have ventured in different directions, and hear
from them about the possible goals in life.  Other examples of
abstract crossroads can be local and interest-based communities,
conferences, and even physical cities - a less-abstract example of
crossroads.&lt;/p&gt;

&lt;p&gt;I think one common logical fallacy that some us may commit is to avoid
these “crossroads”, because we’re so much in a hurry to climb a peak,
that we go and suffer when our tent breaks and we get stuck in a
thunderstorm when the weather forecast changes. Of course, the reverse
fallacy of never venturing out is also common, but as a person, who’s
interested in getting to different peaks, I’m less worried about it
for myself, and therefore less interested in discussing it.&lt;/p&gt;

&lt;p&gt;Creativity and entrepreneurship are about finding a good path to go,
and abound with uncertainty. That uncertainty makes it beneficial to
spend time at crossroads, when starting new creative projects, or
pivoting a business idea.&lt;/p&gt;</description><author>D13V</author><pubDate>Thu, 12 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/10/12/opportunities-at-the-crossroad</guid></item><item><title>El Cuarto Misionero por el Élder Lawrence Corbridge</title><link>https://sean.lane.sh/posts/2017/10/El-Cuarto-Misionero-por-el-%C3%89lder-Lawrence-Corbridge/</link><description>&lt;p&gt;This post is not about technology, computer science, or programming. Instead it&amp;rsquo;s a call back to my time as an LDS missionary in Paraguay. During my time there, I came across a talk given by an Elder Lawrence Corbridge that I really enjoyed. Some friends of mine were asking about it, and I wanted to make a copy in English and Spanish easily accessible. Please find the links to copies below.&lt;/p&gt;
&lt;p&gt;Este post no se trata de tecnología, informática o programación. En cambio, es una llamada a mi tiempo como misionero de los SUD en Paraguay. Durante mi tiempo allí, me encontré con una charla dada por el Élder Lawrence Corbridge que me gustó mucho. Algunos amigos míos preguntaban por eso, y quería hacer una copia en inglés y español fácilmente accesible. Encuentre los enlaces a las copias a continuación.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sean.lane.sh/files/the_fourth_missionary.pdf"&gt;The Fourth Missionary by Elder Lawrence Corbridge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sean.lane.sh/files/el_cuarto_misionero.pdf"&gt;El Cuarto Misionero por el Élder Lawrence Corbridge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Posts on Sean Lane</author><pubDate>Thu, 12 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2017/10/El-Cuarto-Misionero-por-el-%C3%89lder-Lawrence-Corbridge/</guid></item><item><title>Heirloom Code</title><link>https://www.craigpardey.com/post/2017-10-11-heirloom-code/</link><description>&lt;p&gt;&lt;a href="https://www.amazon.ca/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052"&gt;Michael Feathers&lt;/a&gt; says that legacy code is any code without tests but I&amp;rsquo;d go a step further and say that legacy code is any code that is still running even though the original developer(s) are no longer working on it.  And there is certainly plenty of &lt;em&gt;that&lt;/em&gt; in financial institutions.  There are other characteristics too, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;unreproducible production environment&lt;/li&gt;
&lt;li&gt;incomplete source control
&lt;ul&gt;
&lt;li&gt;missing files&lt;/li&gt;
&lt;li&gt;&amp;lsquo;master&amp;rsquo; fails to build&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;no automated build process&lt;/li&gt;
&lt;li&gt;no release process&lt;/li&gt;
&lt;li&gt;few or no unit tests&lt;/li&gt;
&lt;li&gt;no way to run or test the code on a developer workstation&lt;/li&gt;
&lt;li&gt;little or no documentation&lt;/li&gt;
&lt;li&gt;none of the original developers available&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am presently working on a codebase that checks &lt;em&gt;all of the above&lt;/em&gt; boxes and it isn&amp;rsquo;t even that old but instead of dismissing it as an unmaintainable mess I have changed my mindset and have started referring to it as Heirloom Code.&lt;/p&gt;</description><author>Craig Pardey</author><pubDate>Wed, 11 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.craigpardey.com/post/2017-10-11-heirloom-code/</guid></item><item><title>How to Use Shiny Containers with Shinyproxy</title><link>https://lukesingham.com/shiny-containers-with-shinyproxy/</link><description>&lt;p&gt;&lt;strong&gt;Aim&lt;/strong&gt;: Setup &lt;a href="https://www.shinyproxy.io/"&gt;shinyproxy&lt;/a&gt; as a production level way of deploying multiple containerised shiny apps with authentication. Additionally I'll demonstrate how to incorporate containerised python web apps and deploy this behind a reverse proxy using Nginx.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conceptual Overview&lt;/strong&gt;&lt;br /&gt;
&lt;img alt="" src="https://lukesingham.com/content/images/2017/10/overview.png" /&gt;&lt;/p&gt;
&lt;p&gt;This is a pretty significant piece of software. It renders &lt;a href="https://www.rstudio.com/products/shiny-server-pro/"&gt;Shiny Server Pro&lt;/a&gt; redundant. As this solution provides authentication, scalability, decreases maintenance (containers) and enables any web app to be running behind the scenes. So you could have a &lt;a href="https://shiny.rstudio.com/gallery/"&gt;shiny&lt;/a&gt; app, a &lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; app, a &lt;a href="http://flask.pocoo.org/"&gt;flask&lt;/a&gt; app, &lt;a href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt;... and the end-user will simply see a website, whilst the backend has a whole range of different web applications spinning up on demand.&lt;/p&gt;
&lt;p&gt;I ran into some hurdles with &lt;a href="https://www.shinyproxy.io/documentation/getting-started/#prerequisites"&gt;these instructions&lt;/a&gt;. So I'm documenting what worked for me. &lt;strong&gt;My setup:&lt;/strong&gt; I set this up once on a Dell XPS 13 with a fresh install of Ubuntu 16.04.3 LTS and a Ubuntu 16.04.03 Azure VM.&lt;/p&gt;
&lt;h2 id="pre-requisites-%2F-assumptions"&gt;Pre-requisites / Assumptions &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#pre-requisites-%2F-assumptions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="docker"&gt;Docker &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#docker"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you don't have &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; installed yet, I highly recommend running through &lt;a href="https://docs.docker.com/get-started/"&gt;Part 1: Orientation and setup&lt;/a&gt; to &lt;a href="https://docs.docker.com/get-started/part3/"&gt;Part 3: Services&lt;/a&gt; of &lt;a href="https://docs.docker.com/get-started/"&gt;Docker's Getting Started Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If running the following commands return similar console prints you should be fine to continue on.&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; &lt;span class="token parameter variable"&gt;-v&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Docker version 17.06.2-ce, build cec0b72&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; run hello-world&lt;br /&gt;&lt;span class="token comment"&gt;# Hello from Docker!&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# This message shows that your installation appears to be working correctly.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="docker-problems-encountered-for-ubuntu-16"&gt;Docker Problems Encountered for Ubuntu 16 &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#docker-problems-encountered-for-ubuntu-16"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The most time consuming part of the setup were &lt;a href="https://support.openanalytics.eu/t/shinyproxy-on-ubuntu-16-04/38/4"&gt;the instructions for Ubuntu 16&lt;/a&gt; on the &lt;a href="https://www.shinyproxy.io/"&gt;shinyproxy site&lt;/a&gt; guiding modification of &lt;code&gt;/lib/systemd/system/docker.service&lt;/code&gt;. Per the documentation on Shinyproxy:&lt;/p&gt;
&lt;p&gt;&lt;img alt="shinyproxy-docker-instructions" src="https://lukesingham.com/content/images/2017/09/shinyproxy-ubuntu16-docker-config.png" /&gt;&lt;/p&gt;
&lt;p&gt;Running this configuration produced the following error:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; systemctl restart &lt;span class="token function"&gt;docker&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="solution"&gt;Solution &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#solution"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Instead, edit &lt;code&gt;/lib/systemd/system/docker.service&lt;/code&gt; and set &lt;code&gt;ExecStart&lt;/code&gt; to:&lt;/p&gt;
&lt;pre class="language-docker"&gt;&lt;code class="language-docker"&gt;ExecStart=/usr/bin/dockerd -H fd:// -D -H tcp://127.0.0.1:2375&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why? Shinyproxy will look to talk to the docker daemon on &lt;code&gt;tcp://127.0.0.1:2375&lt;/code&gt;. If it can't, then the application won't work.&lt;/p&gt;
&lt;p&gt;Ensure that you restart docker after editing the config with the following commands:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; systemctl daemon-reload&lt;br /&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; systemctl restart &lt;span class="token function"&gt;docker&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="java8"&gt;Java8 &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#java8"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Shinyproxy requires a minimum of &lt;a href="http://www.oracle.com/technetwork/java/javase/overview/java8-2100321.html"&gt;Java 8&lt;/a&gt;. I followed the advice per &lt;a href="https://www.shinyproxy.io/documentation/getting-started/"&gt;shinyproxy.io&lt;/a&gt; and installed the OpenJDK &lt;a href="http://zulu.org/"&gt;Zulu&lt;/a&gt;. &lt;a href="https://www.quora.com/What-is-it-like-to-use-Azul-Systems-Zulu-JVM/answer/Matt-Schuetze"&gt;This Quora answer from the product manager of Zulu&lt;/a&gt; gives some context behind this JDK.&lt;/p&gt;
&lt;p&gt;Run the following at the command line:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;$ &lt;span class="token function"&gt;java&lt;/span&gt; &lt;span class="token parameter variable"&gt;-version&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# openjdk version "1.8.0_144"&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# OpenJDK Runtime Environment (Zulu 8.23.0.3-linux64) (build 1.8.0_144-b01)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# OpenJDK 64-Bit Server VM (Zulu 8.23.0.3-linux64) (build 25.144-b01, mixed mode)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have Java 8 then continue. N.B. Zulu 8.xx.x.x is Java 8. Otherwise, run the following commands to install:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; apt-key adv &lt;span class="token parameter variable"&gt;--keyserver&lt;/span&gt; hkp://keyserver.ubuntu.com:80 --recv-keys 0x219BD9C9&lt;br /&gt;$ &lt;span class="token assign-left variable"&gt;apt_source&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'deb http://repos.azulsystems.com/debian stable main'&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token assign-left variable"&gt;apt_list&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'/etc/apt/sources.list.d/zulu.list'&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;echo&lt;/span&gt; &lt;span class="token string"&gt;"&lt;span class="token variable"&gt;$apt_source&lt;/span&gt;"&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;sudo&lt;/span&gt; &lt;span class="token function"&gt;tee&lt;/span&gt; &lt;span class="token string"&gt;"&lt;span class="token variable"&gt;$apt_list&lt;/span&gt;"&lt;/span&gt; &lt;span class="token operator"&gt;&gt;&lt;/span&gt; /dev/null&lt;br /&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; &lt;span class="token function"&gt;apt-get&lt;/span&gt; update&lt;br /&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; &lt;span class="token function"&gt;apt-get&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; zulu-8&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;N.B.&lt;/strong&gt; I did experience a maven build fail when running &lt;code&gt;mvn -U clean install&lt;/code&gt; on a Mac with a Java9 runtime. Uninstalling Java 9 and running &lt;code&gt;brew cask install java8&lt;/code&gt; fixed the problem.&lt;/p&gt;
&lt;h2 id="download-and-compile-shiny-proxy"&gt;Download and Compile Shiny Proxy &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#download-and-compile-shiny-proxy"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are two options for downloading the shinyproxy software.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option 1&lt;/strong&gt; - I cloned the &lt;a href="https://github.com/openanalytics/shinyproxy/"&gt;shinyproxy repo&lt;/a&gt;. I did not have &lt;a href="https://maven.apache.org/"&gt;apache maven&lt;/a&gt; installed so I needed to &lt;a href="https://maven.apache.org/install.html"&gt;run through the installation of maven first&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Clone the repo&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;git&lt;/span&gt; clone https://github.com/openanalytics/shinyproxy.git&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Change directory&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; shinyproxy/&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Compile the program&lt;/span&gt;&lt;br /&gt;$ mvn &lt;span class="token parameter variable"&gt;-U&lt;/span&gt; clean &lt;span class="token function"&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Option 2&lt;/strong&gt; - You can also go to the &lt;a href="https://www.shinyproxy.io/downloads/"&gt;downloads page&lt;/a&gt; and select the latest file for your particular operating system.&lt;/p&gt;
&lt;h2 id="pull-the-shiny-app-containers"&gt;Pull the shiny app containers &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#pull-the-shiny-app-containers"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We now have shinyproxy ready to run containerised applications. However, we don't have the images that shinyproxy is expecting. We need to pull those first:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Pull the shiny app images&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;sudo&lt;/span&gt; &lt;span class="token function"&gt;docker&lt;/span&gt; pull openanalytics/shinyproxy-demo&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Check they are now in the list of docker images&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; images &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;grep&lt;/span&gt; shinyproxy&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="run-shiny-proxy"&gt;Run Shiny Proxy &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#run-shiny-proxy"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Run the following commands:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Ensure you are in the right directory&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; ~/shinyproxy/target/&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Run shinyproxy&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;java&lt;/span&gt; &lt;span class="token parameter variable"&gt;-jar&lt;/span&gt; shinyproxy-1.0.0.jar&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point you should now be able to navigate to &lt;a href="http://localhost:8080/"&gt;http://localhost:8080&lt;/a&gt; and see the sign in page and login with 'tesla' and 'password' as username and password respectively. If you are doing this on a remote server, test the application is up and running by running:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Print the html of the site to the terminal&lt;/span&gt;&lt;br /&gt;&lt;span class="token function"&gt;curl&lt;/span&gt; http://localhost:8080&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="shinyproxy-login" src="https://lukesingham.com/content/images/2017/09/shinyproxy-login.png" /&gt;&lt;/p&gt;
&lt;p&gt;Once logged in launch an application.&lt;/p&gt;
&lt;p&gt;&lt;img alt="shinyproxy-select-app" src="https://lukesingham.com/content/images/2017/09/shinyproxy-select-app.png" /&gt;&lt;/p&gt;
&lt;p&gt;And bingo we have a containerised and authenticated shiny environment.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/09/shinyproxy-shiny-app.png" /&gt;&lt;/p&gt;
&lt;h2 id="adding-additional-shiny-apps"&gt;Adding Additional Shiny Apps &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#adding-additional-shiny-apps"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.shinyproxy.io/documentation/deployment/"&gt;Shinyproxy docs&lt;/a&gt; provide a ready to go shiny application with a &lt;a href="https://docs.docker.com/engine/reference/builder/"&gt;dockerfile&lt;/a&gt; to build the image. Of course, to use shinyproxy for your own custom shiny applications the dockerfile in the &lt;a href="https://github.com/openanalytics/shinyproxy-template"&gt;shinyproxy-template repo&lt;/a&gt; acts as a template to follow. I'm going to go through the process of adding shinyproxy's pre-built shiny app.&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Clone the shiny app repo&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;git&lt;/span&gt; clone https://github.com/openanalytics/shinyproxy-template.git&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Change into the repo&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; shinyproxy-template/&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Build the image&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; build &lt;span class="token parameter variable"&gt;-t&lt;/span&gt; openanalytics/shinyproxy-template &lt;span class="token builtin class-name"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Check the image is now available in docker&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; images &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;grep&lt;/span&gt; &lt;span class="token string"&gt;"shinyproxy-template\|REPOSITORY"&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# openanalytics/shinyproxy-template   latest              16e8c49e2261        25 minutes ago      851MB&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Check the shiny app runs normally outside shinyproxy&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; run &lt;span class="token parameter variable"&gt;-it&lt;/span&gt; &lt;span class="token parameter variable"&gt;-p&lt;/span&gt; &lt;span class="token number"&gt;3838&lt;/span&gt;:3838  openanalytics/shinyproxy-template&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The new shiny app should now be running on &lt;a href="http://0.0.0.0:3838/"&gt;http://0.0.0.0:3838/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="additional-shiny-app" src="https://lukesingham.com/content/images/2017/09/additional-shiny-app.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now we need to tell shinyproxy to include this additional shiny app by creating and editing an &lt;code&gt;application.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Ensure you are in the right directory&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; ~/shinyproxy/target/&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Create application.yml from repo template&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;curl&lt;/span&gt; https://raw.githubusercontent.com/openanalytics/shinyproxy/master/src/main/resources/application-demo.yml &lt;span class="token operator"&gt;&gt;&lt;/span&gt; application.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now need to add our new shiny app to the &lt;code&gt;application.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class="language-yaml"&gt;&lt;code class="language-yaml"&gt;&lt;span class="token key atrule"&gt;apps&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class="token punctuation"&gt;-&lt;/span&gt; &lt;span class="token key atrule"&gt;name&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; euler&lt;br /&gt;    &lt;span class="token key atrule"&gt;display-name&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; Euler's number&lt;br /&gt;    &lt;span class="token key atrule"&gt;description&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; Adding another app to shinyproxy&lt;br /&gt;    &lt;span class="token key atrule"&gt;docker-cmd&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;"R"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"-e shiny::runApp('/root/euler')"&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="token key atrule"&gt;docker-image&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; openanalytics/shinyproxy&lt;span class="token punctuation"&gt;-&lt;/span&gt;template&lt;br /&gt;    &lt;span class="token key atrule"&gt;groups&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; scientists&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I'm going to run shinyproxy again to confirm the change has been successful.&lt;/p&gt;
&lt;p&gt;&lt;img alt="add-another-shiny-app" src="https://lukesingham.com/content/images/2017/09/add-another-shiny-app.png" /&gt;&lt;/p&gt;
&lt;p&gt;And does the application launch&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/09/euler-app-running.png" /&gt;&lt;/p&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;h2 id="adding-additional-non-shiny-apps"&gt;Adding Additional non-Shiny Apps &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#adding-additional-non-shiny-apps"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I'm going with a very basic 'hello world' flask app. The main issue here is configuring the ports for shinyproxy to pick up the app. Since shiny by default runs on port 3838, I mapped the containerised flask app to run on port 3838 too. I pushed &lt;a href="https://github.com/ucg8j/flask-port3838-container"&gt;a flask repo&lt;/a&gt; to github where I adjusted the 'hello world' &lt;a href="https://github.com/ucg8j/flask-port3838-container/blob/master/app.py"&gt;flask app&lt;/a&gt; on line 28 to run on port 3838 (inside the container) and the &lt;a href="https://github.com/ucg8j/flask-port3838-container/blob/master/Dockerfile"&gt;dockerfile&lt;/a&gt; to expose the container's port 3838 (line 14).&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Clone repo&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;git&lt;/span&gt; clone https://github.com/ucg8j/flask-port3838-container.git&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Change directory&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; flask-port3838-container/&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Build image&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; build &lt;span class="token parameter variable"&gt;-t&lt;/span&gt; flaskapp &lt;span class="token builtin class-name"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Test it runs as a docker container&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token function"&gt;docker&lt;/span&gt; run &lt;span class="token parameter variable"&gt;-p&lt;/span&gt; &lt;span class="token number"&gt;4000&lt;/span&gt;:3838 flaskapp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You'll note that I am passing the publish argument &lt;code&gt;-p 4000:3838&lt;/code&gt;. This allows you to map a container's port to the port of your host in the format of &lt;code&gt;hostport:containerport&lt;/code&gt;. Since I've configured the flask docker container to port 3838 to mimic a shiny app I'll see whether I can manually map it to my computer's localhost of port 4000. That way I'll know that shinyproxy &lt;em&gt;should&lt;/em&gt; be able to do the same.&lt;/p&gt;
&lt;p&gt;&lt;img alt="flask-hello-world" src="https://lukesingham.com/content/images/2017/09/flask-hello-world.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now to add the flask hello world image to shinyproxy by appending it to the app similar to the way we did with the additional shiny app:&lt;/p&gt;
&lt;pre class="language-yaml"&gt;&lt;code class="language-yaml"&gt;&lt;span class="token key atrule"&gt;apps&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt;&lt;br /&gt;  &lt;span class="token punctuation"&gt;-&lt;/span&gt; &lt;span class="token key atrule"&gt;name&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; flaskapp&lt;br /&gt;    &lt;span class="token key atrule"&gt;display-name&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; Demo Flask app&lt;br /&gt;    &lt;span class="token key atrule"&gt;description&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; Adding another non shiny app to shinyproxy&lt;br /&gt;    &lt;span class="token key atrule"&gt;docker-cmd&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;"python"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"app.py"&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="token key atrule"&gt;docker-image&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; flaskapp&lt;br /&gt;    &lt;span class="token key atrule"&gt;groups&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; scientists&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now (re)start shiny proxy &lt;code&gt;java -jar shinyproxy-1.0.0.jar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="add-flask-app" src="https://lukesingham.com/content/images/2017/10/add-flask-app.gif" /&gt;&lt;/p&gt;
&lt;h3 id="auth"&gt;Auth &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#auth"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;By default the authentication is setup to use a demo ldap server &lt;code&gt;ldap://ldap.forumsys.com:389/dc=example,dc=com&lt;/code&gt; for more details visit &lt;a href="http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/"&gt;this page&lt;/a&gt;. I'm going to switch this to use the &lt;code&gt;simple&lt;/code&gt; authentication. I'm also going to change one of the passwords to be confident these changes are taking effect. The top half of my &lt;code&gt;application.yml&lt;/code&gt; file now looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="application-switch-auth-to-simple" src="https://lukesingham.com/content/images/2017/09/application-switch-auth-to-simple.png" /&gt;&lt;/p&gt;
&lt;h2 id="deploy-on-a-cloud-service-(nginx-config)"&gt;Deploy on a cloud service (nginx config) &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#deploy-on-a-cloud-service-(nginx-config)"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point it would be nice to have this on the cloud. Using &lt;a href="https://nginx.org/en/"&gt;nginx&lt;/a&gt; the following config worked for me which was an adaption of the config listed on the &lt;a href="https://www.shinyproxy.io/documentation/security/"&gt;shinyproxy site&lt;/a&gt;. The box I was using was an &lt;a href="https://azure.microsoft.com/en-gb/services/virtual-machines/"&gt;Azure VM&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="language-nginx"&gt;&lt;code class="language-nginx"&gt;&lt;span class="token comment"&gt;# Navigate into the nginx config&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;cd&lt;/span&gt; /etc/nginx/sites-available&lt;br /&gt;&lt;span class="token comment"&gt;# print the config that works for me&lt;/span&gt;&lt;br /&gt;$ cat default&lt;br /&gt;&lt;span class="token comment"&gt;# Default server configuration&lt;/span&gt;&lt;br /&gt;server&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;listen&lt;/span&gt; &lt;span class="token number"&gt;80&lt;/span&gt; default_server&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;listen&lt;/span&gt; [::]:80 default_server&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;root&lt;/span&gt; /var/www/html&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="token comment"&gt;# Add index.php to the list if you are using PHP&lt;/span&gt;&lt;br /&gt;  &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;index&lt;/span&gt; index.html index.htm index.nginx-debian.html&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;server_name&lt;/span&gt; **put your dns or domain here**&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;location&lt;/span&gt; /&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_pass&lt;/span&gt;                            http://127.0.0.1:8090/&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_http_version&lt;/span&gt;                    1.1&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_set_header&lt;/span&gt; Upgrade              &lt;span class="token variable"&gt;$http_upgrade&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_set_header&lt;/span&gt; Connection           &lt;span class="token string"&gt;"upgrade"&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_read_timeout&lt;/span&gt;                    &lt;span class="token number"&gt;600s&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_redirect&lt;/span&gt;                        &lt;span class="token boolean"&gt;off&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_set_header&lt;/span&gt; Host                 &lt;span class="token variable"&gt;$http_host&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_set_header&lt;/span&gt; X-Real-IP            &lt;span class="token variable"&gt;$remote_addr&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_set_header&lt;/span&gt; X-Forwarded-For      &lt;span class="token variable"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class="token directive"&gt;&lt;span class="token keyword"&gt;proxy_set_header&lt;/span&gt; X-Forwarded-Protocol &lt;span class="token variable"&gt;$scheme&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you have shinyproxy running on a cloud server, you may want to leave the application running without having a terminal open. To run leave shinyproxy running in the background run the following:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token function"&gt;nohup&lt;/span&gt; &lt;span class="token function"&gt;java&lt;/span&gt; &lt;span class="token parameter variable"&gt;-jar&lt;/span&gt; shinyproxy-1.0.0.jar &lt;span class="token operator"&gt;&amp;amp;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;nohup&lt;/code&gt; is not a permanent solution. For instance, if your server goes down, shinyproxy will not automatically reboot. &lt;code&gt;nohup&lt;/code&gt; did allow me to quickly get the app running in the background. Check the app, discover issues I needed to address then find the process by running &lt;code&gt;ps aux | grep java&lt;/code&gt; kill that process... rinse and repeat until complete. To leave this permanently on a Ubuntu 16 server the &lt;a href="https://docs.spring.io/"&gt;Spring documentation&lt;/a&gt; has &lt;a href="https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html#deployment-systemd-service"&gt;a configuration guide for setting this as a system service&lt;/a&gt;. Additionally, &lt;a href="https://stackoverflow.com/a/22121547/3691003"&gt;this SO post&lt;/a&gt; is also very helpful.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#conclusion"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Shinyproxy is a great contribution to the R/Shiny community by the team at &lt;a href="https://www.openanalytics.eu/"&gt;openanalytics&lt;/a&gt;. So a big thank you to them! &lt;em&gt;Productionising&lt;/em&gt; shiny apps can be a bit of a pain considering the open source shiny server limitations (no authentication, no concurrency and no resource monitoring). Even accepting those limitations, &lt;a href="https://lukesingham.com/using-package-management-in-r/"&gt;dependency management of R applications&lt;/a&gt; is not widely practiced. Even when R applications use &lt;a href="https://rstudio.github.io/packrat/"&gt;packrat&lt;/a&gt;, language level dependency management doesn't prevent your software breaking due to different system level requirements. Hence, the generalisation of running a website that proxies to containerised applications &lt;em&gt;should&lt;/em&gt; be an incredibly reliable architecture.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources &lt;a class="direct-link" href="https://lukesingham.com/shiny-containers-with-shinyproxy/#resources"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lukesingham.com/how-to-deploy-plotlys-dash-using-shinyproxy/"&gt;How to deploy Dash apps on Shinyproxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/40187306/3691003"&gt;Helpful SO post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linode.com/docs/web-servers/nginx/how-to-configure-nginx"&gt;Configuring nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html"&gt;Spring configuration options i.e. &lt;code&gt;application.yml&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Wed, 11 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/shiny-containers-with-shinyproxy/</guid></item><item><title>How to get windows copy paste events with shell hook.</title><link>https://xosh.org/catch-copy-paste-from-explorer-using-shell-extension/</link><description>This article was originally posted here by the author, that is no longer available.
How to catch copy paste from explorer using shell extension? ICopyHook alternative for files and folder How to catch copy paste from explorer using shell extension? ICopyHook alternative for files and folder Howto trap copy paste event from explorer to do your custom processing or even Howto replace/substitute the copy-paste/cut-paste operation with your own copy or move or anything else?</description><author>XOSH.ORG</author><pubDate>Wed, 11 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xosh.org/catch-copy-paste-from-explorer-using-shell-extension/</guid></item><item><title>Detecting state changes with Redux-Saga</title><link>https://goshacmd.com/detect-state-change-redux-saga/</link><author>Gosha Spark</author><pubDate>Wed, 11 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/detect-state-change-redux-saga/</guid></item><item><title>Fighting Cliqz in Firefox</title><link>http://blog.pythonaro.com/2017/10/fighting-cliqz-in-firefox.html</link><description>&lt;p&gt;Mozilla recently &lt;a href="https://news.ycombinator.com/item?id=15421708" target="_blank"&gt;announced&lt;/a&gt; that some of their German users downloading Firefox will receive a version that tracks some of their web activity, reporting it to Cliqz.com. In the wake of this development, which is pretty awful from a privacy perspective, I went spelunking into my version of FF to see if anything had been enabled already in my build.&lt;/p&gt;
&lt;p&gt;To my horror, cliqz.com is already mentioned in a few places, despite me never installing anything related to it. If you enter about:config in the address bar and search for cliqz, a few entries will pop up:&lt;br /&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHiy5bih0NwTag1vZ-vAKmLACHGqdC7SDoLJBZlT3-qfqW72OgrwctwAx1Np9FTSQbtwjJ41EozdgEB3SCFs2wRiYOTyGt5czrePuR0rMsaFRd_YgIbAXAIl9xKPS5DYU1bfDF/s1600/Screen+Shot+2017-10-10+at+13.29.39.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHiy5bih0NwTag1vZ-vAKmLACHGqdC7SDoLJBZlT3-qfqW72OgrwctwAx1Np9FTSQbtwjJ41EozdgEB3SCFs2wRiYOTyGt5czrePuR0rMsaFRd_YgIbAXAIl9xKPS5DYU1bfDF/s640/Screen+Shot+2017-10-10+at+13.29.39.png" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;
Straight out of the gate, it looks like something from cliqz.com has been whitelisted. What is it?&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;social.*&lt;/code&gt; preferences are related to &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Social_API"&gt;SocialAPI&lt;/a&gt; Services, a sort of framework to integrate social networks into Firefox. It was introduced several years ago but very few people actually use it or know about it. If you look up the related preferences, a few more entries are present:&lt;br /&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA14GIChGnQ4FM2JfySiFinLc0GXEzsGnTAXTl5qrn4tn7ce7giPyo61N5fY-gx2OpMOLtO-I72iFC2skSbQlukA6HmgroxBCyLVvrX3diRQWEcR38Y5Qqi5YwovCgvyS-dDY1/s1600/Screen+Shot+2017-10-10+at+13.32.15.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA14GIChGnQ4FM2JfySiFinLc0GXEzsGnTAXTl5qrn4tn7ce7giPyo61N5fY-gx2OpMOLtO-I72iFC2skSbQlukA6HmgroxBCyLVvrX3diRQWEcR38Y5Qqi5YwovCgvyS-dDY1/s640/Screen+Shot+2017-10-10+at+13.32.15.png" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;
If you are a fan of this sort of thing, you can go to that address &lt;a href="https://activations.cdn.mozilla.net/"&gt;https://activations.cdn.mozilla.net&lt;/a&gt; and install some of the available providers. I have no idea whether they still work or not; among others, delicious.com has recently been sold and it's in read-only mode, so that's unlikely to be useful.&lt;/p&gt;
&lt;p&gt;I personally disabled it all (that &lt;code&gt;social.remote-install.enabled&lt;/code&gt; freaked me out) by double-clicking all boolean properties (turning them to false) and double-clicking then clearing out social.whitelist.&lt;/p&gt;
&lt;p&gt;The other mentions of cliqz seem to be special-casing whitelists aimed at making an extension work around some of the recent changes in the Firefox extensibility framework. If I understand correctly, &lt;code&gt;dom.ipc.cpows.allow-cpows-in-compat-addons&lt;/code&gt; allows Cross-Process Object Wrappers (an internal communication mechanism that should slowly be removed) to be used even if the extension is marked as compatible with the new multiprocess architecture; and &lt;code&gt;extensions.legacy.exceptions&lt;/code&gt; exempts the listed extensions from being marked as Legacy.&lt;/p&gt;
&lt;p&gt;In those whitelists, there is one called testpilot@cliqz.com. &lt;a href="https://testpilot.firefox.com/"&gt;Test Pilot&lt;/a&gt; is an official Firefox add-on from Mozilla that will periodically publish some proposed additions to the browser, allowing users to enable them, test them out, give feedback and so on. I personally like it, some of the proposed features are actually pretty good (although it doesn't look like any of them ever made it to the main build); considering its complexity (an extension-installing extension) it makes sense that it might require some special privileges, and after all it's an official Mozilla feature so why not?&lt;/p&gt;
&lt;p&gt;Well, it looks like Mozilla is using cliqz.com to gather remote info about TestPilot usage, which is very disappointing. TestPilot was marketed as an official Mozilla project, there was no mention of third parties involved. I won't disable TestPilot, but I am again very disappointed in their cavalier attitude with my usage data.&lt;/p&gt;
&lt;p&gt;To conclude, it looks like the "synergy" between Mozilla and Cliqz was already underway before the latest announcement. It's likely that more defensive hacks will be required in the near future to keep user-tracking at bay in Firefox. As a long-time fan of Mozilla since the '90s, this development is disappointing.&lt;/p&gt;</description><author>Subclassed</author><pubDate>Tue, 10 Oct 2017 16:18:31 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2017/10/fighting-cliqz-in-firefox.html</guid></item><item><title>1791: We Did Not See This Coming</title><link>https://www.danstroot.com/posts/2017-10-10-1791-we-did-not-see-this-coming</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/armory1.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;The Second Amendment was passed fifteen years after the American Revolution, in 1791, as part of the Bill of Rights. This was just three years after the Constitution was ratified in 1788. The complete Second Amendment of the United States Constitution reads: "A well regulated Militia, being necessary to the security of a free State, the right of the people to keep and bear Arms, shall not be infringed." James Madison originally proposed the Second Amendment as a way to provide more power to state militias. It begins with the concept...&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2017-10-10-1791-we-did-not-see-this-coming"&gt;1791: We Did Not See This Coming&lt;/a&gt; first appeared on &lt;a href="https://www.danstroot.com"&gt;Dan Stroot's Blog&lt;/a&gt;</description><author>Dan Stroot</author><pubDate>Tue, 10 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2017-10-10-1791-we-did-not-see-this-coming</guid></item><item><title>A technique for selection sampling (sampling without replacement)</title><link>https://bastian.rieck.me/blog/2017/selection_sampling/</link><description>&lt;p&gt;Many applications require the selection of a subset of objects from
a larger set. For example, suppose you are down-sampling a large data
set by choosing the indices that you want to keep at random. If you are
satisfied with obtaining duplicate indices (in essence, if you are
sampling &lt;em&gt;with&lt;/em&gt; replacement), this is a trivial matter in most
programming language. Python certainly makes this absurdly easy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&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="n"&gt;n&lt;/span&gt;&lt;span class="p"&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;_&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="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But what about sampling &lt;em&gt;without&lt;/em&gt; replacement? More precisely, what if
you require the selection of $k$ indices from an array of $n$ values
without choosing duplicate values but still want the probability of
choosing a certain element to be uniform? Well, if you use Python, you
are in luck again:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sample_without_replacement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&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="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But what about other programming languages that may not have similar
builtin functionality, such as C++? In this case, a very simple and
elegant technique is given by none other than the great &lt;a href="http://www-cs-faculty.stanford.edu/~knuth"&gt;Donald E.
Knuth&lt;/a&gt;. The following
algorithm originally was given in &lt;em&gt;The Art of Computer Programming&lt;/em&gt;,
Volume 2, Section 3.4.2 on p. 137. Briefly put, it works like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Set $t = 0$ and $m = 0$. Here, $m$ represents the number of items selected
so far, while $t$ is the total number of items that have already been
traversed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate a random number $U$ that is uniformly distributed between
zero and one.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If $(N-t) U \geq n-m$, &lt;em&gt;skip&lt;/em&gt; the current item by increasing $t$ by 1 and
going back to step 2. Else, &lt;em&gt;select&lt;/em&gt; the current item by increasing
both $t$ and $m$ by 1. Afterwards, either go back to step 2 or stop
the algorithm (if sufficiently many items have been sampled
already).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A very basic implementation of this algorithm (in C++) is given in the
gist below:&lt;/p&gt;

&lt;p&gt;I do not know about you, but my gut reaction upon seeing this algorithm
for the first time was &lt;em&gt;How can this possibly work&lt;/em&gt;? So, let us briefly
prove the algorithm to be correct. Basically, we have to show that every
item has the same probability of being chosen. The key insight is to
realize that the probability has to change depending on the number of
elements that have already been selected. More precisely, we need to
determine the probability of choosing item $t+1$ if $m$ items have
already been selected. This requires some combinatorics. There are
$\binom{N - t}{n -m}$ ways of choosing $n$ items from $N$ such that $m$ items are picked as
the first $t$ items. Or, equivalently, these are the number of potential
permutations of the &lt;em&gt;remaining&lt;/em&gt; $n-m$ elements. Out of these, we are
interested in all the ones that contain item $t+1$—but this is
easy, because we can just take that item as granted and count the
&lt;em&gt;remaining&lt;/em&gt; combinations as $\binom{N-t-1}{n-m-1}$, i.e. the number of ways to
choose $n-m-1$ items out of $N-t-1$
ones. The quotient of these two numbers is exactly the probability with
which we must choose item $t+1$ if we want to have a uniform probability
for choosing a certain item. This quotient turns out to be
$\frac{n-m}{N-t}$, which looks familiar. Finally, note that since $U$ was chosen to
be uniformly distributed between zero and one, the condition $(N-t)U
\geq n-m$ in the algorithm is satisfied with the required probability.
Consequently, this method samples without replacement in the required
manner!&lt;/p&gt;
&lt;p&gt;If you are interested or require a more efficient algorithm, please
refer to the paper &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.94.1689&amp;amp;rep=rep1&amp;amp;type=pdf"&gt;&lt;em&gt;An Efficient Algorithm for Sequential Random
Sampling&lt;/em&gt;&lt;/a&gt;
by Jeffrey Scott Vitter in &lt;em&gt;ACM Transactions on Mathematical Software&lt;/em&gt;,
Volume 13, Issue 1, pp. 58–67, for more details. The paper
&lt;em&gt;should&lt;/em&gt; be available free-of-charge from the link provided above, but
there is also
a &lt;a href="https://hal.inria.fr/docs/00/07/59/29/PDF/RR-0624.pdf"&gt;mirror&lt;/a&gt;
available, thanks to the good folks at &lt;a href="https://www.inria.fr"&gt;INRIA&lt;/a&gt;,
who require their publications to be kept in an open archive. Time
permitting, I might provide a second blog post and implementation about
the more efficient algorithm.&lt;/p&gt;
&lt;p&gt;That is all for now, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 08 Oct 2017 22:54:03 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/selection_sampling/</guid></item><item><title>Hacking Temperature Radio Sensors and Graphing with Prometheus</title><link>https://blog.nobugware.com/post/2017/hacking_temperature_radio_sensors_and_graphing_with_prometheus/</link><description>One year ago I&amp;rsquo;ve started to collect temperature from my house using Acurite sensors.
These sensors are not too expensive and good quality but the &amp;ldquo;base&amp;rdquo; aka the radio receiver connected to internet is costly and totally closed, it&amp;rsquo;s sending your data to the Cloud™, it&amp;rsquo;s not just Acurite, all those &amp;ldquo;IOT&amp;rdquo; devices are generally poor on the software side.
Receiving radio data Most of these sensors have their protocols already reverse engineered you only need the radio receiver part.</description><author>Fabrice Aneche</author><pubDate>Sun, 08 Oct 2017 21:28:46 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2017/hacking_temperature_radio_sensors_and_graphing_with_prometheus/</guid></item><item><title>Notes on PacBSD</title><link>https://blog.nobugware.com/post/2017/notes_on_pacbsd/</link><description>PacBSD is a FreeBSD kernel/world with a PacMan Arch package manager and an optionnal OpenRC init system.
In short ZFS, DTrace and the FreeBSD kernel but the simplicity of Arch for packages management but the Gentoo init.
It&amp;rsquo;s experimental, uncompleted, unfinished, lacks proper documentations but it works and could be/should be the solution we are waiting for :).
Here is some notes on installation (in QEMU), note that it slightly diverges from the official install since it&amp;rsquo;s using a whole ZFS disk, so no GPT.</description><author>Fabrice Aneche</author><pubDate>Sun, 08 Oct 2017 17:57:56 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2017/notes_on_pacbsd/</guid></item><item><title>Quick Thoughts</title><link>https://peterlyons.com/problog/2017/10/quick-thoughts/</link><description>&lt;h3 id="code-coverage"&gt;Code Coverage&lt;/h3&gt;
&lt;p&gt;Organizing code so my 100% tested code is kept separate from other dev's 70% tested code so at least part of my coverage report is green.&lt;/p&gt;
&lt;h3 id="flat-ui"&gt;Flat UI&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.nngroup.com/articles/flat-ui-less-attention-cause-uncertainty"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="dynamodb-tables"&gt;DynamoDB Tables&lt;/h3&gt;
&lt;p&gt;WTF is with dynamodb not having the concept of a database. This is terrible. Now we need to configure every table name for each deployment?&lt;/p&gt;
&lt;h3 id="terraform-drop"&gt;Terraform Drop&lt;/h3&gt;
&lt;p&gt;Heads up, if you use terraform and change your dynamodb table key schema, it will drop and recreate your table without any extra warning.&lt;/p&gt;
&lt;h3 id="deterministic-builds"&gt;Deterministic Builds&lt;/h3&gt;
&lt;p&gt;TIL debian has a strip-nondetermisism perl script you can feed archives (zip, tar, etc) and it will make them deterministic&lt;/p&gt;
&lt;h3 id="almost-swiped"&gt;Almost Swiped&lt;/h3&gt;
&lt;p&gt;Mobile interaction annoyance: If I swipe to dismiss a notification, but not far enough so it stays there, then I swipe it again immediately, I'm fucking trying to dismiss it, cut me some slack and dismiss it already.&lt;/p&gt;
&lt;h3 id="hidden-passwords"&gt;Hidden Passwords&lt;/h3&gt;
&lt;p&gt;I want mobile password inputs to take up the entire screen with keyboard letters and FFS allow me to show the password. 95% of the time shoulder surfing is not a threat to me.&lt;/p&gt;
&lt;h3 id="slack-interviews"&gt;Slack Interviews&lt;/h3&gt;
&lt;p&gt;I don't do whiteboard interviews or coding algorithms. I just ask the candidate to set up some reasonable slack notification preferences.&lt;/p&gt;
&lt;h3 id="slack-accounts"&gt;Slack Accounts&lt;/h3&gt;
&lt;p&gt;If only we could rewind time and have slack use a single account model&lt;/p&gt;
&lt;h3 id="joi-vs-json-schema"&gt;joi vs JSON schema&lt;/h3&gt;
&lt;p&gt;I switched from joi to basic json schema objects for broadest tool support and integration and because manipulating POJOs with JS is really easy. But now the verbosity is getting to me and I might switch back to joi.&lt;/p&gt;
&lt;h3 id="xkcd-compiling"&gt;XKCD Compiling&lt;/h3&gt;
&lt;p&gt;Instead of "compiling" my excuse for slacking off is "terraforming"&lt;/p&gt;
&lt;h3 id="api-gateway-error-messages"&gt;API Gateway error messages&lt;/h3&gt;
&lt;p&gt;For AWS API Gateway errors, use JSON with {"message": errorMessage} so your application errors and the default APIG ones have the same schema&lt;/p&gt;
&lt;h3 id="terraform-apply-errors"&gt;Terraform apply errors&lt;/h3&gt;
&lt;p&gt;terraform doesn't really deliver on its promise/potential. So many cases where "plan" looks good and "apply" fails at runtime. I wonder if we could build a stronger type system and move errors from apply time to plan time like elm did for javascript errors from run time to compile time.&lt;/p&gt;
&lt;h3 id="ignite-bullshit"&gt;Ignite Bullshit&lt;/h3&gt;
&lt;p&gt;Ignite presentation idea: Bullshit. 5 topics, 3 slides per topic: the pitch, why it's bullshit, the better option.&lt;/p&gt;
&lt;h3 id="shift"&gt;Shift&lt;/h3&gt;
&lt;p&gt;Maybe shift key should be last resort as a modifier key. Because you need it for normal typing, seems more ripe for mistakes vs ctrl/opt/cmd.&lt;/p&gt;
&lt;h3 id="dark-patterns"&gt;Dark Patterns&lt;/h3&gt;
&lt;p&gt;Showing a notification widget to a non-logged-in user is a dark pattern.&lt;/p&gt;
&lt;p&gt;TransUnion dark pattern. Fill out a form. Opt out of email. Submit form. Get an error about password field. All fields retain their proper values except opt-in to email is checked again.&lt;/p&gt;
&lt;h3 id="devops-tooling-woes"&gt;DevOps Tooling Woes&lt;/h3&gt;
&lt;p&gt;I really wish there was 1 fucking tool in the entire devops ecosystem that understood what a real multi-stage deployment flow should look like.&lt;/p&gt;
&lt;h3 id="terraform-variable-scope"&gt;Terraform variable scope&lt;/h3&gt;
&lt;p&gt;Terraform what the actual fuck went on with your "declarative" design? &lt;code&gt;* function_name: duplicate local. local value names must be unique&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="scrumish"&gt;Scrumish&lt;/h3&gt;
&lt;p&gt;What methodolgy do you follow? Arbitrary but we say "sprint" a bunch.&lt;/p&gt;
&lt;h3 id="awsmess"&gt;AWSmess&lt;/h3&gt;
&lt;p&gt;An open source AWS linter called awsmess&lt;/p&gt;
&lt;h3 id="code-search"&gt;Code Search&lt;/h3&gt;
&lt;p&gt;OMG If I ask to search logs/code/tech stuff for XYZ-12345 I DO NOT MEAN ("XYZ" OR "12345")&lt;/p&gt;
&lt;h3 id="object-storage"&gt;Object Storage&lt;/h3&gt;
&lt;p&gt;Nerd rage at tech companies that call S3/filesystems "Object Storage". You don't get it. Files and Objects are 2 different things to developers.&lt;/p&gt;
&lt;h3 id="hclfmt-crap"&gt;hclfmt crap&lt;/h3&gt;
&lt;p&gt;Vertically aligning equal assignment operators is terrible. Creates SCM noise. Makes things less readable.&lt;/p&gt;
&lt;h3 id="duolingo-spaced-repetition"&gt;Duolingo Spaced Repetition&lt;/h3&gt;
&lt;p&gt;Not buying their spaced repetition algorithm. Keeps asking me to re-prove that I know words like "gracias".&lt;/p&gt;
&lt;h3 id="old-man-yells-at-url"&gt;Old Man Yells at URL&lt;/h3&gt;
&lt;p&gt;The URL query string. Intended for search. Now just used for tracking and when you do a search they don't even give you a bookmarkable URL.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sun, 08 Oct 2017 06:09:20 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/10/quick-thoughts/</guid></item><item><title>Regex prime checker</title><link>https://codeexplainer.wordpress.com/2017/10/07/regex-prime-checker/</link><description>This Java snippet uses a regular expression for something way different than they were designed for: a primality check. Who is the author? After some digging I found out that the original author is Abigail and the code was originally &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2017/10/07/regex-prime-checker/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Sat, 07 Oct 2017 16:26:38 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2017/10/07/regex-prime-checker/</guid></item><item><title>Setting up Webpack, Babel and React from scratch, revisited</title><link>https://muffinman.io/blog/webpack-babel-react-revisited/</link><description>&lt;article class="article"&gt;&lt;p&gt;Last summer I wrote &lt;a href="/blog/setting-up-webpack-babel-and-react-from-scratch/"&gt;this post&lt;/a&gt;
which quickly became my most popular one to day.
With webpack 2 and 3 it got outdated, so I decided to write a new one.&lt;/p&gt;
&lt;h2 id="before-we-start"&gt;Before we start &lt;a class="anchor-link" href="#before-we-start"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;#x27;ll assume you have a basic knowledge of unix terminal, npm and JavaScript.
You did some React, but now you want to level up and learn how setup React projects from scratch.&lt;/p&gt;
&lt;p&gt;This is detailed step-by-step guide, as I&amp;#x27;ll try to explain the whole process.
If you just want code to play with, check &lt;a href="https://github.com/Stanko/webpack-babel-react-revisited"&gt;this repository&lt;/a&gt; I created for this tutorial.&lt;/p&gt;
&lt;p&gt;Every time I talk about changing a source file, I&amp;#x27;ll paste complete file&amp;#x27;s content beneath it.
You can look for &lt;code&gt;ADDED IN THIS STEP&lt;/code&gt; comments which point out specific things that changed.&lt;/p&gt;
&lt;p&gt;Please note that this tutorial is written on macOS using node 8.5.0,
but it should work on Linux and Windows without any major issues.
If you find something that is not working,
please provide a correction in the comments below.&lt;/p&gt;
&lt;h2 id="what-are-we-trying-to-build"&gt;What are we trying to build? &lt;a class="anchor-link" href="#what-are-we-trying-to-build"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Simple development setup for React applications using Webpack and Babel.
But my main goal is for people to better understand these tools and how to use them.&lt;/p&gt;
&lt;p&gt;Setup that we are going to create is minimal, but it follows the best practices
and gives you a solid ground to start from.&lt;/p&gt;
&lt;h3 id="who-am-i-and-why-should-you-listen-to-me"&gt;Who am I and why should you listen to me? &lt;a class="anchor-link" href="#who-am-i-and-why-should-you-listen-to-me"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Well, I&amp;#x27;m a principal developer at &lt;a href="https://work.co"&gt;Work&amp;amp;Co&lt;/a&gt;.
I have a lot of experience on production level React projects,
for clients like Twitter, Mastercard, Aeromexico, Hampton Creek...
&lt;a href="https://github.com/stanko/marvin"&gt;Marvin&lt;/a&gt;
&lt;span class="sidenote__text" tabindex="0"&gt;boilerplate&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;We have big plans for Marvin in the near future.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
is my creation as well,
and what I&amp;#x27;m trying to teach you is directly based on my experience on these projects.&lt;/p&gt;
&lt;h2 id="init"&gt;Init &lt;a class="anchor-link" href="#init"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Create a new folder, and &lt;code&gt;package.json&lt;/code&gt; file in it, with the following content:&lt;/p&gt;
&lt;pre class="language-json"&gt;&lt;code class="language-json code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack-babel-react-revisited&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course you can replace &amp;quot;webpack-babel-react-revisited&amp;quot; with your project name.&lt;/p&gt;
&lt;div class="spoiler"&gt;&lt;div class="spoiler__content-wrapper" id="mpf7r8gh-oepx75"&gt;&lt;div class="spoiler__content"&gt;&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;- package.json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;button class="spoiler__toggle btn btn--sm"&gt;&lt;span class="spoiler__toggle-show"&gt;Show file structure after this step&lt;/span&gt;&lt;span class="spoiler__toggle-hide"&gt;Hide file structure after this step&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;h2 id="webpack"&gt;Webpack &lt;a class="anchor-link" href="#webpack"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&amp;#x27;ll start with installing webpack for module bundling.
It will transpile and bundle our JavaScript files, compile SASS or PostCSS,
optimize images... and a bunch of other nifty things.&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; --save-dev webpack
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we need some modules.
We&amp;#x27;ll keep our source files in &lt;code&gt;src&lt;/code&gt; folder, so we need to create it.
Then create &lt;code&gt;js&lt;/code&gt; folder in the &lt;code&gt;src&lt;/code&gt; folder you just created, and &lt;code&gt;app.js&lt;/code&gt; file in it.&lt;/p&gt;
&lt;p&gt;Add a simple &lt;code&gt;console.log(&amp;#x27;Hello world!&amp;#x27;);&lt;/code&gt; to &lt;code&gt;app.js&lt;/code&gt;;&lt;/p&gt;
&lt;p&gt;Now we can run webpack from the terminal for the first time:&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;./node_modules/webpack/bin/webpack.js ./src/js/app.js --output-filename ./dist/app.bundle.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you open generated &lt;code&gt;app.bundle.js&lt;/code&gt; you&amp;#x27;ll see webpack&amp;#x27;s module handling code at the top,
and at the end you&amp;#x27;ll find our modest &lt;code&gt;console.log&lt;/code&gt;.
Webpack&amp;#x27;s code does all the work with modules&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;connecting them together while keeping them in separate scopes.
At this point we are not leveraging that (yet).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This command runs webpack using our &lt;code&gt;app.js&lt;/code&gt; as entry and outputs the result to the &lt;code&gt;dist&lt;/code&gt; folder.
As it already looks complicated we&amp;#x27;ll start moving webpack configuration to a file.&lt;/p&gt;
&lt;p&gt;Let&amp;#x27;s create &lt;code&gt;webpack.config.js&lt;/code&gt; in our project&amp;#x27;s root.
We need to add config we just used -
&lt;span class="sidenote__text" tabindex="0"&gt;only entry and output paths.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Plus &lt;code&gt;paths&lt;/code&gt; constant. I like to keep paths in the constant object, as it makes things easier to read.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// We are using node&amp;#x27;s native package &amp;#x27;path&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://nodejs.org/api/path.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;path&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Constant with our paths&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; paths &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;dist&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src/js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Webpack configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;module&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;exports&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;entry&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;output&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;path&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.bundle.js&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;#x27;ll see that we added our &lt;code&gt;app.js&lt;/code&gt; as entry and for the output
we selected &lt;code&gt;dist&lt;/code&gt; folder and &lt;code&gt;app.bundle.js&lt;/code&gt; as the filename.&lt;/p&gt;
&lt;p&gt;Now we can run webpack without inline configuration.
By default webpack looks for &lt;code&gt;webpack.config.js&lt;/code&gt; and reads config from it.&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;./node_modules/webpack/bin/webpack.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command has the exact same result as the first one.
Now let&amp;#x27;s try to make it even nicer.&lt;/p&gt;
&lt;p&gt;Open &lt;code&gt;package.json&lt;/code&gt; which at this point should look like this:&lt;/p&gt;
&lt;pre class="language-json"&gt;&lt;code class="language-json code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack-babel-react-revisited&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;devDependencies&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;webpack&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;^3.6.0&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&amp;#x27;ll add &lt;code&gt;script&lt;/code&gt; section.
In this sections, let&amp;#x27;s add &lt;code&gt;build&lt;/code&gt; task with only one command - &lt;code&gt;webpack&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="language-json"&gt;&lt;code class="language-json code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack-babel-react-revisited&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;devDependencies&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;webpack&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;^3.6.0&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;scripts&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;build&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can run it using:&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; run build
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Npm tasks allow us not to type full path to the package binary every time.
It searches for locally installed packages in the project&amp;#x27;s &lt;code&gt;node_modules&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;Again, it has the same result like the previous command,
but it is cleaner as it uses npm tasks instead of bare terminal commands.&lt;/p&gt;
&lt;p&gt;Now we have our simple &lt;code&gt;build&lt;/code&gt; process, so we can proceed with development setup.&lt;/p&gt;
&lt;div class="spoiler"&gt;&lt;div class="spoiler__content-wrapper" id="mpf7r8gi-ou29vb"&gt;&lt;div class="spoiler__content"&gt;&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;dist &lt;span class="token comment"&gt;# created by webpack when we run &amp;#x27;npm run build&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;node_modules &lt;span class="token comment"&gt;# created by npm&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;src
&lt;/span&gt;&lt;span class="code-line"&gt;  js
&lt;/span&gt;&lt;span class="code-line"&gt;    - app.js
&lt;/span&gt;&lt;span class="code-line"&gt;- package-lock.json &lt;span class="token comment"&gt;# created by npm (for node v8 and higher)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;- package.json
&lt;/span&gt;&lt;span class="code-line"&gt;- webpack.config.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;button class="spoiler__toggle btn btn--sm"&gt;&lt;span class="spoiler__toggle-show"&gt;Show file structure after this step&lt;/span&gt;&lt;span class="spoiler__toggle-hide"&gt;Hide file structure after this step&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;h3 id="webpack-dev-server"&gt;Webpack dev server &lt;a class="anchor-link" href="#webpack-dev-server"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To be able to open our application in a browser, we&amp;#x27;ll need a server.
Webpack already provides us with a &lt;a href="https://webpack.js.org/configuration/dev-server/"&gt;dev server&lt;/a&gt;.
It will server our files during development (obviosly),
but also enable us to use hot module reload (not covered by this post).&lt;/p&gt;
&lt;p&gt;Let&amp;#x27;s install it:&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; --save-dev webpack-dev-server
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&amp;#x27;s update &lt;code&gt;package.json&lt;/code&gt; right away to make it easier to run dev server.&lt;/p&gt;
&lt;pre class="language-json"&gt;&lt;code class="language-json code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack-babel-react-revisited&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;devDependencies&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;webpack&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;^3.6.0&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;webpack-dev-server&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;^2.9.1&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;&amp;quot;scripts&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;dev&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack-dev-server&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token property"&gt;&amp;quot;build&amp;quot;&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;webpack&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We added only one line: &lt;code&gt;&amp;quot;dev&amp;quot;: &amp;quot;webpack-dev-server&amp;quot;,&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now if you run&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; run dev
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;it will fire up our development server, and it is going to be available at &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;.
Now it will just list our project&amp;#x27;s files.&lt;/p&gt;
&lt;p&gt;So let&amp;#x27;s create a simple &lt;code&gt;index.html&lt;/code&gt; in the &lt;code&gt;src&lt;/code&gt; folder&lt;/p&gt;
&lt;pre class="language-html"&gt;&lt;code class="language-html code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token doctype"&gt;&lt;span class="token punctuation"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="token doctype-tag"&gt;doctype&lt;/span&gt; &lt;span class="token name"&gt;html&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class="token attr-name"&gt;charset&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;utf-8&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class="token attr-name"&gt;name&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;viewport&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="token attr-name"&gt;content&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;width=device-width&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Webpack Babel React revisited&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and update &lt;code&gt;webpack.config.js&lt;/code&gt; to use &lt;code&gt;src&lt;/code&gt; as a content base.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// We are using node&amp;#x27;s native package &amp;#x27;path&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://nodejs.org/api/path.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;path&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Constant with our paths&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; paths &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;dist&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token comment"&gt;// source folder path -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src/js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Webpack configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;module&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;exports&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;entry&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;output&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;path&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.bundle.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Dev server configuration -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Now it uses our &amp;quot;src&amp;quot; folder as a starting point&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;devServer&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;contentBase&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every time you change webpack config you need to restart webpack (or webpack dev server).&lt;/p&gt;
&lt;p&gt;Restart &lt;code&gt;npm run dev&lt;/code&gt; and visit &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;, it will just show a blank page.
No signs of our JavaScript.
To automatically inject &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags with our bundled application we&amp;#x27;ll use
&lt;a href="https://github.com/jantimon/html-webpack-plugin"&gt;html-webpack-plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="html-webpack-plugin"&gt;HTML Webpack Plugin &lt;a class="anchor-link" href="#html-webpack-plugin"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This plugin simplifies creation of HTML files to serve your webpack bundles.
Let&amp;#x27;s install it:&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; --save-dev html-webpack-plugin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once installed we need to activate it in &lt;code&gt;webpack.config.js&lt;/code&gt;.
Require it and add it to the &lt;code&gt;plugins&lt;/code&gt; section of
&lt;span class="sidenote__text" tabindex="0"&gt;the config:&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;We don't need &lt;code&gt;contentBase: paths.SRC&lt;/code&gt; anymore as it will be handled by html plugin.
So we'll remove whole &lt;code&gt;devServer&lt;/code&gt; configuration object for now.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// We are using node&amp;#x27;s native package &amp;#x27;path&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://nodejs.org/api/path.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;path&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;HtmlWebpackPlugin&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;html-webpack-plugin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// Import our plugin -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Constant with our paths&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; paths &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;dist&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src/js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Webpack configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;module&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;exports&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;entry&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;output&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;path&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.bundle.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Tell webpack to use html plugin -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// index.html is used as a template in which it&amp;#x27;ll inject bundled app.&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;plugins&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token literal-property property"&gt;template&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;index.html&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Dev server configuration -&amp;gt; REMOVED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// devServer: {&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//   contentBase: paths.SRC,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// },&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we restart &lt;code&gt;dev&lt;/code&gt; task, we&amp;#x27;ll be able to see &lt;code&gt;Hello world!&lt;/code&gt; in the console.
Now we are talking! We can start adding some modern JavaScript.&lt;/p&gt;
&lt;div class="spoiler"&gt;&lt;div class="spoiler__content-wrapper" id="mpf7r8gj-rmclmv"&gt;&lt;div class="spoiler__content"&gt;&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;dist &lt;span class="token comment"&gt;# created by webpack when we run &amp;#x27;npm run build&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;node_modules &lt;span class="token comment"&gt;# created by npm&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;src
&lt;/span&gt;&lt;span class="code-line"&gt;  js
&lt;/span&gt;&lt;span class="code-line"&gt;    - app.js
&lt;/span&gt;&lt;span class="code-line"&gt;  - index.html
&lt;/span&gt;&lt;span class="code-line"&gt;- package-lock.json &lt;span class="token comment"&gt;# created by npm (for node v8 and higher)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;- package.json
&lt;/span&gt;&lt;span class="code-line"&gt;- webpack.config.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;button class="spoiler__toggle btn btn--sm"&gt;&lt;span class="spoiler__toggle-show"&gt;Show file structure after this step&lt;/span&gt;&lt;span class="spoiler__toggle-hide"&gt;Hide file structure after this step&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;h3 id="babel"&gt;Babel &lt;a class="anchor-link" href="#babel"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To be able to use ES2015 and beyond we&amp;#x27;ll need to provide a transpiler.
Our choice is &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt;.
Babel takes modern JavaScript and transpiles it - converts it to the old version
of JavaScript that can be executed in the browsers that don&amp;#x27;t support modern JavaScript standards.&lt;/p&gt;
&lt;p&gt;We need this for two reasons (and you probably know both already):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;React and JSX heavily rely on modern JavaScript features&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;should&lt;/strong&gt; use modern JavaScript - it makes things easier and helps you write better code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;#x27;s continue by installing four packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Babel core package&lt;/li&gt;
&lt;li&gt;Babel webpack loader&lt;/li&gt;
&lt;li&gt;
&lt;span class="sidenote__text" tabindex="0"&gt;Babel env preset&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;&lt;code&gt;babel-preset-env&lt;/code&gt; is successor of &lt;code&gt;babel-preset-es2015&lt;/code&gt;
and it has couple of big advantages which may be covered in another post.
You can read more about using it in
&lt;a href="https://philipwalton.com/articles/deploying-es2015-code-in-production-today/"&gt;this post&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;Babel React preset&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; --save-dev babel-core babel-loader babel-preset-env babel-preset-react
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Babel also has default config file which is &lt;code&gt;.babelrc&lt;/code&gt;, so let&amp;#x27;s create it in our project&amp;#x27;s root:&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token string"&gt;&amp;quot;presets&amp;quot;&lt;/span&gt;&lt;span class="token builtin class-name"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;&amp;quot;env&amp;quot;&lt;/span&gt;, &lt;span class="token string"&gt;&amp;quot;react&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will tell Babel to use two presets we just installed.&lt;/p&gt;
&lt;p&gt;Now we need to update &lt;code&gt;webpack.config.js&lt;/code&gt; to use Babel loader for &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.jsx&lt;/code&gt; files.
We also added some sugar, so you can import those files without specifying file extension.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// We are using node&amp;#x27;s native package &amp;#x27;path&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://nodejs.org/api/path.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;path&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;HtmlWebpackPlugin&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;html-webpack-plugin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Constant with our paths&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; paths &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;dist&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src/js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Webpack configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;module&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;exports&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;entry&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;output&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;path&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.bundle.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Tell webpack to use html plugin&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;plugins&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token literal-property property"&gt;template&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;index.html&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Loaders configuration -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// We are telling webpack to use &amp;quot;babel-loader&amp;quot; for .js and .jsx files&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;module&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;rules&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;test&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;&lt;span class="token special-escape escape"&gt;\.&lt;/span&gt;&lt;span class="token group punctuation"&gt;(&lt;/span&gt;js&lt;span class="token alternation keyword"&gt;|&lt;/span&gt;jsx&lt;span class="token group punctuation"&gt;)&lt;/span&gt;&lt;span class="token anchor function"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;exclude&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;node_modules&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;use&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;          &lt;span class="token string"&gt;&amp;#x27;babel-loader&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Enable importing JS files without specifying their&amp;#x27;s extenstion -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// So we can write:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// import MyComponent from &amp;#x27;./my-component&amp;#x27;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Instead of:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// import MyComponent from &amp;#x27;./my-component.jsx&amp;#x27;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;resolve&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;extensions&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;.jsx&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart &lt;code&gt;npm run dev&lt;/code&gt; once again. Nothing really changed, but our JavaScript is now transpiled,
and if you used any of the modern JavaScript features, those would be transpiled to ES5 synthax.&lt;/p&gt;
&lt;p&gt;Finally let&amp;#x27;s add React.&lt;/p&gt;
&lt;div class="spoiler"&gt;&lt;div class="spoiler__content-wrapper" id="mpf7r8gl-3iqrfn"&gt;&lt;div class="spoiler__content"&gt;&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;dist &lt;span class="token comment"&gt;# created by webpack when we run &amp;#x27;npm run build&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;node_modules &lt;span class="token comment"&gt;# created by npm&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;src
&lt;/span&gt;&lt;span class="code-line"&gt;  js
&lt;/span&gt;&lt;span class="code-line"&gt;    - app.js
&lt;/span&gt;&lt;span class="code-line"&gt;  - index.html
&lt;/span&gt;&lt;span class="code-line"&gt;- .babelrc
&lt;/span&gt;&lt;span class="code-line"&gt;- package-lock.json &lt;span class="token comment"&gt;# created by npm (for node v8 and higher)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;- package.json
&lt;/span&gt;&lt;span class="code-line"&gt;- webpack.config.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;button class="spoiler__toggle btn btn--sm"&gt;&lt;span class="spoiler__toggle-show"&gt;Show file structure after this step&lt;/span&gt;&lt;span class="spoiler__toggle-hide"&gt;Hide file structure after this step&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;h3 id="react"&gt;React &lt;a class="anchor-link" href="#react"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is probably the main reason you are reading this,
so I&amp;#x27;ll assume you are already familiar with &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Install it (this time as a regular dependency):&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; &lt;span class="token parameter variable"&gt;--save&lt;/span&gt; react react-dom
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&amp;#x27;s add div with id &lt;code&gt;app&lt;/code&gt; to &lt;code&gt;index.html&lt;/code&gt;, in which we&amp;#x27;ll render our React app.&lt;/p&gt;
&lt;pre class="language-html"&gt;&lt;code class="language-html code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token doctype"&gt;&lt;span class="token punctuation"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="token doctype-tag"&gt;doctype&lt;/span&gt; &lt;span class="token name"&gt;html&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class="token attr-name"&gt;charset&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;utf-8&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class="token attr-name"&gt;name&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;viewport&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="token attr-name"&gt;content&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;width=device-width&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Webpack Babel React revisited&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class="token attr-name"&gt;id&lt;/span&gt;&lt;span class="token attr-value"&gt;&lt;span class="token punctuation attr-equals"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;app&lt;span class="token punctuation"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally replace &lt;code&gt;console.log&lt;/code&gt; in our &lt;code&gt;app.js&lt;/code&gt; with a real React component.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; render &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-dom&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;export&lt;/span&gt; &lt;span class="token keyword module"&gt;default&lt;/span&gt; &lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;Hello&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;div&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token maybe-class-name"&gt;Hello&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; react
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token operator"&gt;/&lt;/span&gt;div&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Hello&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token dom variable"&gt;document&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getElementById&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;app&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart dev server one more time, and voala, we have our React app running!&lt;/p&gt;
&lt;h2 id="this-is-minimal-working-setup"&gt;This is minimal working setup &lt;a class="anchor-link" href="#this-is-minimal-working-setup"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, you have bare bones setup for making React apps using Webpack and Babel.
You can start exploring on your own, add more stuff and modify it to fit your needs.
However in this post I&amp;#x27;ll cover two more things - CSS and assets loaders.&lt;/p&gt;
&lt;h2 id="css"&gt;CSS &lt;a class="anchor-link" href="#css"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every web application needs CSS. So let&amp;#x27;s add a way of getting CSS into ours.
Create &lt;code&gt;src/css&lt;/code&gt; folder and a simple &lt;code&gt;style.css&lt;/code&gt; in it.&lt;/p&gt;
&lt;pre class="language-css"&gt;&lt;code class="language-css code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token selector"&gt;body&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;background&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token hexcode color"&gt;#f9fafb&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;font-family&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; Helvetica&lt;span class="token punctuation"&gt;,&lt;/span&gt; Arial&lt;span class="token punctuation"&gt;,&lt;/span&gt; sans-serif&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;font-size&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;16&lt;/span&gt;&lt;span class="token unit"&gt;px&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;margin&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;padding&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;30&lt;/span&gt;&lt;span class="token unit"&gt;px&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To add this CSS file to the app, we&amp;#x27;ll use
&lt;a href="https://github.com/webpack-contrib/css-loader"&gt;css-loader&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CSS loader needs to write loaded CSS code to either &lt;code&gt;style&lt;/code&gt; tag in the head
or external stylesheet file.
If you want to write it to the &lt;code&gt;style&lt;/code&gt; tag you should use
&lt;a href="https://github.com/webpack-contrib/style-loader"&gt;style-loader&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But for now, we&amp;#x27;ll extract it to the external file by using
&lt;a href="https://github.com/webpack-contrib/extract-text-webpack-plugin"&gt;extract-text-webpack-plugin&lt;/a&gt;.
HTML webpack plugin, that we already set, will add css file to &lt;code&gt;index.html&lt;/code&gt; for us.&lt;/p&gt;
&lt;p&gt;Again, start by installing packages:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update, April 2018:&lt;/strong&gt; Please note, if you are using webpack v4.x you&amp;#x27;ll need to install
&lt;code&gt;extract-text-webpack-plugin@next&lt;/code&gt; which is webpack 4 compatible.&lt;/p&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; --save-dev css-loader extract-text-webpack-plugin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&amp;#x27;ll need to do two more things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;import our CSS in &lt;code&gt;app.js&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; render &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-dom&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;../css/style.css&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// Import CSS -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;export&lt;/span&gt; &lt;span class="token keyword module"&gt;default&lt;/span&gt; &lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;Hello&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;div&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token maybe-class-name"&gt;Hello&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; react
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token operator"&gt;/&lt;/span&gt;div&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Hello&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token dom variable"&gt;document&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getElementById&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;app&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;and update webpack config to use &lt;code&gt;css-loader&lt;/code&gt; for CSS files:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// We are using node&amp;#x27;s native package &amp;#x27;path&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://nodejs.org/api/path.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;path&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;HtmlWebpackPlugin&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;html-webpack-plugin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;ExtractTextPlugin&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;extract-text-webpack-plugin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;//  -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Constant with our paths&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; paths &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;dist&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src/js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Webpack configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;module&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;exports&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;entry&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;output&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;path&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.bundle.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Tell webpack to use html plugin&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;plugins&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token literal-property property"&gt;template&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;index.html&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;ExtractTextPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;style.bundle.css&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token comment"&gt;// CSS will be extracted to this bundle file -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Loaders configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// We are telling webpack to use &amp;quot;babel-loader&amp;quot; for .js and .jsx files&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;module&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;rules&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;test&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;&lt;span class="token special-escape escape"&gt;\.&lt;/span&gt;&lt;span class="token group punctuation"&gt;(&lt;/span&gt;js&lt;span class="token alternation keyword"&gt;|&lt;/span&gt;jsx&lt;span class="token group punctuation"&gt;)&lt;/span&gt;&lt;span class="token anchor function"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;exclude&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;node_modules&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;use&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;          &lt;span class="token string"&gt;&amp;#x27;babel-loader&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// CSS loader to CSS files -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Files will get handled by css loader and then passed to the extract text plugin&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// which will write it to the file we defined above&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;test&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;&lt;span class="token special-escape escape"&gt;\.&lt;/span&gt;css&lt;span class="token anchor function"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;loader&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;ExtractTextPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;extract&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;          &lt;span class="token literal-property property"&gt;use&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;css-loader&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Enable importing JS files without specifying their&amp;#x27;s extenstion&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// So we can write:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// import MyComponent from &amp;#x27;./my-component&amp;#x27;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Instead of:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// import MyComponent from &amp;#x27;./my-component.jsx&amp;#x27;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;resolve&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;extensions&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;.jsx&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This might seem very complicated to get one CSS file to the page,
but it is very useful when you have multiple stylesheet files
and pre-processing (or post-processing).&lt;/p&gt;
&lt;p&gt;Restart &lt;code&gt;npm run dev&lt;/code&gt;, and you&amp;#x27;ll see that five lines of our beautiful CSS are applied on the page.&lt;/p&gt;
&lt;p&gt;And if we run &lt;code&gt;npm run build&lt;/code&gt; you&amp;#x27;ll see
&lt;span class="sidenote__text" tabindex="0"&gt;&lt;code&gt;style.bundle.css&lt;/code&gt;&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;I use &lt;code&gt;.bundle&lt;/code&gt; postfix so you can easier differentiate webpack bundles from the source files.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
created in the &lt;code&gt;dist&lt;/code&gt; folder,
next to js and html files.&lt;/p&gt;
&lt;div class="spoiler"&gt;&lt;div class="spoiler__content-wrapper" id="mpf7r8gm-fi2n94"&gt;&lt;div class="spoiler__content"&gt;&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;dist &lt;span class="token comment"&gt;# created by webpack when we run &amp;#x27;npm run build&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;node_modules &lt;span class="token comment"&gt;# created by npm&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;src
&lt;/span&gt;&lt;span class="code-line"&gt;  css
&lt;/span&gt;&lt;span class="code-line"&gt;    - style.css
&lt;/span&gt;&lt;span class="code-line"&gt;  js
&lt;/span&gt;&lt;span class="code-line"&gt;    - app.js
&lt;/span&gt;&lt;span class="code-line"&gt;  - index.html
&lt;/span&gt;&lt;span class="code-line"&gt;- .babelrc
&lt;/span&gt;&lt;span class="code-line"&gt;- package-lock.json &lt;span class="token comment"&gt;# created by npm (for node v8 and higher)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;- package.json
&lt;/span&gt;&lt;span class="code-line"&gt;- webpack.config.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;button class="spoiler__toggle btn btn--sm"&gt;&lt;span class="spoiler__toggle-show"&gt;Show file structure after this step&lt;/span&gt;&lt;span class="spoiler__toggle-hide"&gt;Hide file structure after this step&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;h2 id="assets"&gt;Assets &lt;a class="anchor-link" href="#assets"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For the end, we&amp;#x27;ll add &lt;a href="https://github.com/webpack-contrib/file-loader"&gt;file-loader&lt;/a&gt;.
As it&amp;#x27;s name suggests it handles files - images, SVGs, fonts, videos or anything else you need.&lt;/p&gt;
&lt;p&gt;Let&amp;#x27;s create &lt;code&gt;/src/assets/&lt;/code&gt; folder and add
&lt;span class="sidenote__text" tabindex="0"&gt;&lt;a href="https://raw.githubusercontent.com/Stanko/webpack-babel-react-revisited/master/src/assets/keen.png"&gt;Commander Keen&lt;/a&gt; image&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;I still love &lt;a href="https://en.m.wikipedia.org/wiki/Commander_Keen"&gt;Commander Keen&lt;/a&gt; games.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
in it.&lt;/p&gt;
&lt;p&gt;Follow the same flow as with CSS files&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;install loader&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; --save-dev file-loader
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;import image in &lt;code&gt;app.js&lt;/code&gt; and render it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; render &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-dom&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;../css/style.css&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;keenImage&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;../assets/keen.png&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// Importing image -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;export&lt;/span&gt; &lt;span class="token keyword module"&gt;default&lt;/span&gt; &lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;Hello&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;div&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token maybe-class-name"&gt;Hello&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; react
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;span class="token comment"&gt;/* ADDED IN THIS STEP */&lt;/span&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;img src&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; keenImage &lt;span class="token punctuation"&gt;}&lt;/span&gt; alt&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;Commander Keen&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token operator"&gt;/&lt;/span&gt;div&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Hello&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token dom variable"&gt;document&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getElementById&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;app&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;update webpack config to handle image assets&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// We are using node&amp;#x27;s native package &amp;#x27;path&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://nodejs.org/api/path.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;path&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;HtmlWebpackPlugin&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;html-webpack-plugin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;ExtractTextPlugin&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;require&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;extract-text-webpack-plugin&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Constant with our paths&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; paths &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;dist&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;resolve&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;__dirname&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;src/js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Webpack configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;module&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;exports&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;entry&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;JS&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;output&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;path&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;DIST&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app.bundle.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Tell webpack to use html plugin&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;plugins&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token literal-property property"&gt;template&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; path&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;join&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;paths&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;SRC&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;index.html&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;ExtractTextPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;style.bundle.css&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token comment"&gt;// CSS will be extracted to this bundle file -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Loaders configuration&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// We are telling webpack to use &amp;quot;babel-loader&amp;quot; for .js and .jsx files&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;module&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;rules&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;test&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;&lt;span class="token special-escape escape"&gt;\.&lt;/span&gt;&lt;span class="token group punctuation"&gt;(&lt;/span&gt;js&lt;span class="token alternation keyword"&gt;|&lt;/span&gt;jsx&lt;span class="token group punctuation"&gt;)&lt;/span&gt;&lt;span class="token anchor function"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;exclude&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;node_modules&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;use&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;          &lt;span class="token string"&gt;&amp;#x27;babel-loader&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// CSS loader for CSS files&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Files will get handled by css loader and then passed to the extract text plugin&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// which will write it to the file we defined above&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;test&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;&lt;span class="token special-escape escape"&gt;\.&lt;/span&gt;css&lt;span class="token anchor function"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;loader&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;ExtractTextPlugin&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;extract&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;          &lt;span class="token literal-property property"&gt;use&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;css-loader&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// File loader for image assets -&amp;gt; ADDED IN THIS STEP&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// We&amp;#x27;ll add only image extensions, but you can things like svgs, fonts and videos&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;test&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token regex"&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;span class="token regex-source language-regex"&gt;&lt;span class="token special-escape escape"&gt;\.&lt;/span&gt;&lt;span class="token group punctuation"&gt;(&lt;/span&gt;png&lt;span class="token alternation keyword"&gt;|&lt;/span&gt;jpg&lt;span class="token alternation keyword"&gt;|&lt;/span&gt;gif&lt;span class="token group punctuation"&gt;)&lt;/span&gt;&lt;span class="token anchor function"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class="token regex-delimiter"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token literal-property property"&gt;use&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;          &lt;span class="token string"&gt;&amp;#x27;file-loader&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Enable importing JS files without specifying their&amp;#x27;s extenstion&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// So we can write:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// import MyComponent from &amp;#x27;./my-component&amp;#x27;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Instead of:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// import MyComponent from &amp;#x27;./my-component.jsx&amp;#x27;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token literal-property property"&gt;resolve&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token literal-property property"&gt;extensions&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;.js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;.jsx&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart &lt;code&gt;npm run dev&lt;/code&gt; and refresh the browser to see the image.
&lt;code&gt;npm run build&lt;/code&gt; will create image in the &lt;code&gt;dist&lt;/code&gt; folder.&lt;/p&gt;
&lt;div class="spoiler"&gt;&lt;div class="spoiler__content-wrapper" id="mpf7r8go-8c546c"&gt;&lt;div class="spoiler__content"&gt;&lt;pre class="language-sh"&gt;&lt;code class="language-sh code-highlight"&gt;&lt;span class="code-line"&gt;dist &lt;span class="token comment"&gt;# created by webpack when we run &amp;#x27;npm run build&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;node_modules &lt;span class="token comment"&gt;# created by npm&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;src
&lt;/span&gt;&lt;span class="code-line"&gt;  assets
&lt;/span&gt;&lt;span class="code-line"&gt;    - keen.png
&lt;/span&gt;&lt;span class="code-line"&gt;  css
&lt;/span&gt;&lt;span class="code-line"&gt;    - style.css
&lt;/span&gt;&lt;span class="code-line"&gt;  js
&lt;/span&gt;&lt;span class="code-line"&gt;    - app.js
&lt;/span&gt;&lt;span class="code-line"&gt;  - index.html
&lt;/span&gt;&lt;span class="code-line"&gt;- .babelrc
&lt;/span&gt;&lt;span class="code-line"&gt;- package-lock.json &lt;span class="token comment"&gt;# created by npm (for node v8 and higher)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;- package.json
&lt;/span&gt;&lt;span class="code-line"&gt;- webpack.config.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;button class="spoiler__toggle btn btn--sm"&gt;&lt;span class="spoiler__toggle-show"&gt;Show file structure after this step&lt;/span&gt;&lt;span class="spoiler__toggle-hide"&gt;Hide file structure after this step&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;h2 id="that-was-quite-a-ride"&gt;That was quite a ride &lt;a class="anchor-link" href="#that-was-quite-a-ride"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;And all that to create a very simple application, that should look something like this:&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Example app running in the browser" height="906" src="./running-dev-server.png" width="1110" /&gt;&lt;/figure&gt;
&lt;p&gt;Hopefully, you now understand webpack better and are able to create new apps from scratch.&lt;/p&gt;
&lt;p&gt;If you enjoyed this tutorial, please share it, and help me improving
it by pointing out things that are not clear enough or could be written better.&lt;/p&gt;
&lt;p&gt;Complete code is available in &lt;a href="https://github.com/Stanko/webpack-babel-react-revisited"&gt;this repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="but-i-want-more"&gt;But I want more! &lt;a class="anchor-link" href="#but-i-want-more"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Don&amp;#x27;t worry, I will cover more in posts to come.
But it might take a while, as creating a meaningful tutorial is really time consuming.
So please, &lt;a href="http://i.imgur.com/1d9dwpj.gif"&gt;bear with me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This new tutorial series is closely related to &lt;a href="https://github.com/stanko/marvin"&gt;Marvin&lt;/a&gt;&amp;#x27;s future.
So there will posts about development of Marvin and setting up React applications using React.&lt;/p&gt;
&lt;p&gt;React router, redux, hot module reload, thunks, sagas, SASS, PostCSS, universal rendering
are some of the themes that I want to write about.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sat, 07 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/webpack-babel-react-revisited/</guid></item><item><title>The Remains of the Day</title><link>https://nindalf.com/posts/the-remains-of-the-day/</link><description>Follow the story of a reserved butler as he reflects on his life and the meaning of his work in The Remains of the Day.</description><author>Krishna's blog</author><pubDate>Sat, 07 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/the-remains-of-the-day/</guid></item><item><title>C++ Hello World</title><link>https://studiofreya.org/cpp/c-hello-world/</link><description>&lt;p&gt;This is a C++ introduction tutorial for beginners with an example that will print the text “Hello, World!” written in C++ into the console window.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hello World!&lt;/em&gt; is one of the most ubiquitous examples in any programming language. All it does is to print &lt;code&gt;Hello World!&lt;/code&gt; and exit the application.&lt;/p&gt;
&lt;p&gt;As with many things, C++ can do one thing in many ways.&lt;/p&gt;
&lt;h2 id="hello-world"&gt;&lt;span id="Hello-World"&gt;Hello World!&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;This simple program will print &lt;em&gt;Hello world!&lt;/em&gt; in C++ followed by a newline.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Fri, 06 Oct 2017 10:42:12 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/cpp/c-hello-world/</guid></item><item><title>Art Friday: Even More Semitransparent Rectangles</title><link>http://michaelhoney.com/writing/2017/10/6/art-friday-even-more-semitransparent-rectangles</link><description>&lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267178381-I7ZC9RJUFFV5AGR68LAQ/57-42.097168.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="57-42.097168.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267178381-I7ZC9RJUFFV5AGR68LAQ/57-42.097168.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267171215-DQ1NY9RBX5LL8HQ9MBBJ/30-90.28023.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="30-90.28023.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267171215-DQ1NY9RBX5LL8HQ9MBBJ/30-90.28023.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267170885-B0KE2V4NLGBFBU9OWBXP/5-82.69262.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="5-82.69262.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267170885-B0KE2V4NLGBFBU9OWBXP/5-82.69262.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267173780-R2QZD09V8NK8KW2FWUMQ/37-9.805362.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="37-9.805362.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267173780-R2QZD09V8NK8KW2FWUMQ/37-9.805362.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267173780-R4H5ABKRIUYJRTK00RHI/46-13.055236.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="46-13.055236.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267173780-R4H5ABKRIUYJRTK00RHI/46-13.055236.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267176286-Q42PWF7ED7B5V1PC9HB1/48-85.9302.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="48-85.9302.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267176286-Q42PWF7ED7B5V1PC9HB1/48-85.9302.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267176048-CCOCOOWBZ7X9O1X5HJ3F/50-38.028095.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="50-38.028095.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267176048-CCOCOOWBZ7X9O1X5HJ3F/50-38.028095.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267178661-K1VDFBMM3J0SD6YWTSJI/86-49.606636.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="86-49.606636.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267178661-K1VDFBMM3J0SD6YWTSJI/86-49.606636.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267184795-I8WK378GZHUKPAJ2IZ2Q/101--1.5190357.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="101--1.5190357.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267184795-I8WK378GZHUKPAJ2IZ2Q/101--1.5190357.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267184497-QF9ALK3XJN1EU043DCD0/102-101.4939.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="102-101.4939.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267184497-QF9ALK3XJN1EU043DCD0/102-101.4939.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267186768-NTQZ9VJYKPHS4DMV7Z0M/105-96.35358.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="105-96.35358.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267186768-NTQZ9VJYKPHS4DMV7Z0M/105-96.35358.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;
                
              
            
          

          
        

      

        

        

        
          
            
              
                
                &lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267188705-4KVVF8O2O6CRHQN0P91O/107--7.330782.png"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="107--7.330782.png" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1507267188705-4KVVF8O2O6CRHQN0P91O/107--7.330782.png?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Fri, 06 Oct 2017 08:19:04 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2017/10/6/art-friday-even-more-semitransparent-rectangles</guid></item><item><title>Waking up, so we can dream</title><link>http://dimitarsimeonov.com/2017/10/06/waking-up-so-we-can-dream</link><description>&lt;p&gt;Every day we wake up from sleep, but we aren’t really awake. We are
only awake enough to drive our cars, do our work and cook our food.
And when we take a break, and we’re awake, we’re still asleep. We
blink, but we don’t think. And time tic-tocs away. Coffee doesn’t wake
us up. It helps up sleep walk. Yet, it can help us think, and mindful
thought is the only thing that wakes us up.&lt;/p&gt;

&lt;p&gt;I’m talking about a meaning of the word “awake” that is not a common
one. Strategic awakening.  To be strategically awake is to know where
you are in life and where you want to go.&lt;/p&gt;

&lt;p&gt;Even for the common meaning of awakening, there is a gradation.  As
I’ve written before, in “100% awake”, there are multiple stages
between opening the eyes and being able to do basic motor skills, and
getting to the point where I can operate on a much higher level -
solving problems and fixing things.&lt;/p&gt;

&lt;p&gt;But that high level is still.. kinda low. I maintain that there’s and
even higher level of operation. And no, you don’t get there by smoking
joints :P. But seriously, no drugs will get you there on their own,
even if they enhance you like in the movie “Limitless”. We can go
there when we distance ourselves from our current situation, and
consider our life as a whole. Out of body experience, if you will.&lt;/p&gt;

&lt;p&gt;In those moments we reconsider our basic assumptions. ven if I am
really good at writing code, or welding metal pieces together or
painting portraits, is this what I should be doing? Is this the right
thing that is best for me, and for society. Is this the thing that I
enjoy doing, or that it will get me towards doing what I enjoy? Is
this the right &lt;strong&gt;strategic&lt;/strong&gt; thing to do?&lt;/p&gt;

&lt;p&gt;Well first of all, the right strategic thing for every different
person is determined differently. People are in different stages in
their lives, caught up in different circumstances. People all want
different things. We all see success differently. What means success
for you might seem like a failure to me and vice versa. It’s because
it’s all up to us to define what success means for each of us. It’s
not what someone else tells us. “The American Dream” is not everyone’s
dream. It’s just a an inception, which displaces our own desires. It’s
real name is “The American Sleep”. Everyone’s dream is different.&lt;/p&gt;

&lt;p&gt;We can only see our dream, when we are strategically awake, and not
when we are mindlessly doing stuff. We step back and look around, and
look at a map, and see the winding path around the mountain, and know
that there is a peak. And the view… oh the view from the top, and
the views along long the way are beautiful. At least in our own eyes.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 06 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/10/06/waking-up-so-we-can-dream</guid></item><item><title>Spesometro Open Source per .NET</title><link>https://nicolaiarocci.com/spesometro-open-source-per-.net/</link><description>&lt;p&gt;&lt;em&gt;apologies, this post is about an Italian open source release, so it’s
going to be in Italian&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/FatturaElettronica/Spesometro.NET"&gt;Spesometro.NET&lt;/a&gt; è un nuovo progetto open source che ho rilasciato con la &lt;a href="http://gestionaleamica.com"&gt;mia
azienda&lt;/a&gt;. Si tratta di un package .NET che permette di leggere, scrivere
e convalidare lo Spesometro o, come è chiamato formalmente, la Comunicazione
delle Fatture Emesse e Ricevute.&lt;/p&gt;
&lt;p&gt;Si tratta di un adempimento che in tempi recenti, per ragioni che non è il caso
di affrontare in questo articolo, ha causato grosse difficoltà sia ai fornitori
di soluzioni software che, e soprattutto, agli utenti finali di dette
soluzioni.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 05 Oct 2017 10:37:00 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/spesometro-open-source-per-.net/</guid></item><item><title>How I broke Envato Search Engine</title><link>https://serhack.me/articles/how-i-broke-envato-search-field/</link><description>Envato devs had not developed a strong filter in order to avoid any XSS Attack, and I noticed that I could perform a XSS Injection. I have contacted Envato and, after some investigations, they have discovered that my vulnerabilities were critical! They thanked me and patched the vulnerabilities within 5 business days. Good job Envato!! -&lt;a href="https://serhack.me/articles/how-i-broke-envato-search-field/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Thu, 05 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/how-i-broke-envato-search-field/</guid></item><item><title>Javascript Has Gamified Programming</title><link>https://myownfortune.wordpress.com/2017/10/04/javascript-has-gamified-programming/</link><description>Modern Javascript has gamified programming by creating more micro-success moments (aha! finally got it!). But we know there is No Silver Bullet[1], so it couldn&amp;#8217;t have created more moments where you finally solve your hard problems (&amp;#8220;essential complexity&amp;#8221;). Instead, it has created many opportunities to beat problems you wouldn&amp;#8217;t have in another environment (&amp;#8220;accidental complexity&amp;#8221;) and [&amp;#8230;]</description><author>My Own Fortune</author><pubDate>Wed, 04 Oct 2017 03:25:36 GMT</pubDate><guid isPermaLink="true">https://myownfortune.wordpress.com/2017/10/04/javascript-has-gamified-programming/</guid></item><item><title>Posthumous by Jean Nordhaus</title><link>https://ho.dges.online/words/commonplace/posthumous-by-jean-nordhaus/</link><description>&lt;p&gt;Would it surprise you to learn&lt;br /&gt;
that years beyond your longest winter&lt;br /&gt;
you still get letters from your bank, your old &lt;br /&gt;
philanthropies, cold flakes drifting &lt;br /&gt;
through the mail-slot with your name? &lt;br /&gt;
Though it’s been a long time since your face &lt;br /&gt;
interrupted the light in my door-frame,&lt;br /&gt;
and the last tremblings of your voice&lt;br /&gt;
have drained from my telephone wire,&lt;br /&gt;
from the lists of the likely, your name&lt;br /&gt;
is not missing. It circles in the shadow-world&lt;br /&gt;
of the machines, a wind-blown ghost. For generosity&lt;br /&gt;
will be exalted, and good credit&lt;br /&gt;
outlasts death. Caribbean cruises, recipes,&lt;br /&gt;
low-interest loans. For you who asked&lt;br /&gt;
so much of life, who lived acutely&lt;br /&gt;
even in duress, the brimming world&lt;br /&gt;
awaits your signature. Cancer and heart disease&lt;br /&gt;
are still counting on you for a cure.&lt;br /&gt;
B’nai Brith numbers you among the blessed.&lt;br /&gt;
They miss you. They want you back.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Wed, 04 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/posthumous-by-jean-nordhaus/</guid></item><item><title>Der Herbst kommt</title><link>https://rybakov.com/blog/nemo/</link><description>&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="nemooo" loop="true" poster="/video/nemooo/nemooo.jpg"&gt;
      &lt;source src="../video/nemooo/nemooo.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="nemooobuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="nemooopaused"&gt;&lt;/div&gt;
&lt;/div&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Tue, 03 Oct 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/nemo/</guid></item><item><title>Ignorance Is The Parent Of Fear</title><link>https://ho.dges.online/words/commonplace/ignorance-is-the-parent-of-fear/</link><description>&lt;p&gt;Herman Melville&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Ignorance is the parent of fear.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;</description><author>ho.dges.online</author><pubDate>Tue, 03 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/ignorance-is-the-parent-of-fear/</guid></item><item><title>The REAL name, and value, of self-driving cars</title><link>https://stop.zona-m.net/2017/10/the-real-name-and-value-of-self-driving-cars/</link><description>&lt;p&gt;The first issue with self-driving cars may be in how you CALL them.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 01 Oct 2017 20:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/10/the-real-name-and-value-of-self-driving-cars/</guid></item><item><title>The boundaries of Data Visualization</title><link>https://rybakov.com/blog/dataviz/</link><description>&lt;p&gt;It is always great fun to try and find patterns in vast amounts of data. Sometimes you find causation, other times just spurious correlation, but it&amp;rsquo;s a great excercise and the insight you get can be surprising.&lt;/p&gt;
&lt;p&gt;For a while, I have been wearing a light sensor that measures the surrounding light. The light that is around us, everywhere we go. It&amp;rsquo;s intensity and color. These graphs below are just two data points from January and April. Each horizontal pixel represents one minute, with data ranging from 6 am to 8 pm. You can see how the light changes from winter to spring, but as I know my daily routines, looking at these data reminds me of the course of events on the represented days. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/lr_comparison.png" /&gt;




&lt;/figure&gt;
&lt;p&gt;Changes over time can be shown well in a time lapse animation.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 01 Oct 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/dataviz/</guid></item><item><title>Minor design refresh</title><link>https://muffinman.io/blog/minor-design-refresh/</link><description>&lt;article class="article"&gt;&lt;p&gt;I kinda got bored by the current design.
Rotating SVGs in the header ate too much CPU power (oh &lt;a href="/blog/what-is-the-point/"&gt;the irony&lt;/a&gt;).
So I decided to change a thing or two.&lt;/p&gt;
&lt;p&gt;First thing was to get rid of the rotation.
Then logo got replaced and I added this &lt;a href="https://www.readvisions.com/marvin"&gt;marvelous font&lt;/a&gt;.
Header is a bit smaller now and footer blends more with the page.
Typography did undergo some small changes, and both buttons and borders are not lighter as well.
Code snippets are now using a light theme, which should be easier on the eye.&lt;/p&gt;
&lt;p&gt;This is just a minor refresh until I do a full redesign (one of the &lt;a href="/blog/trillion-ideas/"&gt;trillion ideas&lt;/a&gt;).&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sun, 01 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/minor-design-refresh/</guid></item><item><title>Here's what you can do to make migrating your forms to Redux easier in the future</title><link>https://goshacmd.com/prep-forms-for-redux/</link><author>Gosha Spark</author><pubDate>Sun, 01 Oct 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/prep-forms-for-redux/</guid></item><item><title>Facebook and Google forcing countries to trust them</title><link>https://stop.zona-m.net/2017/09/facebook-and-google-forcing-countries-to-trust-them/</link><description>&lt;p&gt;Please have a look at this scary title, just appeared on the Web:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 30 Sep 2017 20:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/09/facebook-and-google-forcing-countries-to-trust-them/</guid></item><item><title>Links - September 29th, 2017</title><link>https://faingezicht.com/links/2017/09/30/links/</link><description>September has been a long month. Moving apartments is both mentally, and physically taxing, and the process is extremely time consuming. These have been sitting idle in the draft box way too long, so here goes:</description><author>Avy Faingezicht</author><pubDate>Sat, 30 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/09/30/links/</guid></item><item><title>A long short month</title><link>https://faingezicht.com/photos/2017/09/30/stuff2/</link><description>September flew by. Somehow I did not post a single article, or photo in the whole month. I got a lot of things done, but it still feels like it was an intellectually unproductive period.

On to the next one.</description><author>Avy Faingezicht</author><pubDate>Sat, 30 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/09/30/stuff2/</guid></item><item><title>ID3D10Device and ID3D11DeviceContext VTable Indexes</title><link>https://xosh.org/id3d10device-vtable/</link><description>&lt;p&gt;I had trouble finding the index of DirectX 10 method &lt;code&gt;OMGetRenderTargets&lt;/code&gt; for hooking. I found these VTables (ID3D10Device and ID3D11DeviceContext) somewhere on the web. Putting these here to save the trouble for someone else.&lt;/p&gt;</description><author>XOSH.ORG</author><pubDate>Sat, 30 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xosh.org/id3d10device-vtable/</guid></item><item><title>Computers Have Had Emotions for Quite Some Time</title><link>https://svedic.org/philosophy/computers-have-had-emotions-for-quite-some-time</link><description>A common assumption is that computers can’t have emotions. But there is a strong philosophical argument that AI systems have had emotions for many decades now. Before making an argument, we need to define &amp;#8220;emotion&amp;#8221;. That definition shouldn’t require consciousness &amp;#8230; &lt;a href="https://svedic.org/philosophy/computers-have-had-emotions-for-quite-some-time"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Fri, 29 Sep 2017 23:31:52 GMT</pubDate><guid isPermaLink="true">https://svedic.org/philosophy/computers-have-had-emotions-for-quite-some-time</guid></item><item><title>What's new in ECMAScript 2017</title><link>https://jmthornton.net/blog/p/ecmascript2017</link><description>Two years ago, ES6 gave a massive update to the already powerful ECMAScript standard. This year's release, ECMAScript 2017, provides several new features and changes. Let's take a look</description><author>Blog by Jade Michael Thornton</author><pubDate>Fri, 29 Sep 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/ecmascript2017</guid></item><item><title>Finding bounding boxes with interval math</title><link>https://mattkeeter.com/blog/2017-09-29-bounds</link><description/><author>Matt Keeter</author><pubDate>Fri, 29 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2017-09-29-bounds</guid></item><item><title>Do Androids Dream of Electric Sheep</title><link>https://nindalf.com/posts/do-androids-dream-of-electric-sheep/</link><description>Do Androids Dream of Electric Sheep has potential, but is sidetracked by a confusing premise and missed opportunities.</description><author>Krishna's blog</author><pubDate>Fri, 29 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/do-androids-dream-of-electric-sheep/</guid></item><item><title>Kernel Recipes 2017 day 3 notes</title><link>https://anisse.astier.eu/kernel-recipes-2017-day-3.html</link><description>&lt;p&gt;This is continuation of &lt;a href="kernel-recipes-2017-day-1.html"&gt;day 1&lt;/a&gt; and &lt;a href="kernel-recipes-2017-day-2.html"&gt;day 2&lt;/a&gt; of Kernel Recipes 2017.&lt;/p&gt;
&lt;h1&gt;Using Linux &lt;code&gt;perf&lt;/code&gt; at Netflix&lt;/h1&gt;
&lt;p&gt;by Brendan Gregg&lt;/p&gt;
&lt;p&gt;Brendan started with a ZFS on Linux case study, where it was eating 30% of the CPU resources, which it should never be doing.  He started by generating a …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Fri, 29 Sep 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/kernel-recipes-2017-day-3.html</guid></item><item><title>Icarus</title><link>https://olshansky.info/movie/icarus/</link><description>Olshansky's review of Icarus</description><author>🦉 olshansky 🦁</author><pubDate>Thu, 28 Sep 2017 16:34:38 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/icarus/</guid></item><item><title>What have I been up to? Late 2017 Edition</title><link>https://thomashunter.name/posts/2017-09-28-what-have-i-been-up-to-late-2017-edition</link><author>Thomas Hunter II</author><pubDate>Thu, 28 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-09-28-what-have-i-been-up-to-late-2017-edition</guid></item><item><title>Kernel Recipes 2017 day 2 notes</title><link>https://anisse.astier.eu/kernel-recipes-2017-day-2.html</link><description>&lt;p&gt;This is continuation of &lt;a href="kernel-recipes-2017-day-1.html"&gt;yesterday's live blog&lt;/a&gt; of Kernel Recipes 2017.&lt;/p&gt;
&lt;h1&gt;Linux Kernel Self Protection Project&lt;/h1&gt;
&lt;p&gt;by Kees Cook&lt;/p&gt;
&lt;p&gt;&lt;a href="http://outflux.net/slides/2017/kr/kspp.pdf"&gt;Presentation slides&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The aim of the project is more than protecting the kernel.&lt;/p&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Kees' motivation for working on Linux, is the two billion Android devices running a Linux. The majority …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Thu, 28 Sep 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/kernel-recipes-2017-day-2.html</guid></item><item><title>Stati, a PHP static site generator that works on any existing Jekyll site</title><link>https://jfoucher.com/2017/09/stati-static-site-generator.html</link><description>&lt;h3 id="success-"&gt;Success !&lt;/h3&gt;

&lt;p&gt;Well it’s been quite a week. Having had an unexpected lull in my contract work, I decided to work on something fun. I use jekyll for most of my static sites, and I quite like it. It’s still a mistery to me why I decided to build a clone of it. But anyway, one week later, here we are. &lt;a href="https://github.com/jfoucher/stati"&gt;Stati&lt;/a&gt; can now build all my ex-Jekyll sites properly. Actually this blog is now generated with Stati!&lt;/p&gt;

&lt;h3 id="architecture"&gt;Architecture&lt;/h3&gt;

&lt;p&gt;I read this &lt;a href="https://www.bytesandwich.com/jekyll/software/blogging/2016/09/14/how-does-jekyll-work.html"&gt;How does Jekyll work&lt;/a&gt; blog post that gives a nice high level overview of the jekyll architecture, and I decided to mostly use the same kind of process.&lt;/p&gt;

&lt;p&gt;A main Site class holds most of the state while the generation is in progress, with &lt;a href="http://symfony.com/doc/current/components/event_dispatcher.html"&gt;events&lt;/a&gt; being dispatched at several steps along the process so that plugins can hook into them and modify the input, the output, or simply monitor the progress of the generation process.&lt;/p&gt;

&lt;p&gt;First all files are read, in different manner depending on their type (static files, posts or pages), then they are rendered (again differently depending on their type) and finally they are written to disk at the correct path.&lt;/p&gt;

&lt;h3 id="plugins"&gt;Plugins&lt;/h3&gt;

&lt;p&gt;At each point in this process, a plugin can come into play to add pages, have them written in different locations, etc…&lt;/p&gt;

&lt;p&gt;The first plugin, and the one that is used by most Jekyll sites I know of, is the paginator. In the case of Stati, it basically takes a list of all posts and generates a new html page for each page of posts. The core Writer then takes care of putting it in it’s proper path.&lt;/p&gt;

&lt;p&gt;The second plugin is a related posts plugin. For each post it calculates the levenshtein distance of it’s title to all the other posts titles and gets the 10 best matches. Lots of room for improvement here.&lt;/p&gt;

&lt;h3 id="try-it-now"&gt;Try it now!&lt;/h3&gt;

&lt;p&gt;So basically that’s it, a fun project that I will probably continue to use and improve. If you’d like to give it a try, you can &lt;a href="https://github.com/jfoucher/stati/releases/latest"&gt;get the latest release from github&lt;/a&gt; and, most importantly, &lt;a href="https://github.com/jfoucher/stati/issues/new"&gt;open an issue&lt;/a&gt; if you run into a snag!&lt;/p&gt;

&lt;p&gt;PS. I just remembered I have a &lt;a href="/2005/03/changes-coming-soon.html"&gt;history&lt;/a&gt; of &lt;a href="/2005/03/new-blog.html"&gt;doing this kind of thing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UPDATE : Just got some &lt;a href="https://stati.jfoucher.com"&gt;documentation&lt;/a&gt; online&lt;/p&gt;</description><author>Geeky Nuggets</author><pubDate>Thu, 28 Sep 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://jfoucher.com/2017/09/stati-static-site-generator.html</guid></item><item><title>Duplicate IDs in HTML: What would happen?</title><link>https://jmthornton.net/blog/p/duplicated-ids</link><description>Duplicated IDs occur both intentionally and not, so what happens when a browser tries to render them?</description><author>Blog by Jade Michael Thornton</author><pubDate>Wed, 27 Sep 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/duplicated-ids</guid></item><item><title>Is it time to replace REST with RPC?</title><link>https://thomashunter.name/posts/2017-09-27-is-it-time-to-replace-rest-with-rpc</link><author>Thomas Hunter II</author><pubDate>Wed, 27 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-09-27-is-it-time-to-replace-rest-with-rpc</guid></item><item><title>My blog setup</title><link>https://muffinman.io/blog/my-blog-setup/</link><description>&lt;article class="article"&gt;&lt;div class="notice notice--warning"&gt;Please note that I&amp;#x27;m not using Jekyll anymore, so this post might be outdated.&lt;/div&gt;&lt;h2 id="update-march-2020"&gt;Update, March 2020 &lt;a class="anchor-link" href="#update-march-2020"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This post is outdated and I simplified my setup a lot. I&amp;#x27;ll try to cover my current setup in one of the future blog posts.&lt;/p&gt;
&lt;h2 id="original-post"&gt;Original post &lt;a class="anchor-link" href="#original-post"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Few days ago I got a following message on LinkedIn.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Stanko! I&amp;#x27;m a junior front-end web developer and I recently found your amazing blog and fell in love with it. Since you don&amp;#x27;t have any other social media, I decided to contact you trough here even if it&amp;#x27;s not ideal. I was wonder what CMS you were using and if you could do a blog post about it ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So here it is, post about my blog setup.&lt;/p&gt;
&lt;h2 id="jekyll"&gt;Jekyll &lt;a class="anchor-link" href="#jekyll"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;#x27;m not using a dynamic CMS but a static site generator called &lt;a href="http://jekyllrb.com/"&gt;Jekyll&lt;/a&gt;.
Static site generators take different approach to making websites.&lt;/p&gt;
&lt;p&gt;Instead of having a database, pulling data from it and dynamically building your pages,
static site generators generate all the pages only when there are changes to the site.
No moving parts, just plain HTML files.
This approach is more secure, makes caching much easier and boosts performance.&lt;/p&gt;
&lt;p&gt;Smashing Magazine has a
&lt;a href="https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/"&gt;post&lt;/a&gt;
on why static sites are awesome.&lt;/p&gt;
&lt;p&gt;Static sites are not limited to blogs. Bigger websites are also easy to build, once you get a hold of it.
There are agencies that are even doing it for client work.&lt;/p&gt;
&lt;p&gt;It comes at the price that once it&amp;#x27;s built you need to deploy it somewhere.
And you don&amp;#x27;t have fancy CMS interface, only good ol&amp;#x27; markdown files.&lt;/p&gt;
&lt;p&gt;Build and deployment part is easy, just let &lt;a href="https://pages.github.com/"&gt;GitHub pages&lt;/a&gt;&lt;sup&gt;1&lt;/sup&gt; do that for you.&lt;/p&gt;
&lt;p&gt;Handling a git repo with a bunch of markdown files should be fairly straight forward
for any developer or tech savvy person. If you feel this is a big burden,
then static site generators might not be for you.&lt;/p&gt;
&lt;small&gt;&lt;sup&gt;1&lt;/sup&gt; There is &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt; as well, which I never used myself, but I&amp;#x27;ve heard good things about it.&lt;/small&gt;
&lt;h2 id="how-to-start-your-own"&gt;How to start your own &lt;a class="anchor-link" href="#how-to-start-your-own"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I keep this blog on GitHub pages (obviously) and I would recommend you to do the same.&lt;/p&gt;
&lt;p&gt;If you want to start from scratch, start with &lt;a href="http://jekyllrb.com/docs/quickstart/"&gt;official quickstart guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Or you can start the same way I did - from the great &lt;a href="http://lanyon.getpoole.com/"&gt;Lanyon theme&lt;/a&gt;.
Just fork it&amp;#x27;s repository and rename it to &lt;code&gt;[your github username].github.io&lt;/code&gt;.
GitHub will automatically build and publish it on the same URL.
Build and publish will happen every time you push a change to your blog&amp;#x27;s repository.&lt;/p&gt;
&lt;p&gt;That&amp;#x27;s it!&lt;/p&gt;
&lt;p&gt;Now you have your own blog. &lt;a href="https://help.github.com/articles/adding-or-removing-a-custom-domain-for-your-github-pages-site/"&gt;Custom domain names&lt;/a&gt;
are also easy to setup.&lt;/p&gt;
&lt;h2 id="my-current-setup-aka-complicating-your-life"&gt;My current setup (aka Complicating your life) &lt;a class="anchor-link" href="#my-current-setup-aka-complicating-your-life"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This part is for fun only and direct result of my experiments.
They ended up not so practical, but I learned a tone playing with random things.
Fun times, but now I would go vanilla.&lt;/p&gt;
&lt;p&gt;I wrote a couple of posts about using Jekyll already, and you can find them under &lt;a href="/archive/#jekyll"&gt;Jekyll category&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="live-reload"&gt;Live reload &lt;a class="anchor-link" href="#live-reload"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First thing I did was to add live reload for posts, Javascript and SCSS files.
You can read about it in &lt;a href="/blog/jekyll-gulp-workflow/"&gt;this post&lt;/a&gt; but I plan to rewrite it as I feel it could be done better.&lt;/p&gt;
&lt;h3 id="custom-plugins-and-travis-ci"&gt;Custom plugins and Travis CI &lt;a class="anchor-link" href="#custom-plugins-and-travis-ci"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then I added a couple of custom plugins. But as a security measure, GitHub has a &lt;a href="https://pages.github.com/versions/"&gt;limited set of Jekyll plugins&lt;/a&gt; you can use.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GitHub Pages is powered by Jekyll. However, all Pages sites are generated using the --safe option to disable custom plugins for security reasons. Unfortunately, this means your plugins won’t work if you’re deploying to GitHub Pages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To be able to use custom plugins, I created a bit more complicated setup using Travis CI.
Again there is a &lt;a href="/blog/travis-jekyll-and-github-pages/"&gt;blog post&lt;/a&gt; about that as well.&lt;/p&gt;
&lt;p&gt;What I actually do? I keep my Jekyll files on the &lt;code&gt;source&lt;/code&gt; branch and when I push to it, that triggers a build on Travis, which then pushes generated site back to the &lt;code&gt;master&lt;/code&gt; branch. Once it is done, GitHub publishes it.&lt;/p&gt;
&lt;p&gt;Once you set it up, it is pretty invisible, but I&amp;#x27;ll probably bail on it once I rewrite my local setup (switch from gulp to webpack).&lt;/p&gt;
&lt;h3 id="source-code"&gt;Source code &lt;a class="anchor-link" href="#source-code"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Complete source code of my blog is available &lt;a href="https://github.com/Stanko/Stanko.github.io/tree/source"&gt;here&lt;/a&gt;.
But again, I recommend you to take the easy way, without custom plugins and Travis setup.&lt;/p&gt;
&lt;h2 id="comments-or-any-other-dynamic-content"&gt;Comments (or any other dynamic content) &lt;a class="anchor-link" href="#comments-or-any-other-dynamic-content"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You guessed it! Sites generated by static site generators are static :)
So there is no user generated content.&lt;/p&gt;
&lt;p&gt;But as comments are important part of the blog I researched how to add them.
Most people recommended Disqus, but I didn&amp;#x27;t really want to add a bunch of 3rd party code.
And to make things worse, it seems they are &lt;a href="https://notes.ayushsharma.in/2017/09/im-killing-disqus-comments-on-my-blog-heres-why"&gt;tracking their users&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Luckily there is &lt;a href="https://staticman.net/"&gt;Staticman&lt;/a&gt;.
It is an open source project which enables user-generated content to be added on static site.
You need to set it up, and then post data to their API.
Staticman will then create a pull request to your site&amp;#x27;s repository.
Once you merge it, GitHub will regenerate your site and user-generated content will be available.&lt;/p&gt;
&lt;p&gt;Pull requests are moderated by default and you need to merge them yourself.
Or you can enable auto-merging. I use moderation myself.&lt;/p&gt;
&lt;p&gt;Staticman also supports reCaptcha and Aksimet for spam protection.&lt;/p&gt;
&lt;p&gt;Check their &lt;a href="https://staticman.net/demo"&gt;demo&lt;/a&gt; and &lt;a href="https://staticman.net/docs/"&gt;getting started guide&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="other-static-site-generators"&gt;Other static site generators &lt;a class="anchor-link" href="#other-static-site-generators"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to explore more static site generators check &lt;a href="https://www.netlify.com/blog/2017/05/25/top-ten-static-site-generators-of-2017/"&gt;this post&lt;/a&gt;,
which lists the most popular ones in 2017.&lt;/p&gt;
&lt;p&gt;Two that drew my attention are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Gatsby - &lt;a href="https://github.com/gatsbyjs/gatsby"&gt;github.com/gatsbyjs/gatsby&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Because it is written in Javascript, and you create your site using React
(and it is pretty obvious by now that I love React).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hugo - &lt;a href="https://gohugo.io/"&gt;https://gohugo.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Because it has the largest community after Jekyll,
and offers some stuff out of the box, which others generators don&amp;#x27;t.
I almost switched to Hugo, but I decided not to, as benefits are minimal compared to my current setup.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="happy-blogging-"&gt;Happy blogging! :) &lt;a class="anchor-link" href="#happy-blogging-"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kudos to Sébastien who inspired me to write this post.
Hopefully it will get at least one person to start blogging.
Trust me, it is not that hard.
If you do, please share your blog in the comments.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 27 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/my-blog-setup/</guid></item><item><title>I have a trillion ideas</title><link>https://muffinman.io/blog/trillion-ideas/</link><description>&lt;article class="article"&gt;&lt;p&gt;But I need to regroup and focus on finishing at least one, instead of starting all of the trillion ones and finishing none.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 27 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/trillion-ideas/</guid></item><item><title>Kernel Recipes 2017 day 1 live-blog</title><link>https://anisse.astier.eu/kernel-recipes-2017-day-1.html</link><description>&lt;p&gt;Following &lt;a href="kernel-recipes-2016-notes.html"&gt;last year attempt&lt;/a&gt;, I'm doing a live blog of Kernel Recipes 6th edition. There's also a &lt;a href="https://air.mozilla.org/embedded-recipes-27-sept-morning/"&gt;live stream at Air Mozilla&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;What's new in the world of storage for Linux&lt;/h1&gt;
&lt;p&gt;by Jens Axboe&lt;/p&gt;
&lt;p&gt;Jens started with the status of blk-mq conversions: most drivers are now converted: stec, nbd, MMC …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Wed, 27 Sep 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/kernel-recipes-2017-day-1.html</guid></item><item><title>git git git git git</title><link>https://caiustheory.com/git-git-git-git-git/</link><description>&lt;p&gt;Ever found you&amp;rsquo;ve accidentally entered too many &lt;code&gt;git&lt;/code&gt;s in your terminal and wondered if there&amp;rsquo;s a solution to it? I quite often type &lt;code&gt;git&lt;/code&gt; then go away and come back, then type a full &lt;code&gt;git status&lt;/code&gt; after it. This leads to a lovely (annoying) error out the box:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git: &lt;span class="s1"&gt;'git'&lt;/span&gt; is not a git command. See &lt;span class="s1"&gt;'git --help'&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What a git.&lt;/p&gt;
&lt;p&gt;My initial thought was overriding the &lt;code&gt;git&lt;/code&gt; binary in my &lt;code&gt;$PATH&lt;/code&gt; and having it strip any leading arguments that match &lt;code&gt;git&lt;/code&gt;, so we end up running just the &lt;code&gt;git status&lt;/code&gt; at the end of the arguments. An easier way is to just use &lt;a href="https://git-scm.com/docs/git-config"&gt;&lt;code&gt;git-config&lt;/code&gt;&lt;/a&gt;&amp;rsquo;s &lt;code&gt;alias.*&lt;/code&gt; functionality to expand the first argument being &lt;code&gt;git&lt;/code&gt; to a shell command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config --global alias.git &lt;span class="s1"&gt;'!exec git'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which adds the following git config to your &lt;code&gt;.gitconfig&lt;/code&gt; file&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;git&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;!exec git&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then you&amp;rsquo;ll find you can &lt;code&gt;git git&lt;/code&gt; to your heart&amp;rsquo;s content&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git sha
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc9c642663c0b63fba3964297c13ce9b61209313
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git git sha
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc9c642663c0b63fba3964297c13ce9b61209313
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git git git git git git git git git git git git git git git git git git git git git git git git git git sha
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cc9c642663c0b63fba3964297c13ce9b61209313
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(&lt;code&gt;git sha&lt;/code&gt; is an alias for &lt;code&gt;git rev-parse HEAD&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;See what other git alias&amp;rsquo; I have in my &lt;a href="https://github.com/caius/zshrc/blob/master/dotfiles/gitconfig"&gt;&lt;code&gt;~/.gitconfig&lt;/code&gt;&lt;/a&gt;, and laugh at all the typo corrections I have in there. (Yes, git provides autocorrection if you enable it, but I&amp;rsquo;m used to these typos working!)&lt;/p&gt;
&lt;p&gt;Now &lt;code&gt;git&lt;/code&gt; back to doing useful things!&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Tue, 26 Sep 2017 14:00:23 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/git-git-git-git-git/</guid></item><item><title>CSE Intro Videos</title><link>https://cscrunch.com/blog/corey-pennycuff/cse-intro-videos</link><description>&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
&lt;a href="https://www.youtube.com/watch?v=jmM5BD5XRzs&amp;amp;list=PLZqirAnnqaCZcPdW1UbD1SPjJH95m-qCl"&gt;YouTube Playlist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a series of videos that I recorded for the benefit of my Intro to Computing and C/C++ students, to teach them basic command line skills.  Since it's on YouTube, you can change the playback speed in case I'm speaking too slowly.  Enjoy!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;section class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above view-mode-rss"&gt;&lt;h2 class="field-label"&gt;Tags:&amp;nbsp;&lt;/h2&gt;&lt;ul class="field-items"&gt;&lt;li class="field-item even"&gt;&lt;a href="https://cscrunch.com/tags/video"&gt;Video&lt;/a&gt;&lt;/li&gt;&lt;li class="field-item odd"&gt;&lt;a href="https://cscrunch.com/tags/basics"&gt;Basics&lt;/a&gt;&lt;/li&gt;&lt;li class="field-item even"&gt;&lt;a href="https://cscrunch.com/tags/command-line"&gt;Command Line&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/section&gt;</description><author>CS Crunch</author><pubDate>Tue, 26 Sep 2017 06:10:06 GMT</pubDate><guid isPermaLink="true">https://cscrunch.com/blog/corey-pennycuff/cse-intro-videos</guid></item><item><title>Blocks and Closures in Ruby</title><link>https://josh.works/blocks_and_closures</link><description>&lt;p&gt;&lt;em&gt;Continuing on from &lt;a href="/metaprogramming-method-missing-01"&gt;yesterday’s post about &lt;code class="language-plaintext highlighter-rouge"&gt;method_missing&lt;/code&gt;&lt;/a&gt;, I’m moving on to a part of Ruby’s language that has been a bit of a mystery for me for quite some time. I’m still working through &lt;a href="https://www.amazon.com/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129"&gt;Metaprogramming in Ruby&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s the concept of &lt;em&gt;lambdas&lt;/em&gt;, &lt;em&gt;procs&lt;/em&gt;, &lt;em&gt;blocks&lt;/em&gt;, and more. I also hope to better understand &lt;em&gt;closures&lt;/em&gt;, and perhaps even some aspects of functional programming, as I’m used to (so far) thinking in OOP approaches.&lt;/p&gt;

&lt;p&gt;I expect my first pass to be rocky, but to also lay a foundation for better understanding later. I’m writing this out because &lt;a href="/learning-how-to-learn"&gt;this is how I learn&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="yield"&gt;yield&lt;/h2&gt;

&lt;p&gt;First new term: &lt;code class="language-plaintext highlighter-rouge"&gt;yield&lt;/code&gt;. &lt;a href="https://ruby-doc.org/core-2.4.2/Proc.html#method-i-yield"&gt;(docs)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is always related to passing blocks around (to methods, or other blocks, procs, etc). I think lots of what we do with blocks interacts with the &lt;code class="language-plaintext highlighter-rouge"&gt;yield&lt;/code&gt; function, but it gets called behind the scenes. (Sorta how &lt;code class="language-plaintext highlighter-rouge"&gt;initialize&lt;/code&gt; calls, among other things, &lt;code class="language-plaintext highlighter-rouge"&gt;new&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;you can call &lt;code class="language-plaintext highlighter-rouge"&gt;yield&lt;/code&gt; from inside a method to see any block passed to it. You can also call &lt;code class="language-plaintext highlighter-rouge"&gt;block_given?&lt;/code&gt; to see if there’s a block floating around anywhere.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;a_method&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;block_given?&lt;/span&gt;
  &lt;span class="s1"&gt;'no block'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;a_method&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"no block"&lt;/span&gt;

&lt;span class="n"&gt;a_method&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"look at me, I'm a block"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"look at me, I'm a block"&lt;/span&gt;

&lt;span class="n"&gt;a_method&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="s2"&gt;"i'm inside a do..end block"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"i'm inside a do..end block"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;!--more--&gt;

&lt;p&gt;Enough on yielding.&lt;/p&gt;

&lt;h2 id="blocks-are-closures"&gt;Blocks are closures&lt;/h2&gt;

&lt;p&gt;So, what is a closure? Great question…&lt;/p&gt;

&lt;p&gt;A block requires an environment to run inside of. An orphaned &lt;code class="language-plaintext highlighter-rouge"&gt;do..end&lt;/code&gt; block doesn’t make sense.&lt;/p&gt;

&lt;p&gt;The environment the block runs inside of has local variables, instance variables, a &lt;code class="language-plaintext highlighter-rouge"&gt;self&lt;/code&gt;, etc. (I’m copying heavily from &lt;em&gt;Metaprogramming Ruby 2&lt;/em&gt; here.) These variables are sometimes referred to as &lt;em&gt;bindings&lt;/em&gt;. A block that has bindings is ready to run.&lt;/p&gt;

&lt;p&gt;A block, with it’s given bindings (which relate to its &lt;em&gt;scope&lt;/em&gt;), is known as a &lt;em&gt;closure&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I don’t yet know why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It seems like it’s tricky for blocks to gain access to variables outside of their immediate context/scope.&lt;/p&gt;

&lt;p&gt;To pass scopes around, you have to get past “Scope Gates”, which is anything ruby method that starts with &lt;code class="language-plaintext highlighter-rouge"&gt;class&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;module&lt;/code&gt;, or &lt;code class="language-plaintext highlighter-rouge"&gt;def&lt;/code&gt;. You might think to yourself “that’s all of them.”&lt;/p&gt;

&lt;p&gt;To sneak a binding through a scope gate, you’ll have to use a block.&lt;/p&gt;

&lt;p&gt;Compare:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;my_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;my_var&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;" from myClass"&lt;/span&gt;
  &lt;span class="c1"&gt;# can we access my_var from here?&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;my_var&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;" from my_method"&lt;/span&gt;
    &lt;span class="c1"&gt;# ... or here?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# womp womp. run the code, and receive:&lt;/span&gt;
&lt;span class="c1"&gt;# blocks_practice.rb:15:in `&amp;lt;class:MyClass&amp;gt;': undefined local variable or method `my_var' for MyClass:Class (NameError)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(you cannot access &lt;code class="language-plaintext highlighter-rouge"&gt;my_var&lt;/code&gt; inside of the class or method. Those methods start with the scope-gated phrase &lt;code class="language-plaintext highlighter-rouge"&gt;class&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;def&lt;/code&gt;)&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;my_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;

&lt;span class="no"&gt;MyClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# we can access my_var from here!&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;my_var&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from myClass"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="c1"&gt;# ... but not from here&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;my_var&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from my_method"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# MyClass.new.my_method&lt;/span&gt;
&lt;span class="c1"&gt;# NameError: undefined local variable or method `my_var' for #&amp;lt;MyClass:0x007f98c93f0980&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;my_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;

&lt;span class="no"&gt;MyClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# we can access my_var from here!&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;my_var&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from myClass"&lt;/span&gt;

  &lt;span class="n"&gt;define_method&lt;/span&gt; &lt;span class="ss"&gt;:my_method&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# ... but not from here&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;my_var&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from my_method"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# MyClass.new.my_method&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "success from my_method"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I feel like there’s something important here, but I don’t yet know what it is. But I’m not worrying about it - this is my first trip through closures in Ruby, and I’m only half way through the chapter!&lt;/p&gt;

&lt;p&gt;Per how I &lt;a href="/learning-how-to-learn"&gt;like to learn&lt;/a&gt;, I’m going to dig into some associated guides/tutorials for the concept of closures in Ruby. I know it’s tied to functional programming, and I think it’ll be useful to me to wrap my head around the idea.&lt;/p&gt;

&lt;h2 id="further-reading"&gt;Further reading&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://stackoverflow.com/questions/2191632/begin-rescue-and-ensure-in-ruby"&gt;Begin, Rescue and Ensure in Ruby? (StackOverflow)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://blog.newrelic.com/2014/12/10/weird-ruby-2-rescue-interrupt-ensure/"&gt;Weird Ruby Part 2: Exceptional Endurance (New Relic)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.sitepoint.com/closures-ruby/"&gt;Closures in Ruby (Site Point)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://scotch.io/tutorials/understanding-ruby-closures"&gt;Understanding Ruby Closures (scotch.io)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Tue, 26 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/blocks_and_closures</guid></item><item><title>Mallorca 2017</title><link>https://ph-uhl.com/0006-mallorca-2017/</link><description>&lt;p&gt;My father, my uncle, and I went for a hiking vacation. Some images
from my 2017 stay in Port de Sóller.&lt;/p&gt;
&lt;p&gt;Whilst on the vacation I wrote some of this post but never finish
it. Until now in 2023. I finally got the opportunity to wrap it all up
and hit publish.&lt;/p&gt;
&lt;h2&gt;Arrival&lt;/h2&gt;
&lt;p&gt;After a...</description><author>Philipp Uhl</author><pubDate>Tue, 26 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ph-uhl.com/0006-mallorca-2017/</guid></item><item><title>Embedded Recipes 2017 notes</title><link>https://anisse.astier.eu/embedded-recipes-2017-live-blog.html</link><description>&lt;p&gt;Following &lt;a href="kernel-recipes-2016-notes.html"&gt;last year attempt&lt;/a&gt;, I'm doing a live blog of Embedded Recipes 1st edition.&lt;/p&gt;
&lt;p&gt;&lt;img alt="jpg" src="/images/er2017/01-Anne.jpg" /&gt;&lt;/p&gt;
&lt;h1&gt;Understanding SCHED_DEADLINE&lt;/h1&gt;
&lt;p&gt;by Steven Rostedt&lt;/p&gt;
&lt;p&gt;Every task starts as SCHED_OTHER, where each task gets a fair share of the CPU bandwidth.&lt;/p&gt;
&lt;p&gt;Then comes SCHED_FIFO, where it's first in, first out, a task will run until it …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Tue, 26 Sep 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/embedded-recipes-2017-live-blog.html</guid></item><item><title>Power point play</title><link>https://rybakov.com/blog/zenitpowerpoint/</link><description>&lt;p&gt;My nephew&amp;rsquo;s laptop is so old, he can&amp;rsquo;t play fifa.
Instead, he animates soccer games in Powerpoint.&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="zenitpowerpoint" loop="true" poster="/video/zenitpowerpoint/zenitpowerpoint.jpg"&gt;
      &lt;source src="../video/zenitpowerpoint/zenitpowerpoint.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="zenitpowerpointbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="zenitpowerpointpaused"&gt;&lt;/div&gt;
&lt;/div&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Mon, 25 Sep 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/zenitpowerpoint/</guid></item><item><title>Karate Golf</title><link>https://mbutler.org/karate-golf/</link><description>PLAY KARATE GOLF In a futuristic world, one karate master must travel from golf course to golf course, fighting the ultimate dragon. It is built with Phaser.js and various art assets from around the web. You can view the code here.</description><author>mbutler</author><pubDate>Mon, 25 Sep 2017 08:03:44 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/karate-golf/</guid></item><item><title>GlusterFS</title><link>https://smcleod.net/2017/09/glusterfs/</link><description>&lt;p&gt;We&amp;rsquo;re in the process of shifting from using our custom &amp;lsquo;glue&amp;rsquo; for orchestrating Docker deployments to Kubernetes, When we first deployed Docker to replace LXC and our legacy Puppet-heavy application configuration and deployment systems there really wasn&amp;rsquo;t any existing tool to manage this, thus we rolled our own, mainly a few Ruby scripts combined with a Puppet / Hiera / Mcollective driven workflow.&lt;/p&gt;
&lt;p&gt;The main objective is to replace our legacy NFS file servers used to host uploads / attachments and static files for our web applications, while NFS(v4) performance is adequate, it is a clear single point of failure and of course, there are the age old stale mount problems should network interruptions occur.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Mon, 25 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/09/glusterfs/</guid></item><item><title>Metaprogramming in Ruby: method_missing</title><link>https://josh.works/metaprogramming-method-missing-01</link><description>&lt;p&gt;I’m working through &lt;a href="https://www.amazon.com/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129"&gt;Metaprogramming in Ruby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s a great read. There are examples in the books, but I wanted to take them out and apply them to some easy &lt;a href="http://exercism.io/"&gt;Exercisms&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I feel some disclosure may be useful. &lt;em&gt;In no way, at all, should you ever implement any of the “solutions” I’m exploring here. I’m intentionally breaking things and doing them wrong to grow my understanding of how Ruby works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re following along, I’m doing the &lt;code class="language-plaintext highlighter-rouge"&gt;hamming_test.rb&lt;/code&gt; Exercism. It’s got a few tests. Here’s the first one:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# hamming_test.rb&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_identical_strands&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Hamming&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;my working solution (in regular, non-metaprogramming ruby), is:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# hamming.rb&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;string2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;string1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;string2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a simple class method, takes two arguments, and even has an enumerable anti-pattern of using a counter outside the loop. This solution of mine is many months old, I’m not going to refactor that &lt;code class="language-plaintext highlighter-rouge"&gt;#each_with_index&lt;/code&gt; method. I know it’s itching for a &lt;code class="language-plaintext highlighter-rouge"&gt;#reduce&lt;/code&gt;, but let’s metaprogram it instead.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;I’m going to implement a ‘method_missing’ metaprogramming approach. I’m going to experiment with how Ruby throws “method missing” errors, and try to creatively break it.&lt;/p&gt;

&lt;h3 id="my-constraints"&gt;My Constraints&lt;/h3&gt;

&lt;p&gt;I want to make all of the tests pass without using &lt;code class="language-plaintext highlighter-rouge"&gt;::compute&lt;/code&gt; anywhere, and without modifying &lt;a href="https://gist.github.com/josh-works/aaaf1a65f9d60c602f91f5b21dc38c82"&gt;the test file&lt;/a&gt; at all.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# hamming.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hamming&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
    &lt;span class="c1"&gt;# `method` will be anything I want it to be&lt;/span&gt;
    &lt;span class="c1"&gt;# args is just an array of any given arguments&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the above snippet, you can jump into a Pry or IRB session and require the file (enter &lt;code class="language-plaintext highlighter-rouge"&gt;$ pry -r ./hamming.rb&lt;/code&gt; in your terminal to open the file in a Pry session…) and enter the following:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Hamming.compute('A', 'A')
=&amp;gt; :compute
=&amp;gt; ["A", "A"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;When you call a method on an object, Ruby looks up the “inheritance chain” all the way to &lt;code class="language-plaintext highlighter-rouge"&gt;BasicObject&lt;/code&gt;. To see what the inheritance chain is for our &lt;code class="language-plaintext highlighter-rouge"&gt;Hamming&lt;/code&gt; class, try:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Hamming.ancestors
=&amp;gt; [Hamming, Object, Kernel, BasicObject]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When you call a method that isn’t part of the &lt;code class="language-plaintext highlighter-rouge"&gt;Hamming&lt;/code&gt; class, Ruby will look to see if it exists in &lt;code class="language-plaintext highlighter-rouge"&gt;Object&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;Kernel&lt;/code&gt;, and &lt;code class="language-plaintext highlighter-rouge"&gt;BasicObject&lt;/code&gt;. &lt;code class="language-plaintext highlighter-rouge"&gt;BasicObject&lt;/code&gt; has a private method called &lt;code class="language-plaintext highlighter-rouge"&gt;method_missing&lt;/code&gt; (&lt;a href="https://ruby-doc.org/core-2.4.2/BasicObject.html#method-i-method_missing"&gt;method_missing docs&lt;/a&gt;), and will call it on whatever object started the whole fiasco. In this case, it will be called on &lt;code class="language-plaintext highlighter-rouge"&gt;Hamming&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can call &lt;code class="language-plaintext highlighter-rouge"&gt;method_missing&lt;/code&gt; yourself:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Hamming.send(:method_missing, :imaginary_method)
NoMethodError: undefined method `imaginary_method' for Hamming:Class
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;send&lt;/code&gt; does a few things, but one of them is lets you call private methods. Useful, since &lt;code class="language-plaintext highlighter-rouge"&gt;method_missing&lt;/code&gt; is a private method.&lt;/p&gt;

&lt;p&gt;Now, this gets us some of the way to a solution.&lt;/p&gt;

&lt;p&gt;I can simply re-label my method, make a few changes to pluck the first and second arguments from &lt;code class="language-plaintext highlighter-rouge"&gt;args&lt;/code&gt;, and I’m in business:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hamming&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&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="nf"&gt;length&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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="nf"&gt;split&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="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Since the &lt;code class="language-plaintext highlighter-rouge"&gt;Hamming&lt;/code&gt; class doesn’t have a &lt;code class="language-plaintext highlighter-rouge"&gt;compute&lt;/code&gt; method, when my test file calls this non-existent method, it eventually ends up with &lt;code class="language-plaintext highlighter-rouge"&gt;BasicObject&lt;/code&gt; calling &lt;code class="language-plaintext highlighter-rouge"&gt;method_missing&lt;/code&gt;, which I’ve now over-ridden to give me this particular output.&lt;/p&gt;

&lt;p&gt;A very obvious problem is now &lt;em&gt;every&lt;/em&gt; method that I might call that doesn’t exist will get passed into this replacement &lt;code class="language-plaintext highlighter-rouge"&gt;compute&lt;/code&gt; method, and will return all sorts of errors.&lt;/p&gt;

&lt;p&gt;For example, the following method calls all give the same error:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Hamming.compute()
Hamming.c
Hamming.why_wont_you_work

=&amp;gt; NoMethodError: undefined method `length' for nil:NilClass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Fortunately, we can add one more element to “scope” the kind of missing method errors we’re intercepting. That would aid future developers who won’t be quite as flummoxed by this random error code.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="sx"&gt;%w[compute]&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&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="nf"&gt;length&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;super&lt;/code&gt; (&lt;a href="https://ruby-doc.org/docs/keywords/1.9/files/keywords_rb.html#M000034"&gt;docs&lt;/a&gt;) passes the call along to the parent object if certain conditions are/are not met. In this case, we’re passing the &lt;code class="language-plaintext highlighter-rouge"&gt;method_missing&lt;/code&gt; call up the inheritance chain &lt;em&gt;unless&lt;/em&gt; the method matches a list we give it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;This passes all the tests! It’s horrible code, but was an educational journey for me.&lt;/p&gt;

&lt;p&gt;Oh, and lets just switch to a &lt;code class="language-plaintext highlighter-rouge"&gt;#reduce&lt;/code&gt; real quick. My eye is twitching:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hamming&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="sx"&gt;%w[compute]&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&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="nf"&gt;length&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&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="nf"&gt;split&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="nf"&gt;each_with_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&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;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;counter&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There. Slightly better.&lt;/p&gt;

&lt;p&gt;That’s it for now. A small journey into one metaprogramming concept. More soon!&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Sun, 24 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/metaprogramming-method-missing-01</guid></item><item><title>Set DuckDuckGo as default search in Thunderbird</title><link>https://jmthornton.net/blog/p/thunderbird-ddg</link><description>DuckDuckGo can still be tricky to add to some services. However, adding it to Thunderbird is just a few short steps.</description><author>Blog by Jade Michael Thornton</author><pubDate>Sat, 23 Sep 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/thunderbird-ddg</guid></item><item><title>The endless, useless CRAP in connected cars</title><link>https://stop.zona-m.net/2017/09/the-endless-useless-crap-in-connected-cars/</link><description>&lt;p&gt;Somebody says that it is &lt;a href="https://www.iottechnews.com/news/2017/sep/08/time-buckle-why-possibilities-connected-cars-are-endless/"&gt;&amp;ldquo;Time to buckle up: Why the possibilities of connected cars are endless&amp;rdquo;&lt;/a&gt;, because:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 23 Sep 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/09/the-endless-useless-crap-in-connected-cars/</guid></item><item><title>Emacs Tips and Tricks</title><link>https://lambdaland.org/posts/2017-09-23-emacs-tips-and-tricks/</link><description>&lt;h2 id="to-learn-about"&gt;To Learn About&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;☒ Company-mode (completion framework for lots of stuff)&lt;/li&gt;
&lt;li&gt;☒ YASnippets (templates)&lt;/li&gt;
&lt;li&gt;☒ Auto-YASnippets (something like that—I installed it for temporary
templates)&lt;/li&gt;
&lt;li&gt;☒ Alchemist mode (integrates with company mode—tooling for Elixir)&lt;/li&gt;
&lt;li&gt;☐ What do &lt;code&gt;M-.&lt;/code&gt; and &lt;code&gt;M-,&lt;/code&gt; do?&lt;/li&gt;
&lt;li&gt;☐ &lt;code&gt;font-lock-add-keywords&lt;/code&gt; would let me add new keywords to a
language&lt;/li&gt;
&lt;li&gt;☐ hi-lock&lt;/li&gt;
&lt;li&gt;☐ highlight-phrase, unhighlight-regex&lt;/li&gt;
&lt;li&gt;☒ &lt;a class="link-external" href="https://www.emacswiki.org/emacs/Registers" rel="external"&gt;Registers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;☐ Auto-loading packages to make startup time shorter&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="things-that-make-me-happy"&gt;Things that make me happy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Undo in region (just highlight something and hit undo)&lt;/li&gt;
&lt;li&gt;Generate Backus-Nauer Forms with a slightly modified syntax with
&lt;code&gt;ebnf-eps-buffer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="helm"&gt;Helm&lt;/h2&gt;
&lt;p&gt;You can filter buffers by pattern with Helm. Type: &lt;code&gt;@pattern&lt;/code&gt; to find
buffers matching &lt;code&gt;pattern&lt;/code&gt;. If you want to have spaces in the pattern,
you must escape them with a backslash.&lt;/p&gt;
&lt;h3 id="searching-with-the-silver-searcher"&gt;Searching with the Silver Searcher&lt;/h3&gt;
&lt;p&gt;You’ll need &lt;code&gt;helm-ag&lt;/code&gt;. After searching, you get the following
keybindings:&lt;/p&gt;
&lt;h5 id="key-bindings"&gt;Key Bindings&lt;/h5&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style="width: 19%;" /&gt;
&lt;col style="width: 80%;" /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;C-c o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open other window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Search in parent directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;C-c C-e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch to edit mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-x C-s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Save ag results to buffer(Ask save buffer name if prefix key is specified)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;C-c C-f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable helm-follow-mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-c &amp;gt;&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Move to next file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;C-c &amp;lt;&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Move to previous file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-c ?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show help message&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h5 id="edit-mode-keymap"&gt;Edit mode keymap&lt;/h5&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;C-c C-c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Commit changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-c C-k&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Abort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;C-c C-d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mark delete line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-c C-u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unmark&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h5 id="saved-buffer-keymap"&gt;Saved buffer keymap&lt;/h5&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;RET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jump to current line posion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;code&gt;C-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jump to current line posion in other window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;code&gt;g&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update result&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="registers"&gt;Registers&lt;/h2&gt;
&lt;p&gt;Any letter can be a register. (Uppercase and lowercase are distinct.) In
the follinwg examples, &lt;code&gt;&amp;lt;r&amp;gt;&lt;/code&gt; represents a register name.&lt;/p&gt;
&lt;p&gt;Working with the point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x r SPC &amp;lt;r&amp;gt;&lt;/code&gt; Store point in register (mnemonic: C-SPC saves
current mark)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x r j &amp;lt;r&amp;gt;&lt;/code&gt; Jump to point saved in register (mnemonic: &lt;em&gt;j&lt;/em&gt;ump)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Working with text:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x r s &amp;lt;r&amp;gt;&lt;/code&gt; &lt;em&gt;S&lt;/em&gt;ave region into register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-x r i &amp;lt;r&amp;gt;&lt;/code&gt; &lt;em&gt;I&lt;/em&gt;nsert contents of register (also works for numbers)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Working with numbers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-u NUMBER C-x r n &amp;lt;r&amp;gt;&lt;/code&gt; Save a &lt;em&gt;n&lt;/em&gt;umber&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-u NUMBER C-x r + &amp;lt;r&amp;gt;&lt;/code&gt; Increment register &lt;code&gt;&amp;lt;r&amp;gt;&lt;/code&gt; by &lt;code&gt;NUMBER&lt;/code&gt; (if
&lt;code&gt;C-u NUMBER&lt;/code&gt; omitted, increments by 1)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-x C-k r &amp;lt;r&amp;gt;&lt;/code&gt; Save last kbd macro to register&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="special-modes"&gt;Special Modes&lt;/h2&gt;
&lt;h3 id="racket"&gt;Racket&lt;/h3&gt;
&lt;p&gt;Start everything off right with &lt;code&gt;M-x run-geiser RET racket RET&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-c C-d TAB&lt;/code&gt; Open up documentation for command under point&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="calc"&gt;Calc&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;TAB&lt;/code&gt; rotate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="web-mode"&gt;Web Mode&lt;/h3&gt;
&lt;p&gt;I do a fair amount of web programming. &lt;code&gt;web-mode&lt;/code&gt; is awesome! There are
way too many keystrokes for me to list. Here are my favorite, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-c C-e /&lt;/code&gt; Close element. (Mnemonic: C-&lt;em&gt;element&lt;/em&gt; / (for closing
HTML tags))&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-c C-f&lt;/code&gt; Fold. Collapses current tag and subtree. Same keystroke to
unfold.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="markdown-mode"&gt;Markdown Mode&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-c C-]&lt;/code&gt; Complete markup of element. (e.g. sticks “###” at the
&lt;em&gt;end of a line&lt;/em&gt; on a h3 element&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;TAB&lt;/code&gt; When called on a heading, collapses/expands the heading.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Shift-TAB&lt;/code&gt; Cycles global folding/visibility&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Text keys: (all start with &lt;code&gt;C-c C-s&lt;/code&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-c C-s s&lt;/code&gt; Make current word/region bold (&lt;code&gt;s&lt;/code&gt; is for strong)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-c C-s e&lt;/code&gt; Italics. (&lt;code&gt;e&lt;/code&gt; for emphasis)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bookmarks"&gt;Bookmarks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I installed the &lt;code&gt;bm&lt;/code&gt; module. Run &lt;code&gt;bm-toggle&lt;/code&gt; to book mark a line
visually.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Native bookmarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x r m&lt;/code&gt; New bookmark. Prompts for a name. Mnemonic: “&lt;em&gt;m&lt;/em&gt;ark”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x r b&lt;/code&gt; Jump to a bookmark. Mnemonic: “&lt;em&gt;b&lt;/em&gt;ookmark”, or “&lt;em&gt;b&lt;/em&gt;ack to
&lt;em&gt;b&lt;/em&gt;ookmark”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x r l&lt;/code&gt; List bookmarks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jumping to a bookmark will do so in the &lt;em&gt;current window&lt;/em&gt;, and will put
you where the point last was in that buffer. If you are already in the
buffer, then it will jump to the point where to bookmark was set.&lt;/p&gt;
&lt;p&gt;Bookmarks persist over a session—I’m not sure where the file is, but
they do get stored in some file.&lt;/p&gt;
&lt;h2 id="expansion"&gt;Expansion&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;M-/&lt;/code&gt; will do “dynamic expansion”—if there is a word in one of the
buffers of the current session that starts with whatever your cursor is
on, it will expand to that word. Multiple consecutive invocations of
this function will cycle through available expansions.&lt;/p&gt;
&lt;p&gt;There’s a way to do manual expansion, but I don’t know it.&lt;/p&gt;
&lt;h2 id="window-enlargements"&gt;Window enlargements&lt;/h2&gt;
&lt;p&gt;I’ve defined a few nice functions. Here they are:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;defun&lt;/span&gt;&lt;span&gt; sticky-enlarge-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span&gt;prefix&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;interactive&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;P&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;enlarge-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;if&lt;/span&gt;&lt;span&gt; prefix &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;car&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;span style="color: #B48EAD;"&gt; 1&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;unless&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;current-message&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;message&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;(Use &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;`&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;'&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt; and &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;`&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;'&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt; to adjust window size)&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;let&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; ((&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;map&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;make-sparse-keymap&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;]&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;enlarge-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;[&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;shrink-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;set-transient-map&lt;/span&gt;&lt;span&gt; map t&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;defun&lt;/span&gt;&lt;span&gt; sticky-shrink-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span&gt;prefix&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;interactive&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;P&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;shrink-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;if&lt;/span&gt;&lt;span&gt; prefix &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;car&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;span style="color: #B48EAD;"&gt; 1&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;unless&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;current-message&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;message&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;(Use &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;`&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;'&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt; and &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;`&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;'&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt; to adjust window size)&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;  (&lt;/span&gt;&lt;span style="color: #81A1C1;"&gt;let&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; ((&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;map&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;make-sparse-keymap&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;]&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;enlarge-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;[&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;shrink-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;    (&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;set-transient-map&lt;/span&gt;&lt;span&gt; map t&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; global-map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;C-x }&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;sticky-enlarge-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; global-map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;C-x {&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;sticky-shrink-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; global-map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;&amp;lt;f7&amp;gt;&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;shrink-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; global-map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;&amp;lt;f8&amp;gt;&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;balance-windows&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;define-key&lt;/span&gt;&lt;span&gt; global-map &lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;(&lt;/span&gt;&lt;span style="color: #88C0D0;"&gt;kbd&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt; &amp;quot;&lt;/span&gt;&lt;span style="color: #A3BE8C;"&gt;&amp;lt;f9&amp;gt;&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;&amp;quot;) '&lt;/span&gt;&lt;span&gt;enlarge-window-horizontally&lt;/span&gt;&lt;span style="color: #ECEFF4;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="functions"&gt;Functions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;toggle-truncate-lines&lt;/code&gt; will toggle how long lines are displayed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-d&lt;/code&gt; is essentially &lt;code&gt;ls&lt;/code&gt; — lists the contents of a directory&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-u M-|&lt;/code&gt; pipe region to a shell command and replace it with the
output&lt;/p&gt;
&lt;p&gt;You can get sweet &lt;code&gt;sed&lt;/code&gt;-like behavior with something like this:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt; perl -ne 's/^(\d+)\.(\d+)/&amp;lt;&amp;lt;1 Thes. $1:$2&amp;gt;&amp;gt;/g; print'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="macro-wisdom"&gt;Macro wisdom&lt;/h2&gt;
&lt;p&gt;Put cursor where it is supposed to go, begin recording (&lt;code&gt;C-x (&lt;/code&gt;), do
thingy, isearch to next location, and then stop recording. (&lt;code&gt;C-x )&lt;/code&gt;)
This lets you see what is going to be edited next, and hit &lt;code&gt;C-s C-s&lt;/code&gt; if
you want to skip to the next match.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;f3&amp;gt;&lt;/code&gt; Is a very fancy key. Normally, it will begin recording a macro.
Once you are defining a macro, hitting &lt;code&gt;&amp;lt;f3&amp;gt;&lt;/code&gt; again will insert the
current macro counter.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;f4&amp;gt;&lt;/code&gt; is its best friend. Hitting &lt;code&gt;&amp;lt;f4&amp;gt;&lt;/code&gt; while defining a macro will
end the macro. Hitting &lt;code&gt;&amp;lt;f4&amp;gt;&lt;/code&gt; otherwise will then run the last defined
keyboard macro. Running &lt;code&gt;C-u &amp;lt;f4&amp;gt;&lt;/code&gt; runs the second macro in macro ring.
Running &lt;code&gt;C-u 4 &amp;lt;f4&amp;gt;&lt;/code&gt; runs the first macro 4 times. (Adjust 4 as you
will.)&lt;/p&gt;
&lt;p&gt;You can use Lisp inside of a macro. For example, to insert incrementing
numbers, do:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;M-: (setq x 1) RET&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;C-(&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;C-u M-: x RET&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;M-: (setq x (+ x 1))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;&amp;lt;whatever else&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;C-)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can repeat a macro until an error is signaled with &lt;code&gt;C-u 0 C-x e&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also run &lt;code&gt;apply-macro-to-region-lines&lt;/code&gt; (&lt;code&gt;C-x C-k r&lt;/code&gt;) to fire a
macro on every line in the region.&lt;/p&gt;
&lt;p&gt;To prompt a user for input while writing a macro, do: &lt;code&gt;C-u C-x q&lt;/code&gt;. This
is a variant of &lt;code&gt;C-x q&lt;/code&gt; which queries the user.&lt;/p&gt;
&lt;h3 id="recursive-editing"&gt;Recursive editing&lt;/h3&gt;
&lt;p&gt;Hitting &lt;code&gt;C-r&lt;/code&gt; will enter a recursive editing level &lt;em&gt;when the macro is
run&lt;/em&gt;, but not while you are recording.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C-x q&lt;/code&gt; enters a query state: &lt;code&gt;y&lt;/code&gt; continues to execute the macro, &lt;code&gt;n&lt;/code&gt;
aborts the &lt;em&gt;current&lt;/em&gt; iteration, and &lt;code&gt;q&lt;/code&gt; aborts all together.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C-u C-x q&lt;/code&gt; lets you enter in some text.&lt;/p&gt;
&lt;p&gt;To finish recursive editing, type &lt;code&gt;C-M-c&lt;/code&gt;. To abort and halt execution,
type &lt;code&gt;C-]&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="rectangles"&gt;Rectangles&lt;/h2&gt;
&lt;p&gt;To select text in a rectangle, use &lt;code&gt;C-x SPC&lt;/code&gt;. The region will then
highlight like a rectangle. The kill and yank commands will work like
normal (i.e. hitting &lt;code&gt;C-k&lt;/code&gt; will kill the rectangle.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x r M-w&lt;/code&gt; Copy rectangle as kill. (Think &lt;code&gt;M-w&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x r N&lt;/code&gt; Inserts numbered lines in the rectangle. Accepts a prefix
argument to change at what number the lines start at.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;M-x string-insert-rectangle&lt;/code&gt; Prompts for a string and inserts it at
the current rectangle. So you can go from this:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt; one&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; two&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; three&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; four&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt; - one&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; - two&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; - three&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; - four&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;by setting the mark on the &lt;code&gt;o&lt;/code&gt; of &lt;code&gt;one&lt;/code&gt;, then moving to the &lt;code&gt;f&lt;/code&gt; in
&lt;code&gt;four&lt;/code&gt;, then running the command.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="misc-keystrokes"&gt;Misc. Keystrokes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x &amp;lt;right arrow&amp;gt;&lt;/code&gt; cycle through buffers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-q&lt;/code&gt; toggle read-only mode in current buffer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-;&lt;/code&gt; to set comment column to cursor’s current column&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-h&lt;/code&gt; Really &lt;code&gt;&amp;lt;any prefix&amp;gt; C-h&lt;/code&gt; shows a listing of all possible
completions after the prefix character.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x 8 RET&lt;/code&gt; Insert arbitary unicode character by name. You can
insert snowmen like this!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x 8 &amp;lt;char&amp;gt;&lt;/code&gt; There are a bunch of characters that you can insert
after this. “&amp;lt;” will insert “«”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x n n&lt;/code&gt; Only displays the region. Good for focusing. Use &lt;code&gt;C-x n w&lt;/code&gt;
to display everything.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x $&lt;/code&gt; To hide lines in the current buffer, type ‘C-x $’
(‘set-selective-display’) with a numeric argument N. Then lines with
at least N columns of indentation disappear from the screen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-u&lt;/code&gt; Prefix argument. The default is 4. If you want to grow the
current window by, say, 15 lines, do following: &lt;code&gt;C-u 15 C-x ^&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-u &amp;lt;number&amp;gt; &amp;lt;key&amp;gt;&lt;/code&gt; Repeats &lt;code&gt;&amp;lt;key&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt; times. It’s
different for inserting digits. If you wanted to insert &lt;code&gt;5&lt;/code&gt; seven
times, type &lt;code&gt;C-u 7 C-u 5&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-k C-i&lt;/code&gt; Inserts the current value of the keyboard macro
counter and increments it. When &lt;code&gt;C-u&lt;/code&gt; proceeds the command, the
previous value is inserted, and the counter is not updated. A prefix
argument specifies a different increment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-k C-c&lt;/code&gt; Prompts for the initial value of the keyboard macro.
Must be called prior to starting macro definition to be used this
way. It has another behavior if called during macro definition. See
&lt;a class="link-external" href="https://www.emacswiki.org/emacs/EmacsKeyboardMacroCounter" rel="external"&gt;this
page&lt;/a&gt; for
help.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x C-k n&lt;/code&gt; Give the last kbd macro a name, which you can then call&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ESC-^&lt;/code&gt; Join this line to the previous and fix up whitespace at
join. Useful if &lt;code&gt;auto-fill-mode&lt;/code&gt; was turned on and you need to
unwrap a line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;f1&amp;gt;&lt;/code&gt; Run help&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;f2&amp;gt;&lt;/code&gt; Appears to be a prefix command, much like &lt;code&gt;C-x&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;f10&amp;gt;&lt;/code&gt; Opens the menu. As in, the one at the top of the screen that
you never have actually used. With ACTUAL GRAPHICS!!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;C-x RET f&lt;/code&gt; Allows you to set the encoding when saving the file.
Useful for stripping bad line endings in DOS files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dired"&gt;Dired&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-o&lt;/code&gt; In dired, opens the file the cursor is on in the other window.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="occur"&gt;Occur&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;C-u M-s o &amp;lt;pattern&amp;gt; RET&lt;/code&gt; Copies all strings mattching &lt;code&gt;&amp;lt;pattern&amp;gt;&lt;/code&gt;
(if you use &lt;code&gt;.*thingy.*&lt;/code&gt; it will copy the whole line with “thingy”
in it) into buffer called &lt;code&gt;*Occur*&lt;/code&gt; ### Regexes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not like Perl. In &lt;code&gt;(?:aaa|bbb)&lt;/code&gt;, the characters &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;)&lt;/code&gt;, and &lt;code&gt;|&lt;/code&gt; all
match themselves. If you want perl-like behavior, escape them:
&lt;code&gt;\(?:aaa\|bbb\)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But when you want to type that in a string literal, use
&lt;code&gt;"\\(?:aaa\\|bbb\\)"&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="character-classes"&gt;Character Classes&lt;/h4&gt;
&lt;p&gt;Some common character classes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt; works as expected (any char)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[[:ascii:]]+&lt;/code&gt; any ascii character&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[_A-Za-z0-9]+&lt;/code&gt; letters, digits, underscores&lt;/li&gt;
&lt;li&gt;&lt;code&gt;"\([^"]+\)"&lt;/code&gt; capture text between double quotes (not accounting for
escaped chars)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="regex-search-and-replace"&gt;Regex search and replace:&lt;/h4&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;M-x replace-regexp&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;Replace regexp: right\|left&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;Replace regexp with: \,(if (equal &amp;quot;right&amp;quot; \&amp;amp;amp;) &amp;quot;left&amp;quot; &amp;quot;right&amp;quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks like the &lt;code&gt;\,(...)&lt;/code&gt; syntax says “evaluate me”. :)&lt;/p&gt;
&lt;h4 id="regex-search-and-replace-with-captured-bit"&gt;Regex search and replace with captured bit&lt;/h4&gt;
&lt;pre class="giallo" style="color: #D8DEE9; background-color: #2E3440;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;M-x replace-regexp&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;Replace regexp: subject(\([A-Za-z]+\))&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;Replace regexp with: \1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That gets subject(*), and retuns *&lt;/p&gt;
&lt;h2 id="programming-languages"&gt;Programming Languages&lt;/h2&gt;
&lt;h3 id="c"&gt;C&lt;/h3&gt;
&lt;p&gt;Compile (using &lt;code&gt;make -k&lt;/code&gt;) with &lt;code&gt;M-x compile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Any errors will show up in a special buffer; visit with &lt;kbd&gt;C-x
`&lt;/kbd&gt;&lt;/p&gt;</description><author>Lambda Land</author><pubDate>Sat, 23 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2017-09-23-emacs-tips-and-tricks/</guid></item><item><title>Red Hat Open Source Day rewards with proprietary hardware. For the fourth time</title><link>https://stop.zona-m.net/2017/09/red-hat-open-source-day-rewards-with-proprietary-hardware.-for-the-fourth-time/</link><description>&lt;p&gt;The &lt;a href="https://www.redhat.com/it/events/red-hat-open-source-day-italia"&gt;&amp;ldquo;Open Source Day&amp;rdquo; by Red Hat Italia&lt;/a&gt; is a yearly event in which the italian branch of that corporate Open Source champion:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 22 Sep 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/09/red-hat-open-source-day-rewards-with-proprietary-hardware.-for-the-fourth-time/</guid></item><item><title>Outrunning regret</title><link>http://dimitarsimeonov.com/2017/09/22/outrunning-regret</link><description>&lt;p&gt;I have some thoughts about regret in life, which might be
counterintuitive.&lt;/p&gt;

&lt;p&gt;You might have heard of Jeff Bezos making the decision to start Amazon
as a part of regret-minimization decision making. For him, there
would’ve been a certain regret of not attempting Amazon, but there
wouldn’t be as much regret if he tried and it didn’t work out. From
his point of view, minimizing the regret is to minimize the difference
between the best he could be and what he actually achieved. If the
best is not that high, but he achieved it, then that’s cool. But if he
achieved a lot of success, but there was still a lot of success he
missed on, he would have regretted it.&lt;/p&gt;

&lt;p&gt;This is somewhat similar with Reinforcement learning, where the notion
of “regret” has a strict mathematical definition - the sum of
differences over time between the reward the agent or robot receives,
and the maximum possible reward it could receive. Ideally, when
solving reinforcement learning problem, we want the robot to reach the
maximum reward, and we want the robot to do it fast. A robot which
takes long time to learn kind of sucks at reinforcement learning, as
it has a high reward. Another robot might take even longer to find the
most optimal solution, but might get close to quickly, and have a
lower overall regret.&lt;/p&gt;

&lt;p&gt;As I’ve written before, in “Life is not a reinforcement learning
problem”, we can’t directly apply the robot’s algorithms to our lives,
because we are the ones who define the reward. Part of the problem is
to even understand which things in life reward us, and which cause us
regret. Only then we can get optimize our lives. Jeff Bezos understood
that &lt;strong&gt;for himself&lt;/strong&gt; not trying would have caused more regret, than
not succeeding. But for another person, not succeeding might have
caused more regret than not trying. Each of us gets to define their
own rewards and regrets in life.&lt;/p&gt;

&lt;p&gt;Here comes my counter-intuitive observation. If you try to minimize
reward, in the long run you will maximize it.&lt;/p&gt;

&lt;p&gt;What the fuck! Really? Should we then go and start doing random things
in life, and surrender our free will? I don’t think so. I think
minimizing the regret can actually provide us with long periods in
life without any experienced regret. Let me elaborate.&lt;/p&gt;

&lt;p&gt;Let’s say that you think hard about what you value in life and decide
to go do it. You’ll start approaching this goal, whether it is about
financial, personal, or community project. You might fail, you might
succeed, or you might get closer. If you fail - tough luck, but you’ll
probably try again anyway. If you start getting closer and/or
ultimately succeed at the goal, whether it is to build a boat by
woodworking, or to raise a family, or to build a company, or to clean
and declutter your apartment, or to get in the physical shape you
want, then congratulations - you’ve reduced, and maybe even eliminated
your regret. In those cases, you’re on a roll, and getting to have the
life that you want. Your regret is super low, and maybe even zero.&lt;/p&gt;

&lt;p&gt;You do this for some time. And you’re fucking enjoying it. This is the
best time of your life so far. You set out to do something and you did
it. You’ve been building boats with your bare hands, or you’ve got
great relationship with your spouse and kids, or your really enjoying
your career and the company you’ve built.&lt;/p&gt;

&lt;p&gt;But it’s not gonna last. The feeling. Unless you’re some Zen monk or
whatever. At some point you’ll develop knowledge and appetite for
something else. If you’ve been building wooden boats, now you might
want to start building, or to architect houses or larger
buildings.&lt;/p&gt;

&lt;p&gt;Months and years at the top of your game have exposed you to a new
network of people and ideas previously unbeknownst to you. You start
to soak up the new knowledge, slowly at first, but it builds up. It
gradually changes your outlook, and your understanding of life. You
realize, that building the wooden boats is not the maximum you can do
and that you actually have the ability to build these damn houses and
buildings. Your regret function changes.&lt;/p&gt;

&lt;p&gt;And then you start another wild ride, reducing your new reward
function and building houses. It takes time, but you eventually get so
good at it, that you think you’re building the best houses that you
can. Your reward function drops to zero again, and you enjoy a couple
of years doing that. You’re truly happy, and you have no regrets in
life.&lt;/p&gt;

&lt;p&gt;But again, a couple of years later, your outlook changes, and now you
want to build skyscrapers, or to raise a family or whatever. Damn it!
You have newfound regrets in life again. All right, you go after them,
and so on.&lt;/p&gt;

&lt;p&gt;You have those cycles in life during which you reduce regret, you
flat-line it at zero for some time, and then eventually you change
your regret perception and start another cycle.&lt;/p&gt;

&lt;p&gt;So that’s the gist of it. We as humans will change our priorities and
objectives throughout our lives. I guess Jeff Bezos is still in the
years of his life, that he’s optimizing for the success of his Amazon
empire. Bill Gates, however, has enjoyed multiple years at the top of
Microsoft, making it one of the most successful companies at the time,
and has now redefined his personal goals and objectives towards
philanthropy.&lt;/p&gt;

&lt;p&gt;I’ve had time in my life, when my main objective was math
competitions. Later on I’ve had objectives of getting really good at
computer science and AI, and experiencing love to the
fullest. Currently, I’m getting increasingly exciting about writing,
communication, leadership, and fitness. I’m a gradually transforming
human being, and my present self is a different person from my self
ten years ago.&lt;/p&gt;

&lt;p&gt;That’s OK. I’ll keep on finding new priorities, and I’m cool with
it. I’ll probably never be fully satisfied with life for too long. But
I hope to have some of those periods in between that I’ve reduced my
previous regrets, and haven’t formed new ones.&lt;/p&gt;

&lt;p&gt;Those are the days, Ned.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 22 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/09/22/outrunning-regret</guid></item><item><title>Return Of The RSS</title><link>https://smcleod.net/2017/09/return-of-the-rss/</link><description>&lt;p&gt;Of all the tools for reading news and subscribing to software releases, I still find RSS the most useful.&lt;/p&gt;
&lt;p&gt;I use Feedly to manage my rss subscriptions and keep all my devices in sync, but instead of using the Feedly&amp;rsquo;s own client, I use an app called Reeder as the client / reader itself.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://feedly.com/smcleod/blogs"&gt;Link: My Feedly RSS Feed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="feedly"&gt;&lt;a href="https://feedly.com"&gt;Feedly&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;RSS feed subscription management&lt;/p&gt;
&lt;p&gt;Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keyword alerts.&lt;/li&gt;
&lt;li&gt;Browser plugins to subscribe to (current) url.&lt;/li&gt;
&lt;li&gt;Notation and highlighting support (a bit like Evernote).&lt;/li&gt;
&lt;li&gt;Search and filtering across large numbers of feeds / content.&lt;/li&gt;
&lt;li&gt;IFTTT, Zapier, Buffer and Hootsuite integration.&lt;/li&gt;
&lt;li&gt;Built in save / share functionality (that I only use when I&amp;rsquo;m on the website).&lt;/li&gt;
&lt;li&gt;Backup feeds to Dropbox.&lt;/li&gt;
&lt;li&gt;Very fast, regardless of the fact that I&amp;rsquo;m in Australia - which often impacts the performance of apps / sites that tend to be hosted on AWS in the US as the latency is so high.&lt;/li&gt;
&lt;li&gt;Article de-duplication is currently being developed I believe, so I&amp;rsquo;m looking forward to that!&lt;/li&gt;
&lt;li&gt;Easy manual import, export and backup (no vendor lock-in is important to me).&lt;/li&gt;
&lt;li&gt;Public sharing of your Feedly feeds (we&amp;rsquo;re getting very meta here!).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="reeder"&gt;&lt;a href="http://reederapp.com"&gt;Reeder&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A (really) beautiful and fast iOS / macOS client&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Fri, 22 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2017/09/return-of-the-rss/</guid></item><item><title>RIP Solaris</title><link>https://jasoneckert.github.io/myblog/rip-solaris/</link><description>&lt;p&gt;&lt;img alt="Solaris" src="solaris.png#center" title="Solaris" /&gt;&lt;/p&gt;
&lt;p&gt;The 80s and 90s was a period of intense development in the computer hardware and software worlds.  On the hardware side, processors started to become much more powerful, and the word on the streets was that RISC (Reduced Instruction Set Computing) was going to be the way of the future.  Powerful RISC platforms emerged during this time, including Sun Microsystems SPARC, HP PA-RISC, SGI MIPS, IBM PowerPC, and the DEC Alpha - these platforms were very powerful, and ushered in 64-bit computing over a decade before it became common in home computers.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Thu, 21 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/rip-solaris/</guid></item><item><title>Why Sine Wave?</title><link>https://myownfortune.wordpress.com/2017/09/21/why-sine-wave/</link><description>In this post we will understand what it means to say &amp;#8220;this song has a lot of high frequencies&amp;#8221;, then hunt and capture the waveform that allows us to say this! Some Python code will be used, but understanding it is not necessary. Footnotes are more technically advanced. The x coordinate of the circle&amp;#8230; is frequency?! [&amp;#8230;]</description><author>My Own Fortune</author><pubDate>Thu, 21 Sep 2017 02:42:03 GMT</pubDate><guid isPermaLink="true">https://myownfortune.wordpress.com/2017/09/21/why-sine-wave/</guid></item><item><title>Dual Booting Ubuntu and Windows 10 on a Dell XPS 13</title><link>https://lukesingham.com/dual-booting-ubuntu-and-windows-10-on-a-dell-xps/</link><description>&lt;p&gt;&lt;strong&gt;My Setup&lt;/strong&gt;: &lt;a href="http://www.dell.com/en-uk/shop/laptop-and-2-in-1-pcs/xps-13/spd/xps-13-9360-laptop"&gt;Dell XPS 13-9360&lt;/a&gt; + Windows 10&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aim&lt;/strong&gt; - Get Ubuntu on the machine.&lt;/p&gt;
&lt;p&gt;Essentially, follow &lt;a href="https://askubuntu.com/a/868294/424657"&gt;these instructions&lt;/a&gt; with two key modifications.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You should be able to get away with switching from &lt;a href="https://en.wikipedia.org/wiki/RAID"&gt;RAID&lt;/a&gt; to &lt;a href="https://en.wikipedia.org/wiki/Advanced_Host_Controller_Interface"&gt;AHCI&lt;/a&gt; without re-imaging windows using &lt;a href="http://triplescomputers.com/blog/uncategorized/solution-switch-windows-10-from-raidide-to-ahci-operation/"&gt;these instructions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Disable &lt;a href="https://en.wikipedia.org/wiki/BitLocker"&gt;Bitlocker&lt;/a&gt; - this is crucial! The first time I ran this... I didn't complete this step which led me to screwing up my Windows 10 installation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I neglected Step 2. If the boot priority is Ubuntu first (i.e. Grub) then Ubuntu loads fine. However, windows doesn't load as the Bitlocker detects a change to the BIOS and will require a code to unlock it which, if you're like me, you probably don't have.&lt;/p&gt;
&lt;p&gt;I did try running through the &lt;a href="https://help.ubuntu.com/community/Boot-Repair"&gt;boot-repair tool&lt;/a&gt; from Ubuntu but kept facing the &lt;code&gt;GPT detected...&lt;/code&gt; error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; I use the BIOS boot priority to change the operating system. Now both Win10 and Ubuntu are running on my machine.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources &lt;a class="direct-link" href="https://lukesingham.com/dual-booting-ubuntu-and-windows-10-on-a-dell-xps/#resources"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/a/868294/424657"&gt;Main instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://triplescomputers.com/blog/uncategorized/solution-switch-windows-10-from-raidide-to-ahci-operation/"&gt;Switching from RAID to AHCI without re-imaging Win10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/security/operating-system-security/data-protection/bitlocker/"&gt;Turn off Bitlocker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/Dell/comments/5xw27t/dell_xps_15_9560_dualboot_windows_10_ubuntu_lts/"&gt;Reddit thread&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Wed, 20 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/dual-booting-ubuntu-and-windows-10-on-a-dell-xps/</guid></item><item><title>Selectively disabling payment gateways in WooCommerce</title><link>https://daniel.do/article/selectively-disabling-payment-forms-in-woocommerce</link><author>Daniel Immke</author><pubDate>Wed, 20 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/selectively-disabling-payment-forms-in-woocommerce</guid></item><item><title>Multi-Font Themes in Emacs</title><link>https://bastibe.de/2017-09-19-multi-font-themes.html</link><description>&lt;p&gt;Traditionally, text editor themes are all about colors, right? In programming, we use color to tell variables from type declarations, comments, or strings. However, any other text document uses typography instead of color to distinguish between headlines, list items, and keywords. I think that our current approach to highlighting code is misguided.&lt;/p&gt;
&lt;p&gt;I think that color themes are an accident of history. Terminal text editors are unable to switch fonts. All they can do is switch colors, so colors is all we use. But in todays graphical world, we are no longer bound by the shackles of terminals, and Emacs can switch fonts just as easily as colors&lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;It all started about a year ago, when I fell in love with a font called &lt;a href="https://www.fsd.it/shop/fonts/pragmatapro/"&gt;PragmataPro&lt;/a&gt;. One of the coolest features of Pragmata was its native bold and italic letters, and its wide support for unicode symbols. I had to find a use for these features! And so, down the rabbit hole I went. &lt;strong&gt;Keywords&lt;/strong&gt; should be bold! &lt;em&gt;# Comments&lt;/em&gt; should be italic! And while we're at it, why not add some &lt;em&gt;underlines&lt;/em&gt;? And so on.&lt;/p&gt;
&lt;p&gt;The logical next step was then to get rid of colors altogether. At first, as an experiment. Do I really &lt;em&gt;need&lt;/em&gt; colors in code? The very pretty &lt;a href="https://github.com/maio/eink-emacs"&gt;eink theme&lt;/a&gt; seemed to claim otherwise. After a few months of this lunacy, I realized that while I didn't strictly &lt;em&gt;need&lt;/em&gt; colors, the stylistic variations of just one font aren't quite sufficient for source code. In particular, it wasn't always easy to distinguish between italic and roman type in PragmataPro, which lead to some confusion.&lt;/p&gt;
&lt;p&gt;But then, inspiration hit me: Who says that I could only use one single font? No one!&lt;/p&gt;
&lt;p&gt;&lt;img alt="color%20theme" src="http://bastibe.de/static/2017-09/color%20theme.png" /&gt;&lt;/p&gt;
&lt;p&gt;The tricky bit is to find fonts that work well together. In this example, I'm using PragmataPro for all regular code, &lt;a href="https://be5invis.github.io/Iosevka/"&gt;Iosevka&lt;/a&gt; Slab&lt;sup class="footnote-ref" id="fnref-2"&gt;&lt;a href="#fn-2"&gt;2&lt;/a&gt;&lt;/sup&gt; for strings, and oblique&lt;sup class="footnote-ref" id="fnref-3"&gt;&lt;a href="#fn-3"&gt;3&lt;/a&gt;&lt;/sup&gt; Iosevka for comments. &lt;a href="http://font.ubuntu.com/"&gt;Ubuntu Mono&lt;/a&gt; and &lt;a href="http://input.fontbureau.com/"&gt;InputCompressed&lt;/a&gt; work well, too. You can find my current theme &lt;a href="https://github.com/bastibe/.emacs.d/blob/master/lisp/my-eink-theme.el"&gt;on Github&lt;/a&gt;. The only downside is that while these fonts share the character width, the heights differ slightly, which sometimes leads to uneven line heights.&lt;/p&gt;
&lt;p&gt;Still, I love the look of this! (Of course it won't work in a terminal, or most other text editors.)&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;Can other text editors do this? I honestly have no idea.&lt;a class="footnote" 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 just love the look of the slab-serif characters in Iosevka! Look at the beautiful &lt;code&gt;&amp;quot;}&amp;quot;&lt;/code&gt; in the screenshot!&lt;a class="footnote" href="#fnref-2"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn-3"&gt;&lt;p&gt;not to be confused with &lt;em&gt;italic&lt;/em&gt;, which changes glyphs in addition to slanting.&lt;a class="footnote" href="#fnref-3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>bastibe.de</author><pubDate>Tue, 19 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-09-19-multi-font-themes.html</guid></item><item><title>Tracking and managing your Postgres connections</title><link>/2017/09/18/postgres-connection-management/</link><description>&lt;p&gt;Managing connections in Postgres is a topic that seems to come up several times a week in conversations. I&amp;rsquo;ve written some about scaling your connections and the right approach when you truly need a high level of connections, which is to use a connection pooler like pgBouncer. But what do you do before that point and how can you better track what is going on with your connections in Postgres?&lt;/p&gt;
&lt;p&gt;Postgres under the covers has a lot of metadata about both historical and current activity against a system. Within Postgres you can run the following query which will give you a few results:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;count&lt;/span&gt;(&lt;span style="color: #f92672;"&gt;*&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #66d9ef;"&gt;state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; pg_stat_activity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;GROUP&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;BY&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #66d9ef;"&gt;count&lt;/span&gt; &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;-------+-------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;7&lt;/span&gt; &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; active
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #ae81ff;"&gt;69&lt;/span&gt; &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; idle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #ae81ff;"&gt;26&lt;/span&gt; &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; idle &lt;span style="color: #66d9ef;"&gt;in&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;transaction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #ae81ff;"&gt;11&lt;/span&gt; &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; idle &lt;span style="color: #66d9ef;"&gt;in&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;transaction&lt;/span&gt; (aborted)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(&lt;span style="color: #ae81ff;"&gt;4&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;rows&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;Time: &lt;span style="color: #ae81ff;"&gt;30&lt;/span&gt;.&lt;span style="color: #ae81ff;"&gt;337&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each of these is useful in determining what you should do to better manage your connection count. All of these numbers can be useful to record every say 30 seconds and chart on your own internal monitoring. Lets break down each:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;active&lt;/strong&gt; - This is currently running queries, in a sense this is truly how many connections you may require at a time&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;idle&lt;/strong&gt; - This is where you have opened a connection to the DB (most frameworks do this and maintain a pool of them), but nothing is happening. This is the one area that a connection pooler like pgBouncer can most help.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;idle in transaction&lt;/strong&gt; - This is where your app has run a &lt;code&gt;BEGIN&lt;/code&gt; but it&amp;rsquo;s now waiting somewhere in a transaction and not doing work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For &lt;strong&gt;idle&lt;/strong&gt; as mentioned above it&amp;rsquo;s one that you do want to monitor and if you see a high number here it&amp;rsquo;s worth investing in setting up a pgBouncer.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;idle in transaction&lt;/strong&gt; this one is a bit more interesting. Here what you likely want to do when first investigating is get an idea of how old those are. You can do this by querying pg_stat_activity and filtering for where the state is &lt;code&gt;idle in transaction&lt;/code&gt; and checking how old those queries are. For ones that have been running too long you may want to manually kill them.&lt;/p&gt;
&lt;p&gt;If you find that you have some stale transactions hanging around this could be for days, hours, or even just a few minutes you may want to set a default to kill those transactions.&lt;/p&gt;
&lt;p&gt;To help with this Postgres has a nice feature of a &lt;code&gt;statement_timeout&lt;/code&gt;. A statement timeout will automatically kill queries that run longer than the allotted time. You can set this at both a global level and for a specific session. To do this at the database level you&amp;rsquo;d run this with an &lt;code&gt;alter database dbnamehere set statement_timeout = 60000;&lt;/code&gt; which is 60 seconds. To do so during a given session simply run &lt;code&gt;set statment_timeout = 6000000;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For &lt;em&gt;idle in transaction&lt;/em&gt; that have been running too long there is its own setting setting that you can set in a similar fashion &lt;code&gt;idle_in_transaction_session_timeout&lt;/code&gt; (on Postgres 9.6 and up). Setting both &lt;code&gt;statement_timeout&lt;/code&gt; and &lt;code&gt;idle_in_transaction_session_timeout&lt;/code&gt; will help with cancelling long running queries and transactions.&lt;/p&gt;
&lt;p&gt;Keeping your connection limits in check should lead to a much healthier performing database and thus app.&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>Mon, 18 Sep 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/09/18/postgres-connection-management/</guid></item><item><title>Reflections on a Year of Daily Memory Drawings</title><link>https://johnj.com/posts/daily-composition-lessons-learned/</link><description>&lt;div class="outline-2" id="outline-container-headline-1"&gt;
&lt;h2 id="headline-1"&gt;
365 Drawings
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-1"&gt;
&lt;p&gt;
The sketchbooks shown below are the result of doing one drawing from
memory every day for a year, a project I finished this month.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_2934.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_2934_hu_d7079272117865da.jpg" style="width: 500px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
A year's worth of Daily Compositions
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
This drawing practice was based on the Daily Composition, which, as I
&lt;a href="./daily-memory-drawing.html"&gt;explained&lt;/a&gt; last January, is an exercise from &lt;em&gt;The Natural Way to Draw&lt;/em&gt;,
by &lt;a href="https://en.wikipedia.org/wiki/Kimon_Nicola%25C3%25AFdes"&gt;Kimon Nicolaïdes&lt;/a&gt; (published posthumously in 1941).  The
requirements for this exercise are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;See&lt;/em&gt; things and events that interest you throughout the day;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Remember&lt;/em&gt; them, and&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Capture&lt;/em&gt; them on paper, in the form of a single image …&lt;/li&gt;
&lt;li&gt;… &lt;em&gt;Once per day&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these is challenging in its own way, and each reinforces the
other.  Maintaining the practice over a full year taught me a number
of lessons.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0014-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0014-online_hu_e72bc2f803ffd4bb.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Example drawing: 54th and Cornell
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class="outline-3" id="outline-container-headline-2"&gt;
&lt;h3 id="headline-2"&gt;
Lesson 1: The limits of visual memory
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-2"&gt;
&lt;p&gt;
I’d struggled with this exercise now and again over the years, and in
taking it up again I was immediately reminded just how little I
remember of what I see throughout the day.&lt;/p&gt;
&lt;p&gt;
The mind is able to recognize, and, to a greater or lesser extent, to
respond mentally and emotionally to a stunning variety of objects and
occurrences in the world around us. This happens automatically and
without effort. But this sort of ordinary seeing is not the same as
being able to &lt;em&gt;recall&lt;/em&gt; and to visually &lt;em&gt;reproduce&lt;/em&gt; the things we
"see."&lt;/p&gt;
&lt;p&gt;
To demonstrate this to yourself, try to draw your spouse's face, or a
friend's, from memory. This is a person you would have no trouble
recognizing, even at some distance, yet you don't really have access
to how your brain stores that information. Now try to draw your car,
or bicycle, or the front of your building. These are things you know
well, yet you probably cannot describe them visually in much detail.&lt;/p&gt;
&lt;p&gt;
Doing this exercise faithfully made this fact painfully obvious.  Each
day, out of the millions of details that passed in front of my eyes, I
was left grasping only a handful of facts to work with at day's end.
(The number of memories was small, but I was surprised that it was
never zero.)&lt;/p&gt;
&lt;p&gt;
Contrast this with the capabilities of a camera: it faithfully records
the details it is exposed to, millions of bits of data per shot. But
the camera, a mere machine, cannot recognize or react emotionally to
those details&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-1" id="footnote-reference-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0004-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0004-online_hu_7013ec1e85de63d6.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Adams St. Bridge
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-3"&gt;
&lt;h3 id="headline-3"&gt;
Lesson 2: Trying to remember amplifies seeing
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-3"&gt;
&lt;p&gt;
It would be easy to think of the Daily Composition exercise as a way
of learning how to do a camera's job: you are exposed to scenes, and
later you record them on paper.  I did find myself, in fact, taking
mental "pictures" most days, of a person or group doing something, in
some specific place.  I would see a person getting into a cab, or
construction workers huddled over a hole, or (one day) a unicycle
rider cresting a small hill, and I would think, "that's it!" and try
to remember, for that evening's drawing, everything I could about the
moment I'd just seen.&lt;/p&gt;
&lt;p&gt;
During the course of the year, I didn't actually get that much better
in terms of the sheer number of details I could recall.  A half dozen
"facts" (the size and shape of a doorway; the size and number of
windows in a storefront; the particular shape of a woman's boots),
along with a rough gesture for and/or placement of the key figures,
were about as I could expect for any given day's drawing.&lt;/p&gt;
&lt;p&gt;
A much bigger change occurred in my ability to &lt;em&gt;notice&lt;/em&gt; things, and my
emotional response to them was amplified. Knowing that I needed
material for a drawing at the end of the day simply opened my eyes
more. It was like going on vacation somewhere totally new. I saw
things in my neighborhood, and on my commute, that I had passed by
without noticing for years: the shapes and placement of signs, light
poles, fire hydrants; the construction and weathering of steel
supports for elevated trains; the multitudes of ornamental details on
buildings. The endless variety of people's faces… commuters,
shopkeepers, construction workers, homeless men and women; the smiles,
grim stares (especially at commute times) or lines of care they bore;
their postures and gestures (all too often, in relationship to their
phones); the cut and fit of their clothing, coats, boots or shoes.
The endless repetitive movements of pigeons, and the surprising
variety of other birds (sparrows, hawks, cranes, herons, geese, ducks,
swallows, and several migratory bird species I couldn't identify).
The printed word, in steel or brass relief, to be seen everywhere in
streets and sidewalks, indicating lines of survey, or the origin or
builders of utility covers or nearby buildings. All the endless
varieties of trees, contours of trunks, branching patterns, leaves,
and all the grasses, flowers and weeds of the city… these things
came to my notice, were revealed fresh as though I had previously had
some sort of screen over my vision that had fallen away.&lt;/p&gt;
&lt;p&gt;
Part of &lt;em&gt;seeing&lt;/em&gt; these things became &lt;em&gt;caring&lt;/em&gt; about them.  In that regard I
became less, not more, like a camera.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0015-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0015-online_hu_a086311c63874f96.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Promontory Point
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-4"&gt;
&lt;h3 id="headline-4"&gt;
Lesson 3: Emotion aids recall
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-4"&gt;
&lt;p&gt;
If I saw something I reacted to emotionally, it was usually a lot
easier to recall later. This seems obvious, but to live the connection
between emotion and memory as part of one's daily routine for a year
had a cumulative effect.  This is what I meant when I said in my &lt;a href="./daily-memory-drawing.html"&gt;last
post&lt;/a&gt; that I felt a stronger connection to Chicago and my surroundings.
I suspect that building these sorts of connections to daily life is
one of the main reason Nicolaïdes recommends the exercise as a daily
practice.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0020-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0020-online_hu_eadcd6ef322bd9c1.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
South Loop Mural and Smoker
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-5"&gt;
&lt;h3 id="headline-5"&gt;
Lesson 4: Other tricks for remembering
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-5"&gt;
&lt;p&gt;
Aside from focusing on things that give an emotional charge, here are
some more tricks I used to remember things I saw:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Practice drawing or painting something while you look at it.&lt;/strong&gt; This
includes making movements in the air as if you were drawing,
building a little actual muscle memory (and inviting curious
glances from passersby).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Re-remember things&lt;/strong&gt;. If I saw something I wanted to "save up" for
the evening's drawing, then whenever I saw something &lt;em&gt;else&lt;/em&gt; that
looked interesting, I would look carefully at it, but then I would
use the whole noticing-something-noteworthy experience as a
reminder to remember the &lt;em&gt;other&lt;/em&gt; thing I was trying to remember
also.  In other words, every new thing I noticed became a reminder
to remember the other thing.  Occasionally, I would build a list of
things to remember and would then go through the list items
one-by-one whenever this occurred.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;De-distract and focus.&lt;/strong&gt; Of course, sometimes the above tricks got
to be too much; at those times, I'd try to minimize my visual input
by looking down at the sidewalk if safe to do so (allowing my
peripheral vision or looking up when needed, in order to keep from
getting hit by buses, etc.), just making the effort to hold the
memories in my mind while I walked or ran.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0030-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0030-online_hu_f4e978740993e80.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Weed whacking on the Lakefront
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-6"&gt;
&lt;h3 id="headline-6"&gt;
Lesson 5: Invention and knowledge help fill in details
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-6"&gt;
&lt;p&gt;
Given a relative paucity of remembered facts, how do you complete your
drawing? Just as our mind fills in details about what we see without
our being consciously aware of it, one can invent the elements of a
scene that elude our grasp when we try to recall them.  For this, a
knowledge of perspective, of human anatomy and clothing, of the
construction of builings and plants and trees, and especially of light
and shadow are indispensible for adding extra life and believability to
a composition, no matter how quickly executed.  For example, I would
rarely remember a &lt;em&gt;specific&lt;/em&gt; shadow, but if I knew where I was and
what time it was, I could place the shadows based on where the sun
would have been at the time. Used skillfully, invention can also &lt;em&gt;amplify&lt;/em&gt;
whatever emotional response led one to record the scene in one's mind
to begin with.&lt;/p&gt;
&lt;p&gt;
I think I got slightly better at "filling in the gaps" this way over
the year.  The exercise does seem to strengthen the connection
between memory, knowledge, and imagination.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0032-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0032-online_hu_96a505f7e1a7873.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Dearborn subway entrance
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-7"&gt;
&lt;h3 id="headline-7"&gt;
Lesson 6: Drawing can distort memory; revisiting a place helps
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-7"&gt;
&lt;p&gt;
I often noticed that, after drawing something that occurred in a
specific place, my memory would be strongly affected by whatever
inventions (or mistakes) I came up with to compensate for my ignorance
of the drawing's setting.  For this reason, I sometimes disliked
looking at the drawings after the fact because they were so clearly
wrong and they interfered with my "real" memory of where the event
occurred.  An easy remedy for this was just to go back to the place in
question and look around. One sees many more details the second time
around, and it's always amusing and humbling to realize how wrong you
got it the first time.&lt;/p&gt;
&lt;p&gt;
On a related note, I find that taking and reviewing photographs
shapes my memory as well. I remember things differently, and more
emotionally, having drawn them, either from life or from memory, than
I do when I've photographed them.  I sometimes limit my photography
when I travel for this reason (although I still take a ton of
pictures).&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0006-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0006-online_hu_5d22614547dbcf83.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
North Avenue Apple Store
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-8"&gt;
&lt;h3 id="headline-8"&gt;
Lesson 7: Don't make it a big deal
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-8"&gt;
&lt;p&gt;
To do the exercise three hundred and sixty five days in a row did
require commitment, since I have a busy schedule and was generally
doing it at the end of the day when my &lt;a href="http://www.webmd.com/diet/features/willpower-facts#1"&gt;willpower budget&lt;/a&gt; and my ability
to focus were all but spent.&lt;/p&gt;
&lt;p&gt;
Nicolaïdes makes a point of not making a big deal of these drawings,
setting a fifteen minute time limit for each.  I broke this rule many
times, especially at the beginning when I would try to recall as much
as possible.  Eventually, however, I settled for just jotting down a
few things I remembered seeing (sometimes starting with just
remembering where I was and what I did, which could be hard enough),
and turning the most compelling memory into a small composition.  Even
on days when I was the most busy and distracted I could typically
remember at least one thing to put down on paper.  And I found there
was only a loose correlation between how much effort I put into
remembering things throughout any given day, and how much I liked the
drawing at the end of that day.  Some days I was excited about the
results, and some days I was just happy to put the drawing away
afterward.  Part of what's good about doing something like this is you
can fail over and over again, and your daily commitment to the
practice means that any specific failure is no big deal.&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-2" id="footnote-reference-2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0027-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0027-online_hu_e88cb84ccf7e83e9.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cyclists kissing at The Point
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-9"&gt;
&lt;h3 id="headline-9"&gt;
Lesson 8: More can be better
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-9"&gt;
&lt;p&gt;
At least half the drawings are so bad, I find them pretty painful to
look at now.  Many of them show an interesting tidbit or idea worth
developing further.  And a small fraction, less than 10%, I enjoy
looking at and find appealing on their own terms. Some of these are
shown here.&lt;/p&gt;
&lt;p&gt;
The few successes illustrate an important rule that I still struggle
with: with art making, sometimes quantity wins.  I prefer to work for
a long time on paintings, but it is nice to complete something every
day and, occasionally, to have it succeed.  No matter who you are, I
suspect if you make a drawing a day for a whole year, at least a few
of them will suprise and please you.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0017-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0017-online_hu_6a67fe54854d52ad.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Randolph and Wabash
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-10"&gt;
&lt;h3 id="headline-10"&gt;
Lesson 9: It's about composition
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-10"&gt;
&lt;p&gt;
Composition is about choosing what goes in a picture and arranging
those things in a pleasing design which communicates one's ideas or
intentions.  One reason I took up this practice is that I find
inventing compositions (e.g., in the studio) more challenging than
finding them directly in front of me.  Ultimately, memory and
rendering are only part of the practice… the rest (perhaps the
biggest part) is design. Nearly four hundred drawings later I still
find it challenging, but solving a specific design problem every night
has made the whole problem of composition seem tractable in a way it
didn't before.  This, I imagine, was another reason Nicolaïdes
emphasized this exercise.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0008-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0008-online_hu_d2cd5cc5683976fe.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Planting Bulbs
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-11"&gt;
&lt;h2 id="headline-11"&gt;
Moving forward
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-11"&gt;
&lt;blockquote&gt;
&lt;p&gt;It will be helpful if you keep this up for a year, and it will be
twice as helpful if you keep it up for two years. The really serious
student will make a quick composition every day for the rest of his
life despite everything else he has to do. –Nicolaïdes&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
In later chapters of &lt;em&gt;The Natural Way to Draw&lt;/em&gt;, variations on the
Daily Composition are introduced, including a greater amount of
invention, and revisiting the same scene over several days in an
extended composition.  For myself, I wanted the challenge of working
primarily from memory for a year, but have increasingly been craving
more time for both invention and for working from life. I intend to
continue regular compositional practice, but more as a natural and
playful part of my creative rhythm, rather than as a tightly-defined
daily practice.  I don't know where it will lead, but look forward to
finding out.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-12"&gt;
&lt;h2 id="headline-12"&gt;
More Drawings
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-12"&gt;
&lt;p&gt;
Here are a few more drawings from the year.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0018-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0018-online_hu_5c4add0eef962d8f.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Shambhala Center
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0002-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0002-online_hu_f85477a99ad051fd.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
54th and Cornell
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0011-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0011-online_hu_8ed9fd9e57d36147.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Van Buren
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0031-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0031-online_hu_ffd710c0494b12f7.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Truck, alley off Van Buren
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0022-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0022-online_hu_d79eb53bf5edcee0.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
March for Science, Columbus Drive
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0023-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0023-online_hu_bc084553557c5484.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Hipster cyclist crossing Metra tracks
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0025-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0025-online_hu_e2afde0e47eca187.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Stephen Assael class demo
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0034-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0034-online_hu_a827cc3d1d789f2.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Printers' Row Book Fair
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0012-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0012-online_hu_eb9ccacbc943203d.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
55th St.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0013-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0013-online_hu_d8b7230ab2f8673a.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cement mixer, Lake Shore Drive under McCormick Place
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0016-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0016-online_hu_c441dacfdf1c5834.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
63rd St. Beach
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20170917_0033-online.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20170917_0033-online_hu_e20285879b56f3c9.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Checking phone, near Oak St.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnotes"&gt;
&lt;hr class="footnotes-separatator" /&gt;
&lt;div class="footnote-definitions"&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-1"&gt;&lt;a href="#footnote-reference-1"&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;Some machine learning systems have gotten pretty good at recognizing specific objects in a digital image; thankfully, none of these has emotions yet.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-2"&gt;&lt;a href="#footnote-reference-2"&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;The ability to fail and to start anew, over and over again, is the most important creative skill that I know of.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Mon, 18 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/daily-composition-lessons-learned/</guid></item><item><title>Visualizing the sentiments in U.S. Presidential Inauguration Speeches</title><link>https://bastian.rieck.me/blog/2017/inauguration_speeches_sentiment_analysis/</link><description>&lt;p&gt;In previous posts, I wrote about &lt;a href="https://bastian.rieck.me/blog/2017/inauguration_speeches_brief/"&gt;a brief analysis of U.S. Presidential
Inauguration Speeches&lt;/a&gt; and
&lt;a href="https://bastian.rieck.me/blog/2017/inauguration_speeches_tf_idf/"&gt;how to extend this analysis using
tf–idf&lt;/a&gt;. In this
post, I want to present an extended analysis based on &lt;em&gt;sentiment
analysis&lt;/em&gt;. Sentiment analysis encompasses a class of techniques for
detecting whether sentences are mean either negatively, neutrally, or
positively.&lt;/p&gt;
&lt;h1 id="depicting-sentiment-over-time"&gt;Depicting sentiment over time&lt;/h1&gt;
&lt;p&gt;Since every inauguration speech has a beginning and an end, it forms
a natural time-series. Hence, I first calculated the sentiment scores
for every sentence in a speech and scaled an artificial &lt;em&gt;time&lt;/em&gt; parameter
over the speech between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;. This yields a nice &lt;em&gt;sentiment
curve&lt;/em&gt; plot, in which the abscissa denotes the time of the speech, and
the ordinate denotes the sentiment of a given sentence—with values
close to &lt;code&gt;+1&lt;/code&gt; meaning that the sentence is extremely positive, &lt;code&gt;0&lt;/code&gt;
meaning that the sentence is neutral, and &lt;code&gt;-1&lt;/code&gt; meaning that the sentence
is extremely negative.&lt;/p&gt;
&lt;p&gt;Here are some example visualizations of the last three inauguration
speeches. Positive sentences are shown in green, while negative ones are
shown in red. I am filling the distance between true neutral sentences
with the colour in order to show patterns and ‘rhythm’ of
different speeches. A black line indicates the &lt;em&gt;mean&lt;/em&gt; sentiment over the
speech.&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_sentiments_obama_2009.svg"&gt;&lt;img alt="Sentiment curve for Barack Obama (2009)" src="https://bastian.rieck.me/images/inauguration_speeches_sentiments_obama_2009.svg" width="800" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_sentiments_obama_2013.svg"&gt;&lt;img alt="Sentiment curve for Barack Obama (2013)" src="https://bastian.rieck.me/images/inauguration_speeches_sentiments_obama_2013.svg" width="800" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_sentiments_trump_2017.svg"&gt;&lt;img alt="Sentiment curve for Donald J. Trump (2017)" src="https://bastian.rieck.me/images/inauguration_speeches_sentiments_trump_2017.svg" width="800" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;It is interesting to see that Obama’s &lt;em&gt;first&lt;/em&gt; speech appears to be
more subdued and neutral than the subsequent speeches, which exhibit
more peaks and thus a larger variability between extremely positive and
extremely negative sentiment.&lt;/p&gt;
&lt;p&gt;If you want to &lt;em&gt;compare&lt;/em&gt; the different sentiment curves for your
favourite presidents, you may do so—I have prepared a &lt;a href="https://bastian.rieck.me/images/inauguration_speeches_sentiments_all.svg"&gt;large
visualization that combines all sentiment
curves&lt;/a&gt;.
Watching the appearance and disappearance of negative sentiments over
time is quite fascinating. The 1945 speech by Roosevelt is a striking
example of evoking very negative imagery for a prolonged period of time.&lt;/p&gt;
&lt;h1 id="comparing-mean-sentiments"&gt;Comparing mean sentiments&lt;/h1&gt;
&lt;p&gt;For comparing individual presidents, the curves are well and good, but
I was also interested in the &lt;em&gt;global&lt;/em&gt; sentiment of a speech and how it
evolves over time. To this end, I calculated the &lt;em&gt;mean&lt;/em&gt; (average)
sentiment over every speech and depicted it over time. This works
because sentiments are &lt;em&gt;always&lt;/em&gt; bounded between &lt;code&gt;[-1:1]&lt;/code&gt;, making their
comparison very easy. Here is the average sentiment of a speech, plotted
over time:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_mean_sentiment_over_time.svg"&gt;&lt;img alt="Average sentiment of a speech over time" src="https://bastian.rieck.me/images/inauguration_speeches_mean_sentiment_over_time.svg" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;We can see an interesting pattern: after the second World War, speeches
become more positive on average. They remain that way until the first
inauguration speech of Barack Obama, which, as I noted above, is
somewhat subdued again. Afterwards, they pick up steam. Donald
Trump’s speech evokes more positive sentiments, on average, than
most of the speeches since 1945.&lt;/p&gt;
&lt;p&gt;All in all, I think that this is a nice tool to assess patterns in
speeches. If you want, go take a look at the individual sentiment
curves, which are &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches/tree/master/Output/Sentiments"&gt;stored on
GitHub&lt;/a&gt;.
Maybe you pick up something interesting.&lt;/p&gt;
&lt;h1 id="code"&gt;Code&lt;/h1&gt;
&lt;p&gt;I used the intriguing
&lt;a href="https://textblob.readthedocs.io/en/dev"&gt;&lt;code&gt;TextBlob&lt;/code&gt;&lt;/a&gt; Python module for
this analysis. All visualizations are done using
&lt;a href="http://gnuplot.info"&gt;&lt;code&gt;gnuplot&lt;/code&gt;&lt;/a&gt;. As usual, the scripts and data
files—as well as the output—is stored in the &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches"&gt;GitHub
repository&lt;/a&gt; for
the project.&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 17 Sep 2017 17:13:22 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/inauguration_speeches_sentiment_analysis/</guid></item><item><title>The Mathematics of 2048: Counting States with Combinatorics</title><link>http://jdlm.info/articles/2017/09/17/counting-states-combinatorics-2048.html</link><description>&lt;p&gt;&lt;strong&gt;Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2017-09-25&lt;/strong&gt; There was some lively &lt;a href="https://news.ycombinator.com/item?id=15327837"&gt;discussion about this article on Hacker News&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is the second in a series. Next: &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html"&gt;Counting States by Exhaustive Enumeration&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot of 2048 with an infeasible board configuration" src="/assets/2048/2048_infeasible.png" style="width: 40%; float: right; margin-left: 10pt; border: 6pt solid #eee;" /&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;my last 2048 post&lt;/a&gt;, I found that it takes at least 938.8 moves on average to win a game of &lt;a href="http://gabrielecirulli.github.io/2048"&gt;2048&lt;/a&gt;. The main simplification that enabled that calculation was to ignore the structure of the board — essentially to throw the tiles into a bag instead of placing them on a board. With the ‘bag’ simplification, we were able to model the game as a Markov chain with only 3486 distinct states.&lt;/p&gt;

&lt;p&gt;In this post, we’ll make a first cut at counting the number of states without the bag simplification. That is, in this post a &lt;em&gt;state&lt;/em&gt; captures the complete configuration of the board by specifying which tile, if any, is in each of the board’s cells. We would therefore expect there to be a lot more states of this kind, now that the positions of the tiles (and cells without tiles) are included, and we will see that this is indeed the case.&lt;/p&gt;

&lt;p&gt;To do so, we will use some (simple) techniques from enumerative combinatorics to exclude some states that we can write down but which can’t actually occur in the game, such as the one above. The results will also apply to 2048-like games played on different boards (not just 4x4) and up to different tiles (not just the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile). We’ll see that such games on smaller boards and/or to smaller tiles have far fewer states than the full 4x4 game to 2048, and that the techniques used here are relatively much more effective at reducing the estimated number of states when the board size is small. As a bonus, we’ll also see that the 4x4 board is the smallest square board on which it is possible to reach the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;The (research quality) code behind this article is &lt;a href="https://github.com/jdleesmiller/twenty48"&gt;open source&lt;/a&gt;, in case you would like to see the &lt;a href="https://github.com/jdleesmiller/twenty48/blob/4337c357f2cc14bdc3e14ddaa5207ad2a6a972e6/bin/combinatorics"&gt;implementation&lt;/a&gt; or &lt;a href="https://github.com/jdleesmiller/twenty48/tree/4337c357f2cc14bdc3e14ddaa5207ad2a6a972e6/data/combinatorics"&gt;code for the plots&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id="baseline"&gt;Baseline&lt;/h1&gt;

&lt;p&gt;The most straightforward way to estimate the number of states in 2048 is to observe that there are 16 cells, and each cell can either be blank or contain a tile with a value that is one of the 11 powers of 2 from 2 to 2048. That gives 12 possibilities for each of the 16 cells, for a total of \(12^{16}\), or 184 quadrillion (~\(10^{17}\)), possible states that we can write in this way. For comparison, &lt;a href="https://tromp.github.io/chess/chess.html"&gt;some estimates&lt;/a&gt; put the number of possible board configurations for the game of chess at around \(10^{45}\) states, and &lt;a href="https://en.wikipedia.org/wiki/Go_and_mathematics#Complexity_of_certain_Go_configurations"&gt;the latest estimates&lt;/a&gt; for the game of Go are around \(10^{170}\) states, so while \(10^{17}\) is large, it’s certainly not the largest as games go.&lt;/p&gt;

&lt;p&gt;For 2048-like games more generally, let \(B\) be the board size, and let \(K\) be the exponent of the winning tile with value \(2^K\). For convenience, let \(C\) denote the number of cells on the board, so \(C=B^2\). For the usual 4x4 game to 2048, \(B=4\), \(C=16\), and \(K = 11\), since \(2^{11} = 2048\), and our estimate for the number of states is \[(K + 1)^C.\] Now let’s see how we can refine this estimate.&lt;/p&gt;

&lt;p&gt;First, since the game ends when we obtain a \(2^K\) tile, we don’t particularly care about where that tile is or what else is on the board. We can therefore condense all of the states with a \(2^K\) tile into a special “win” state. In the remaining states, each cell can either be blank or hold one of \(K - 1\) tiles. This reduces the number of states we have to worry about to \[K^C + 1\] where the \(1\) is for the win state.&lt;/p&gt;

&lt;p&gt;Second, we can observe that some of those \(K^C\) states can never occur in the game. In particular, the rules of the game imply two useful properties:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property 1:&lt;/strong&gt; There are always at least two tiles on the board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property 2:&lt;/strong&gt; There is always at least one &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile on the board.&lt;/p&gt;

&lt;p&gt;The first property holds because even if you start with two tiles and merge them, there is still one left, and then the game adds a random tile, leaving two tiles. The second property holds because the game always adds a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile after each move.&lt;/p&gt;

&lt;p&gt;We therefore know that in any valid state there must be at least two tiles on the board, and that one of them must be a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile. To account for this, we can subtract all states with no &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile, of which are \((K-2)^C\), and also the states with just one &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile and all other cells empty, of which there are \(C\), and the states with only one &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile and all other cells empty, of which there are again \(C\). This gives an estimate of
\[K^C - (K-2)^C - 2C + 1\]
states in total. Of course, when \(K\) or \(C\) is large, this looks pretty much just like \(K^C\), which is the dominant term, but this correction is more significant for smaller values.&lt;/p&gt;

&lt;p&gt;Let’s use this formula to tabulate the estimated number of states various board sizes and maximum tiles:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Maximum Tile&lt;/th&gt;
      &lt;th colspan="3"&gt;Board Size&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th align="right"&gt;2x2&lt;/th&gt;
      &lt;th align="right"&gt;3x3&lt;/th&gt;
      &lt;th align="right"&gt;4x4&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;8&lt;/td&gt;
      &lt;td align="right"&gt;73&lt;/td&gt;
      &lt;td align="right"&gt;19,665&lt;/td&gt;
      &lt;td align="right"&gt;43,046,689&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;16&lt;/td&gt;
      &lt;td align="right"&gt;233&lt;/td&gt;
      &lt;td align="right"&gt;261,615&lt;/td&gt;
      &lt;td align="right"&gt;4,294,901,729&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;32&lt;/td&gt;
      &lt;td align="right"&gt;537&lt;/td&gt;
      &lt;td align="right"&gt;1,933,425&lt;/td&gt;
      &lt;td align="right"&gt;152,544,843,873&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;64&lt;/td&gt;
      &lt;td align="right"&gt;1,033&lt;/td&gt;
      &lt;td align="right"&gt;9,815,535&lt;/td&gt;
      &lt;td align="right"&gt;2,816,814,940,129&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;128&lt;/td&gt;
      &lt;td align="right"&gt;1,769&lt;/td&gt;
      &lt;td align="right"&gt;38,400,465&lt;/td&gt;
      &lt;td align="right"&gt;33,080,342,678,945&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;256&lt;/td&gt;
      &lt;td align="right"&gt;2,793&lt;/td&gt;
      &lt;td align="right"&gt;124,140,015&lt;/td&gt;
      &lt;td align="right"&gt;278,653,866,803,169&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;512&lt;/td&gt;
      &lt;td align="right"&gt;4,153&lt;/td&gt;
      &lt;td align="right"&gt;347,066,865&lt;/td&gt;
      &lt;td align="right"&gt;1,819,787,258,282,209&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;1024&lt;/td&gt;
      &lt;td align="right"&gt;5,897&lt;/td&gt;
      &lt;td align="right"&gt;865,782,255&lt;/td&gt;
      &lt;td align="right"&gt;9,718,525,023,289,313&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;2048&lt;/td&gt;
      &lt;td align="right"&gt;8,073&lt;/td&gt;
      &lt;td align="right"&gt;1,970,527,185&lt;/td&gt;
      &lt;td align="right"&gt;44,096,709,674,720,289&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;We can see immediately that the 2x2 and 3x3 games have many orders of magnitude fewer states than the 4x4 game. We’ve also also managed to reduce our estimate for the number of tiles in the 4x4 game to 2048 to “only” 44 quadrillion, or ~\(10^{16}\).&lt;/p&gt;

&lt;h1 id="counting-in-layers"&gt;Counting in Layers&lt;/h1&gt;

&lt;p&gt;To gain some additional insight into these state counts, we can take advantage of another important property, which was also useful in the last post:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property 3:&lt;/strong&gt; The sum of the tiles on the board increases by either 2 or 4 with each move.&lt;/p&gt;

&lt;p&gt;This holds because merging two tiles does not change the sum of the tiles on the board, and the game then adds either a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;Property 3 implies that states never repeat in the course of a game. This means that we can organize the states into &lt;em&gt;layers&lt;/em&gt; according to the sum of their tiles. If the game is in a state in the layer with sum 10, we know that the next state must be in the layer with either sum 12 or sum 14. It turns out we can also count the number of states in each layer, as follows.&lt;/p&gt;

&lt;p&gt;Let \(S\) denote the sum of the tiles on the board. We want to count the number of ways that up to \(C\) numbers, each of which is a power of 2 between 2 and \(2^{K-1}\), can be added together to produce \(S\).&lt;/p&gt;

&lt;p&gt;Fortunately, this turns out to be a variation on a well-studied problem in combinatorics: counting the &lt;a href="https://en.wikipedia.org/wiki/Composition_(combinatorics)"&gt;compositions of an integer&lt;/a&gt;. In general, a composition of an integer \(S\) is an ordered collection of integers that sum to \(S\); each integer in the collection is called a &lt;em&gt;part&lt;/em&gt;. For example, there are four compositions of the integer \(3\), namely \(1 + 1 + 1\), \(1 + 2\), \(2 + 1\) and \(3\). When there are restrictions on the parts, such as being a power of two and only having a certain number of parts, the term is a &lt;em&gt;restricted&lt;/em&gt; composition.&lt;/p&gt;

&lt;p&gt;Even more fortunately, Chinn and Niederhausen (2004) &lt;sup id="fnref:Chinn"&gt;&lt;a class="footnote" href="#fn:Chinn" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; have already studied exactly this kind of restricted composition and derived a recurrence that allows us count the number of compositions in which there are a specific number of parts, and each part is a power of 2. Let \(N(s, c)\) denote the number of compositions of a (positive) integer \(s\) into exactly \(c\) parts where each part is a power of 2. It then holds that
\[
N(s, c) = \begin{cases}
\sum_{i = 0}^{\lfloor \log_2 s \rfloor} N(s - 2^i, c - 1), &amp;amp; 2 \le c \le s \\\&lt;br /&gt;
1, &amp;amp; c = 1 \textrm{ and } s \textrm{ is a power of 2} \\\&lt;br /&gt;
0, &amp;amp; \textrm{otherwise}
\end{cases}
\]
because for every composition of \(s - 2^i\) into \(c - 1\) parts, we can obtain a composition of \(s\) with \(c\) parts by adding one part with value \(2^i\).&lt;/p&gt;

&lt;p&gt;We now just need to make a few minor adjustments to the summation bounds: we would like to use powers of 2 starting at 2 and at most \(2^{K-1}\), since if we have a \(2^K\) tile the game is won. To this end, let \(N_m(s, c)\) denote the number of compositions of \(s\) into exactly \(c\) parts where each part is a power of 2 between \(2^m\) and \(2^{K-1}\). This is given by
\[
N_m(s, c) = \begin{cases}
\sum_{i = m}^{K - 1} N(s - 2^i, c - 1), &amp;amp; 2 \le c \le s \\\&lt;br /&gt;
1, &amp;amp; c = 1 \textrm{ and }
     s = 2^i \textrm{ for some } i \in \{ m, \ldots, K-1 \} \\\&lt;br /&gt;
0, &amp;amp; \textrm{otherwise}
\end{cases}
\]
following the same logic as above.&lt;/p&gt;

&lt;p&gt;Now we have a formula for exactly \(c\) parts, but we want a formula for up to \(c\) parts. We can follow the same rationale as in the previous section: subtract off the states with no 2 or 4 tile, of which there are \(N_3(s, c)\). According to property 1, we need at least 2 parts, so we start summing at \(c=2\). This gives
\[
\sum_{c = 2}^{C} {C \choose c} \left( N_1(s, c) - N_3(s, c) \right)
\]
as our estimate for the number of states with sum \(s\). Here \(C \choose c\) is a &lt;a href="https://en.wikipedia.org/wiki/Binomial_coefficient"&gt;binomial coefficient&lt;/a&gt; that gives the number ways of choosing \(c\) of the possible \(C\) cells into which to place the tiles. Let’s plot it out.&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Number of states by sum of tiles (with K=11)" src="/assets/2048/combinatorics_layers_summary.png" /&gt;
&lt;/p&gt;

&lt;p&gt;In terms of magnitude, we can see that the 2x2 game never has more than 60 states in any layer, the 3x3 game peaks at about 3 million states per layer, and the 4x4 game peaks at about 32 trillion (\(10^{13}\)) states per layer. The number of states grows rapidly early in the game but then tapers off and eventually decreases as the board fills up. On the decreasing portion of the curve, we see discontinuities: particularly for higher sums, it may happen that there are no tiles that will fit on the board and sum to that value.&lt;/p&gt;

&lt;p&gt;The upper limit on the horizontal axis arises because we can have \(C\) values, each up to \(2^{K-1}\), so the maximum achievable sum is \(C 2^{K-1}\), or 16,384 for the 4x4 game to 2048.&lt;/p&gt;

&lt;p&gt;Finally, it’s worth noting that if we sum the number of states in each layer over all of the possible layer sums from 4 to \(C 2^{K-1}\), and add one for the special win state, we get the same number of states as we estimated in the previous section, which is a helpful sanity check.&lt;/p&gt;

&lt;h3 id="layer-reachability"&gt;Layer Reachability&lt;/h3&gt;

&lt;p&gt;Another useful consequence of Property 3 is that if two consecutive layers have no states, it’s not possible to reach later layers. This is because the sum can increase by at most 4 per turn; if there are two adjacent layers with no states, then the sum would have to increase by 6 in a single move in order to ‘jump’ to the subsequent layer, which is not possible. Finding the layer sums that contain no states according to the calculation above therefore allows us to tighten up our estimate by excluding states in unreachable layers after the last reachable layer. The largest reachable layer sums (without ever attaining a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile) are:&lt;/p&gt;

&lt;table style="width: auto;"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Board Size&lt;/th&gt;
      &lt;th&gt;Largest Reachable Layer Sum&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2x2&lt;/td&gt;
      &lt;td align="right"&gt;60&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3x3&lt;/td&gt;
      &lt;td align="right"&gt;2,044&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4x4&lt;/td&gt;
      &lt;td align="right"&gt;9,212&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;This table also tells us that the highest tile we can reach on the 2x2 board is the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile, because the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile can’t occur in a layer with sum 60 or less, and similarly highest reachable tile on the 3x3 board is the &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt; tile. This means that the 4x4 board is the smallest square board on which it’s possible to reach the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile &lt;sup id="fnref:smallest-board"&gt;&lt;a class="footnote" href="#fn:smallest-board" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;. For the 4x4 board, the largest layer sum we can reach without reaching a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile (and therefore winning) is 9,212, but larger sums would be reachable if we did allow a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;Taking into account layer reachability, the new estimates for the number of states are:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Maximum Tile&lt;/th&gt;
      &lt;th&gt;Method&lt;/th&gt;
      &lt;th colspan="3"&gt;Board Size&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th align="right"&gt;2x2&lt;/th&gt;
      &lt;th align="right"&gt;3x3&lt;/th&gt;
      &lt;th align="right"&gt;4x4&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;8&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;73&lt;/td&gt;&lt;td align="right"&gt;19,665&lt;/td&gt;&lt;td align="right"&gt;43,046,689&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;73&lt;/td&gt;&lt;td align="right"&gt;19,665&lt;/td&gt;&lt;td align="right"&gt;43,046,689&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;16&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;233&lt;/td&gt;&lt;td align="right"&gt;261,615&lt;/td&gt;&lt;td align="right"&gt;4,294,901,729&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;233&lt;/td&gt;&lt;td align="right"&gt;261,615&lt;/td&gt;&lt;td align="right"&gt;4,294,901,729&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;32&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;537&lt;/td&gt;&lt;td align="right"&gt;1,933,425&lt;/td&gt;&lt;td align="right"&gt;152,544,843,873&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;529&lt;/td&gt;&lt;td align="right"&gt;1,933,407&lt;/td&gt;&lt;td align="right"&gt;152,544,843,841&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;64&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;1,033&lt;/td&gt;&lt;td align="right"&gt;9,815,535&lt;/td&gt;&lt;td align="right"&gt;2,816,814,940,129&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;905&lt;/td&gt;&lt;td align="right"&gt;9,814,437&lt;/td&gt;&lt;td align="right"&gt;2,816,814,934,817&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;128&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;1,769&lt;/td&gt;&lt;td align="right"&gt;38,400,465&lt;/td&gt;&lt;td align="right"&gt;33,080,342,678,945&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;905&lt;/td&gt;&lt;td align="right"&gt;38,369,571&lt;/td&gt;&lt;td align="right"&gt;33,080,342,314,753&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;256&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;2,793&lt;/td&gt;&lt;td align="right"&gt;124,140,015&lt;/td&gt;&lt;td align="right"&gt;278,653,866,803,169&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;905&lt;/td&gt;&lt;td align="right"&gt;123,560,373&lt;/td&gt;&lt;td align="right"&gt;278,653,849,430,401&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;512&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;4,153&lt;/td&gt;&lt;td align="right"&gt;347,066,865&lt;/td&gt;&lt;td align="right"&gt;1,819,787,258,282,209&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;905&lt;/td&gt;&lt;td align="right"&gt;339,166,485&lt;/td&gt;&lt;td align="right"&gt;1,819,786,604,950,209&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;1024&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;5,897&lt;/td&gt;&lt;td align="right"&gt;865,782,255&lt;/td&gt;&lt;td align="right"&gt;9,718,525,023,289,313&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;905&lt;/td&gt;&lt;td align="right"&gt;786,513,819&lt;/td&gt;&lt;td align="right"&gt;9,718,504,608,259,073&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th align="right" rowspan="2" valign="top"&gt;2048&lt;/th&gt;
      &lt;td&gt;Baseline&lt;/td&gt;
      &lt;td align="right"&gt;8,073&lt;/td&gt;&lt;td align="right"&gt;1,970,527,185&lt;/td&gt;&lt;td align="right"&gt;44,096,709,674,720,289&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Layer Reachability&lt;/td&gt;
      &lt;td align="right"&gt;905&lt;/td&gt;&lt;td align="right"&gt;1,400,665,575&lt;/td&gt;&lt;td align="right"&gt;44,096,167,159,459,777&lt;/td&gt;
    &lt;/tr&gt;

  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;This has a large effect on the 2x2 board, reducing the number of states from 8,073 to 905 for the game up to 2048, and it’s notable that the figure for the number of reachable states does not increase from 905 for maximum tiles over &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt;, because it’s not possible to reach tiles larger than &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; on a 2x2 board. It also has some effect on the 3x3 board, but on the 4x4 board, there is relatively little effect — we remove “only” about 500 billion states from the total for the game to 2048.&lt;/p&gt;

&lt;p&gt;In graphical form, these data look like:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Estimated number of states each for board size and maximum tile" src="/assets/2048/combinatorics_totals.svg" /&gt;
&lt;/p&gt;

&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;We’ve obtained some rough estimates for the number of states in the game of 2048 and similar games on smaller boards and to lesser tiles. Our best estimate so far for the number of states in the 4x4 game to 2048 is roughly 44 quadrillion (~\(10^{16}\)).&lt;/p&gt;

&lt;p&gt;It is likely that this and the other estimates are substantial overestimates, because there are many reasons that states might be counted here but still not be reachable in the game. For example, a state like the one in the cover image for this blog post:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="An infeasible board position with three 2 tiles in the middle with empty cells around" src="/assets/2048/2048_infeasible_board.png" /&gt;
&lt;/p&gt;

&lt;p&gt;satisfies all of the restrictions we’ve considered here, but it is still not possible to reach it, because we must have swiped in some direction before getting to this state, and that would have moved two of the &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles to the edge of the board. It may be possible to adapt the counting arguments above to take this (and likely other restrictions) into account, but I have not figured out how!&lt;/p&gt;

&lt;p&gt;In &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html"&gt;the next post&lt;/a&gt;, we’ll see that the number of actually reachable states is much lower by actually enumerating them. There will still be a lot of them for the 3x3 and 4x4 boards, so we will need some computer science as well as mathematics.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;If you’ve read this far, perhaps you should &lt;a href="https://twitter.com/jdleesmiller"&gt;follow me on twitter&lt;/a&gt;, or even apply to work at &lt;a href="https://www.overleaf.com/jobs"&gt;Overleaf&lt;/a&gt;. &lt;code class="language-plaintext highlighter-rouge"&gt;:)&lt;/code&gt;&lt;/p&gt;

&lt;h1 id="footnotes"&gt;Footnotes&lt;/h1&gt;





&lt;!--
To make the infeasible state diagram:

Go to http://gabrielecirulli.github.io/2048/
Open dev console
gm = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager)
// Remove the two random tiles (if needed); for me they were:
gm.grid.removeTile(new Tile({x: 0, y: 2}))
gm.grid.removeTile(new Tile({x: 3, y: 3}))
gm.actuate()
// Board should be empty
gm.grid.insertTile(new Tile({x: 1, y: 1}, 2))
gm.grid.insertTile(new Tile({x: 2, y: 1}, 2))
gm.grid.insertTile(new Tile({x: 1, y: 2}, 2))
gm.actuate()
// Board should have the three faked tiles.
--&gt;
&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:Chinn"&gt;
      &lt;p&gt;Chinn, P. and Niederhausen, H., 2004. Compositions into powers of 2. &lt;em&gt;Congressus Numerantium&lt;/em&gt;, 168, p.215. &lt;a href="http://math.fau.edu/Niederhausen/HTML/Papers/CompositionsIntoPowersOf2.doc"&gt;(preprint)&lt;/a&gt; &lt;a class="reversefootnote" href="#fnref:Chinn"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:smallest-board"&gt;
      &lt;p&gt;We could also have shown this using the Markov chain analysis from &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;my previous post&lt;/a&gt; by removing all of the states with more than nine tiles, and seeing whether it was still possible to reach the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile. If we &lt;a href="https://github.com/jdleesmiller/twenty48/blob/4337c357f2cc14bdc3e14ddaa5207ad2a6a972e6/bin/markov_chain#L382-L397"&gt;do this&lt;/a&gt;, we find that &lt;a href="https://github.com/jdleesmiller/twenty48/blob/4337c357f2cc14bdc3e14ddaa5207ad2a6a972e6/data/markov_chain/minmax_cells.csv"&gt;it is not&lt;/a&gt;. Interestingly, if we allow the Markov chain to continue to larger maximum tile values, the same analysis shows that it is possible to reach the &lt;code class="language-plaintext highlighter-rouge"&gt;131072&lt;/code&gt; (that is, \(2^{17}\)) tile on a 4x4 board, if the structure of the board is ignored. Whether this is true when there are structural constraints is still open, but I suspect it is not. It is, however, possible to play to at least the &lt;code class="language-plaintext highlighter-rouge"&gt;8192&lt;/code&gt; tile, as shown by &lt;a href="https://www.youtube.com/watch?v=96ab_dK6JM0"&gt;this AI bot&lt;/a&gt;, and there is a &lt;a href="https://www.youtube.com/watch?v=MDkZkweB5lM"&gt;‘proof of concept’ video&lt;/a&gt; for the &lt;code class="language-plaintext highlighter-rouge"&gt;131072&lt;/code&gt; tile. &lt;a class="reversefootnote" href="#fnref:smallest-board"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>jdlm.info</author><pubDate>Sun, 17 Sep 2017 04:00:00 GMT</pubDate><guid isPermaLink="true">http://jdlm.info/articles/2017/09/17/counting-states-combinatorics-2048.html</guid></item><item><title>Home Server Build</title><link>https://captnemo.in/blog/2017/09/17/home-server-build/</link><description>&lt;p&gt;I’d been planning to run my own home server for a while, and this culminated in a mini-ITX build recently. The current build configuration is available at &lt;a href="/setup/homeserver/"&gt;/setup/homeserver/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In no particular order, here were the constraints:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The case should be small (I preferred the Elite 110, but it was unavailable in India).&lt;/li&gt;
  &lt;li&gt;Dual LAN, if possible (decided against it at the end). The plan was to run the entire home network from this directly by plugging in the ISP into the server.&lt;/li&gt;
  &lt;li&gt;Recent i3/i5 for amd64 builds.&lt;/li&gt;
  &lt;li&gt;Enough SATA bays in the cabinet for storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The plans for the server:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Scheduled backups from other sources (Android/Laptop)&lt;/li&gt;
  &lt;li&gt;Run Kodi (or perhaps switch to Emby)&lt;/li&gt;
  &lt;li&gt;Run torrents. Transmission-daemon works. Preferably something pluggable and that works with RSS&lt;/li&gt;
  &lt;li&gt;Do amd64 builds. See https://github.com/captn3m0/ideas#arch-linux-package-build-system&lt;/li&gt;
  &lt;li&gt;Host a webserver. This is primarily for serving resources off the internet
    &lt;ul&gt;
      &lt;li&gt;Host some other minor web-services&lt;/li&gt;
      &lt;li&gt;A simple wiki&lt;/li&gt;
      &lt;li&gt;Caldav server&lt;/li&gt;
      &lt;li&gt;Other personal projects&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Sync Server setup. Mainly for the Kindle and the phone.&lt;/li&gt;
  &lt;li&gt;Calibre-server, koreader sync server for the Kindle
    &lt;ul&gt;
      &lt;li&gt;Now looking at libreread as well&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Tiny k8s cluster for running other webapps&lt;/li&gt;
  &lt;li&gt;Run a graylog server for sending other system log data (using papertrail now, has a 200MB limit)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No plans to move mail hosting. That will stay at migadu.com for now.&lt;/p&gt;

&lt;p&gt;I had a lot of spare HDDs that I was going to re-use for this build:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;WD MyBook 3TB (external, shelled).&lt;/li&gt;
  &lt;li&gt;Seagate Expansion: 1TB&lt;/li&gt;
  &lt;li&gt;Seagate Expansion 3TB (external, shelled)&lt;/li&gt;
  &lt;li&gt;Samsung EVO 128GB SSD&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The 2x3TB disks are setup with RAID1 over &lt;code class="language-plaintext highlighter-rouge"&gt;btrsfs&lt;/code&gt;. Important data is snapshotted to the other 1TB disk using btrfs snapshots and subvolumes. In total giving me ~4TB of storage.&lt;/p&gt;

&lt;h2 id="software"&gt;Software&lt;/h2&gt;

&lt;p&gt;Currently running &lt;code class="language-plaintext highlighter-rouge"&gt;kodi-standalone-service&lt;/code&gt; on boot. Have to decide on a easy-to-use container orchestration platform. Choices as of now are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Rancher&lt;/li&gt;
  &lt;li&gt;Docker Swarm&lt;/li&gt;
  &lt;li&gt;Shipyard&lt;/li&gt;
  &lt;li&gt;Terraform&lt;/li&gt;
  &lt;li&gt;Portainer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most of these are tuned for multi-host setups, and bring in a lot of complexity as a result. Looking at Portainer, which seems well suited to a single-host setup.&lt;/p&gt;

&lt;p&gt;Other services I’m currently running:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;elibsrv&lt;/code&gt;. Running a patched build with support for ebook-convert&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ubooquity&lt;/code&gt; for online reading of comics&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img alt="" src="/img/home-server.jpg" /&gt;&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;</description><author>Nemo's Home</author><pubDate>Sun, 17 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/09/17/home-server-build/</guid></item><item><title>Project Updates</title><link>https://captnemo.in/blog/2017/09/16/project-updates/</link><description>&lt;p&gt;Over the last couple of years, I’ve been involved with lots of side projects, both online and offline. Some of them, I’ve written about on the blog, like my &lt;a href="/blog/2017/05/01/spectrumyzer-visualization/"&gt;music visualizer project&lt;/a&gt;. A few of them, got their own project page, like &lt;a href="/projects/shauryaa/"&gt;the website for my niece&lt;/a&gt; (but no blog post) while some didn’t even get a mention. I thought I’d write about the many-many side projects I’ve started (and abandoned). You might also wanna visit the &lt;a href="/projects/"&gt;/projects&lt;/a&gt; page for the larger projects.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;a href="/blog/2017/09/17/home-server-build/"&gt;Home Server Build&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;Sep 2017&lt;/strong&gt; Built a home server, mostly as a HTPC but also as a learning exercise for managing services over Docker.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/sushigo"&gt;Sushi Go&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;Summer 2017&lt;/strong&gt; This is a work-in-progress conversion of Sushi Go (original), the popular card game by Gamewright into Ruby.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/youtube-ripper"&gt;youtube-ripper&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;June 2017&lt;/strong&gt; Downloads music-compilations from YouTube and rips them into multiple tagged MP3 files.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/cosmere-books"&gt;cosmere-books&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;September 2017&lt;/strong&gt; Wrote a EPUB generator for multiple books in the Cosmere. Currently covers 4 different serializations at Tor.com. Also created a project page on all of my ebooks projects at &lt;a href="/ebooks/"&gt;/ebooks/&lt;/a&gt;&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/ideas"&gt;ideas&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;Ongoing&lt;/strong&gt; I maintain a CC0 licensed list of personal ideas. Feel free to use.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="/blog/2017/05/01/spectrumyzer-visualization/"&gt;spectrumyzer&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;May 2017&lt;/strong&gt; Created an animated wallpaper using spectrumyzer. Wrote a &lt;a href="/blog/2017/05/01/spectrumyzer-visualization/"&gt;blog post about it&lt;/a&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/google-sre-ebook"&gt;google-sre&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;Feb/Sep 2017&lt;/strong&gt; EPUB generator for the Google SRE ebook. Started in February in Python. Gave up and redid it properly in September.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/codechef"&gt;CodeChef Offline&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;March 2012&lt;/strong&gt; I attempted to make a offline repository for CodeChef problems. I spent some time in May 2017 upgrading the project with a cleaner scraper and a Jekyll base.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/hoshruba"&gt;Hoshruba&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;June 2015&lt;/strong&gt; I wrote a script that scraped Tor’s serialized publication of the first book in Hoshruba series to generate EPUB and MOBI files. I would recommend the book if you are interested in reading what many would term the “original fantasy book”&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/hackertray"&gt;HackerTray&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;December 2013 -&lt;/strong&gt; I wrote a Linux PyGTK application that sits in your taskbar using Indicator Applet to show you the latest stories from Hacker News. Looking for a maintainer.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/magicmuggle"&gt;MagicMuggle&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;May 2017&lt;/strong&gt; I wrote a script to convert Magic Muggle (A Harry Potter fanfic about a muggle who accidentally gets into Hogwarts) books from their original reddit posts to EPUB and MOBI files.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://github.com/captn3m0/kerala-it"&gt;Kerala IT Policy&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;March 2017&lt;/strong&gt; Attempted to transcribe the draft IT policies put up by the Government of Kerala. Lots of OCR followed by manual fixes. I stopped working on this when I realized that the government had actually put up a really nice website for this (with clear plaintext, not the bad PDF I was using as the source).&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://lightsaber.captnemo.in"&gt;lightsaber&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;August 2015&lt;/strong&gt; I created a DNS based HTTP-3xx redirect service. Useful if you own a domain and you want it to be redirected, but don’t have a webserver with you. Made as part of the Django Hackathon organized by HackerEarth in Ruby.&lt;/dd&gt;
  &lt;dt&gt;&lt;a href="https://hackercouch.com"&gt;HackerCouch&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;&lt;strong&gt;November 2015&lt;/strong&gt; My hack during hackbeach 2015. Created something best described as “couchsurfing for hackers”. Simple Jekyll/Ruby website hosted on GitHub Pages.&lt;/dd&gt;
&lt;/dl&gt;</description><author>Nemo's Home</author><pubDate>Sat, 16 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/09/16/project-updates/</guid></item><item><title>Quick and dirty React Reason HMR (Hot module reloading)</title><link>https://jeroenpelgrims.com/quick-and-dirty-react-reason-hmr-hot-module-reloading/</link><description>&lt;p&gt;It proved quite hard to find a way to do HMR in ReasonReact.&lt;br /&gt;
Here's a quick but dirty way of doing it:&lt;/p&gt;
&lt;p&gt;Initialize an app using &lt;a href="https://github.com/reasonml-community/reason-scripts"&gt;reason-scripts&lt;/a&gt;&lt;br /&gt;
After having installed the bucklescript platform you can run:&lt;br /&gt;
&lt;code&gt;yarn create react-app reasonreact-hmr -- --scripts-version reason-scripts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Replace your src/index.re file with this:&lt;/p&gt;
&lt;pre class="language-ocaml " style="background-color: #ffffff; color: #323232;"&gt;&lt;code class="language-ocaml"&gt;&lt;span&gt;[&lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;%%&lt;/span&gt;&lt;span&gt;bs.raw {&lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;|
&lt;/span&gt;&lt;span&gt;  require('.&lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;/&lt;/span&gt;&lt;span&gt;index.css')
&lt;/span&gt;&lt;span&gt;  var App &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span&gt; require(&lt;/span&gt;&lt;span style="color: #183691;"&gt;&amp;quot;./app.js&amp;quot;&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;  var ReactDOMRe &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span&gt; require(&lt;/span&gt;&lt;span style="color: #183691;"&gt;&amp;quot;reason-react/lib/js/src/reactDOMRe.js&amp;quot;&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;  var ReasonReact &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span&gt; require(&lt;/span&gt;&lt;span style="color: #183691;"&gt;&amp;quot;reason-react/lib/js/src/reasonReact.js&amp;quot;&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;  function render(Component) {
&lt;/span&gt;&lt;span&gt;    ReactDOMRe.renderToElementWithId(
&lt;/span&gt;&lt;span&gt;      ReasonReact.element(&lt;/span&gt;&lt;span style="color: #0086b3;"&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span style="color: #0086b3;"&gt;0&lt;/span&gt;&lt;span&gt;, Component.make(&lt;/span&gt;&lt;span style="color: #183691;"&gt;&amp;quot;Welcome to React and Reason&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span style="color: #0086b3;"&gt;[]&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span style="color: #183691;"&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;  render(App);
&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;if &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;module&lt;/span&gt;&lt;span&gt;.hot) {
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;module&lt;/span&gt;&lt;span&gt;.hot.accept(&lt;/span&gt;&lt;span style="color: #0086b3;"&gt;() &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;=&amp;gt; &lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;span&gt;      const NextApp &lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span&gt; require('.&lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;/&lt;/span&gt;&lt;span&gt;app').default;
&lt;/span&gt;&lt;span&gt;      render(NextApp);
&lt;/span&gt;&lt;span&gt;    });
&lt;/span&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;span style="font-weight: bold; color: #a71d5d;"&gt;|&lt;/span&gt;&lt;span&gt;}];
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what we've done here is replace the rendering code which was in Reason before with raw Javascript code which supports hot reloading right from Reason. (The same JS code you can use in any javascript react project to make it support HMR)&lt;/p&gt;
&lt;p&gt;Why Javascript and not Reason? Because I don't know enough of Reason/Ocaml yet to implement this using that.&lt;/p&gt;
&lt;h2 id="what-s-actually-going-on"&gt;What's actually going on?&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/quick-and-dirty-react-reason-hmr-hot-module-reloading/#what-s-actually-going-on" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I took the js code that is generated from the original index.re and modified it to support HMR.&lt;br /&gt;
The require statements you see are the ones generated by reason when you run the project for the first time.&lt;/p&gt;</description><author>Jeroen Pelgrims</author><pubDate>Fri, 15 Sep 2017 21:28:00 GMT</pubDate><guid isPermaLink="true">https://jeroenpelgrims.com/quick-and-dirty-react-reason-hmr-hot-module-reloading/</guid></item><item><title>Fixing a soldering iron with 3D printing</title><link>https://mattkeeter.com/blog/2017-09-15-iron</link><description/><author>Matt Keeter</author><pubDate>Fri, 15 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2017-09-15-iron</guid></item><item><title>The How and Why of BlockValue</title><link>https://josh.works/block-value</link><description>&lt;p&gt;I wrote the following post, and built the application in question, in 2017, in my “end of Turing” project, before I’d ever been hired as a software developer.&lt;/p&gt;

&lt;p&gt;I really enjoyed the app that I built, and I keep wanting to get around to cleaning it up and making it work again. Maybe sometime soon!&lt;/p&gt;

&lt;hr /&gt;

&lt;ul&gt;
  &lt;li&gt;👉 &lt;a href="https://github.com/josh-works/block_value"&gt;View the github repo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;👉 &lt;a href="https://block-value.herokuapp.com/"&gt;view the app on Heroku (currently broken)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve been sketching out an app that “crowdsources” GIS data.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Geographic_information_system"&gt;Wikipedia&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A geographic information system (GIS) is a system designed to capture, store, manipulate, analyze, manage, and present spatial or geographic data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My inspiration is &lt;a href="https://hoodmaps.com"&gt;Hoodmaps&lt;/a&gt;, which &lt;a href="https://twitter.com/levelsio"&gt;@levelsio&lt;/a&gt; kindly wrote an &lt;a href="https://levels.io/hoodmaps/"&gt;in-depth post about&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Armed with a solid example for something that I thought I could work with, I got to work.&lt;/p&gt;

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

&lt;p&gt;In general, property delivers value to people by doing &lt;em&gt;something&lt;/em&gt;. It can do all sorts of things, but my first pass was to try to figure out the relationship between buildings and parking lots. Eventually I realized I needed to be able to “tag”:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;parking lots&lt;/li&gt;
  &lt;li&gt;buildings&lt;/li&gt;
  &lt;li&gt;green space (useful)&lt;/li&gt;
  &lt;li&gt;legally required but otherwise useless green space (building setbacks)&lt;/li&gt;
  &lt;li&gt;streets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and maybe more some day.&lt;/p&gt;

&lt;p&gt;I’ve got a working hypothesis that we’ve built our cities based off of some insane rules, one of which being “lets put surface parking lots &lt;em&gt;everywhere&lt;/em&gt;.”&lt;/p&gt;

&lt;p&gt;I contend that a surface parking lot close to an economically productive stretch of property (like a walkable downtown) is a very poor use of resources.&lt;/p&gt;

&lt;p&gt;Lets look at a quick example from my home town, Golden, CO:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Downtown golden" src="/images/17-09-14-not-annotated.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Hm. Doesn’t reveal too much, does it?&lt;/p&gt;

&lt;p&gt;Maybe it would be nice if we could color-code the map by land use?&lt;/p&gt;

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

&lt;p&gt;Lets take another look, through the lens of crowd-sourced GIS data:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Red is parking, blue is building" src="/images/17-09-14-BlockValue.jpg" /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Red is parking lots, blue is buildings. This is downtown Golden, or almost everything that everyone loves about downtown is blue, and the red stuff is (again, just my opinion) counter-productive.&lt;/p&gt;

&lt;p&gt;The concept of this app is dead-simple. Almost paint-by-numbers so.&lt;/p&gt;

&lt;p&gt;It’s still a bit clunky to use, but here’s the gist:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Painting on the map" src="/images/17-09-14Screen Recording 2017-09-14 at 04.03 PM.gif" /&gt;&lt;/p&gt;

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

&lt;p&gt;It’s a pretty simple tech stack, but the devil is in the details.&lt;/p&gt;

&lt;p&gt;On the front-end, I’ve got a transparent HTML5 canvas overlaid on a Google Maps satellite layer.&lt;/p&gt;

&lt;p&gt;To draw on the map, the user is just painting on the HTML5 canvas.&lt;/p&gt;

&lt;p&gt;That was the easy point. Harder is the fact that I have to store this user data, which is coming from the HTML5 canvas as just X and Y coordinates relative to the edge of the screen.&lt;/p&gt;

&lt;p&gt;Fortunately, StackOverflow to the rescue. I got two functions to convert a Lat/Long coordinates to a point on a map, and back again.&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="c1"&gt;// convert position on map to coordinates&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;latLng2Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;latLng&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;topRight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProjection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fromLatLngToPoint&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="nf"&gt;getBounds&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getNorthEast&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bottomLeft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProjection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fromLatLngToPoint&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="nf"&gt;getBounds&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getSouthWest&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&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="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getZoom&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;worldPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProjection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fromLatLngToPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;latLng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;worldPoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;bottomLeft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worldPoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;topRight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;scale&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="nf"&gt;point2LatLng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;point&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;topRight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProjection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fromLatLngToPoint&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="nf"&gt;getBounds&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getNorthEast&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bottomLeft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProjection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fromLatLngToPoint&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="nf"&gt;getBounds&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getSouthWest&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&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="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getZoom&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;worldPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;bottomLeft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;topRight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&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;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProjection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fromPointToLatLng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worldPoint&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;A bit of tweaking got those working for my &lt;code class="language-plaintext highlighter-rouge"&gt;drawUserPaths&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;drawSh*t&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;Every time the user draws a path, an AJAX call fires, sending&lt;code class="language-plaintext highlighter-rouge"&gt;UserPaths&lt;/code&gt; (these are the user data containing the color, size, and location of what the user is drawing) to my server.&lt;/p&gt;

&lt;p&gt;It’s hard to draw closed paths on top of HTML5 canvas. These screenshots make it look like someone is drawing a continuous line, but there’s not. Here’s what a quick mouse movement looks like:&lt;/p&gt;

&lt;p&gt;&lt;img alt="drawing paths" src="/images/17-09-14Screen Recording 2017-09-14 at 04.26 PM.gif" /&gt;&lt;/p&gt;

&lt;p&gt;Here’s my “draw stuff” function:&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;function&lt;/span&gt; &lt;span class="nf"&gt;drawPath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;mouseDown&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="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentColor&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strokeStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentColor&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;brushSize&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;offsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetX&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;offsetY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetY&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isDrawing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offsetX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offsetY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearRect&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;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beginPath&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;moveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;points&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;points&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="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;points&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="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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;points&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;points&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="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;offsetX&lt;/span&gt;
  &lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;offsetY&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;positionOnMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;point2LatLng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;point&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.color-picker div.active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;category&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;positionOnMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;positionOnMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sizeRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;brushSize&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zoom&lt;/span&gt;
  &lt;span class="nx"&gt;userPaths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;size_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sizeRatio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;line_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lineCount&lt;/span&gt;
      &lt;span class="p"&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;The “business” is the &lt;code class="language-plaintext highlighter-rouge"&gt;ctx.beginPath()&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;ctx.stroke()&lt;/code&gt; portions. HTML5 seems to think well in points, not in “paths”. So, if I want to be able to draw a continuous path, there’s some very tricky business around connecting many points. I left that for a later day, so for now - everyone is drawing overlapping circles. Bleh.&lt;/p&gt;

&lt;p&gt;When the user moves the map, another AJAX calls fires, retrieving the server data.&lt;/p&gt;

&lt;p&gt;(There are some hefty problems in this process. I’ll get to the “what’s next” below)&lt;/p&gt;

&lt;p&gt;The data’s stored in a standard PostGres Database. Watching the logs when others were using it was fun:&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;TFW people are using your app b/c it looks like Postgres is blowing up. 😱 &lt;a href="https://t.co/XBPV73uuim"&gt;pic.twitter.com/XBPV73uuim&lt;/a&gt;&lt;/p&gt;&amp;mdash; Josh Thompson (@josh_works) &lt;a href="https://twitter.com/josh_works/status/893216572747247619"&gt;August 3, 2017&lt;/a&gt;&lt;/blockquote&gt;


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

&lt;p&gt;I’d not done much with JavaScript or AJAX calls before this project.&lt;/p&gt;

&lt;p&gt;Most of my time was spent wrestling with the HTML5 canvas overlay, getting it to play correctly with the Google Maps layer underneath.&lt;/p&gt;

&lt;p&gt;When a user toggles the “draw” function, I’m just changing the z-index of the canvas to go “below” the google maps layer. I can’t imagine this is best practice, but it is what it is.&lt;/p&gt;

&lt;p&gt;It was hard converting x/y data from the canvas to lat/long coordinates to store in the database, and to bring it back out when I need to load up the data.&lt;/p&gt;

&lt;p&gt;There were lots of challenges, but it’s been very educational!&lt;/p&gt;

&lt;h1 id="whats-next"&gt;What’s next&lt;/h1&gt;

&lt;p&gt;I desperately need to set up caching all over the place, and localize the data that I return in my database to contain only about what is visible on the screen.&lt;/p&gt;

&lt;p&gt;There’s a few UI tweaks I need to get in place, too. It’s hard to move between drawing and moving the map.&lt;/p&gt;

&lt;p&gt;Finally, I’d like to be able to “do math” against the colored portions of the screen. To say “50% of the visible region is parking lot” or something like that. Then I can start comparing it against popular urban areas in other cities, and other countries.&lt;/p&gt;

&lt;p&gt;I think this stage will be when the real value is visible.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Thu, 14 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/block-value</guid></item><item><title>Encapsulating State with Functional Children</title><link>https://dylanpaulus.com/posts/2017/encapsulating-state-with-functional-children/</link><description>&lt;p&gt;import Alert from "../../../../components/Alert.astro";&lt;/p&gt;

  Update (3/20/2023): Since writing this post the community has called this
  technique "Render Props".

&lt;p&gt;There is a technique for creating reusable components that got missed in my last post, &lt;a href="/posts/tips-on-creating-reusable-components/"&gt;Tips on Creating Reusable Components&lt;/a&gt;, that I'd like to talk about. That is, components that have functions as children. This is a great tool that mirrors higher order components, in that it lets us abstract away reusable states. We'll start out with an example.&lt;/p&gt;
&lt;h3&gt;Breaking down functional children&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import React from "react";

class Booer extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      test: "...",
    };
  }

  componentDidMount() {
    setTimeout(() =&amp;gt; {
      this.setState({
        test: "BOO!",
      });
    }, 1000);
  }

  render() {
    // Using children as a function!
    return this.props.children(this.state.test);
  }
}

function Timer(props) {
  return &amp;lt;Booer&amp;gt;{(test) =&amp;gt; &amp;lt;div&amp;gt;{test}&amp;lt;/div&amp;gt;}&amp;lt;/Booer&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Booer&lt;/em&gt; is a component that after 1000ms, updates its state to say "Boo!". Nothing special. The power in functional children comes in play in the render method. Instead of treating &lt;code&gt;this.props.children&lt;/code&gt; as a variable, we pass a long some state which gets injected into the children prop. Moving to the &lt;em&gt;Timer&lt;/em&gt; component, we see something a little odd. The &lt;em&gt;Booer&lt;/em&gt; component takes a function with an argument, &lt;code&gt;test&lt;/code&gt;, being that state we passed into &lt;code&gt;this.props.children&lt;/code&gt;. We are then free to return any valid React children in the function. This let's us reuse state for different visual components! In the case of the &lt;em&gt;Timer&lt;/em&gt; component, it will show a &lt;em&gt;div&lt;/em&gt; with "...". Once 1000ms is complete, the contents will be replaced with "Boo!".&lt;/p&gt;
&lt;h3&gt;Toggle Component&lt;/h3&gt;
&lt;p&gt;The first example is a nice way to show functional children, but let's make something a little more practical. Like the title suggestions, how about a component that keeps track of a toggle! This may look something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import React from "react";

class Toggle extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isToggled: false,
    };

    this.toggle = this.toggle.bind(this);
  }

  toggle() {
    this.setState((prevState) =&amp;gt; ({
      isToggled: !prevState.isToggled,
    }));
  }

  render() {
    const { isToggled } = this.state;

    return this.props.children(isToggled, this.toggle);
  }
}

function ToggleButton() {
  return (
    &amp;lt;Toggle&amp;gt;
      {(isToggled, toggle) =&amp;gt; (
        &amp;lt;button onClick={toggle}&amp;gt;{isToggled ? "ON" : "off"}&amp;lt;/button&amp;gt;
      )}
    &amp;lt;/Toggle&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looking at it, the &lt;em&gt;Booer&lt;/em&gt; component is pretty similar to out new &lt;em&gt;Toggle&lt;/em&gt; component. They both handle some state, then pass it to &lt;code&gt;this.props.children()&lt;/code&gt; as function argument. In the case of &lt;em&gt;Toggle&lt;/em&gt;, we are now passing two arguments. First, our &lt;em&gt;isToggled&lt;/em&gt; state. Second, a class method that will toggle the &lt;em&gt;isToggled&lt;/em&gt; state. &lt;code&gt;this.toggle&lt;/code&gt; will be useful for a consumer to control events.&lt;br /&gt;
Looking at the &lt;em&gt;ToggleButton&lt;/em&gt; component, it's pretty simple to wire out a button that has toggle ability, while making its state reusable! What if we want a toggle checkbox? We can just swap out the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; JSX tags for &lt;code&gt;&amp;lt;input type="checkbox"&amp;gt;&lt;/code&gt;!&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Functional children is yet another technique for creating reusable components. It helps us move presentational components away from stateful logic (ie. Dumb/Smart components or Containers/Components).&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Thu, 14 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2017/encapsulating-state-with-functional-children/</guid></item><item><title>Enterprise Conversation Episode 14: OpenTable with Thomas Hunter</title><link>https://thomashunter.name/posts/2017-09-14-node-foundation-enterprise-conversation</link><author>Thomas Hunter II</author><pubDate>Thu, 14 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-09-14-node-foundation-enterprise-conversation</guid></item><item><title>Dynamic Adaptive Streaming over HTTP (MPEG-DASH) for everyone</title><link>https://rybakov.com/blog/mpeg-dash/</link><description>&lt;p&gt;I had a simple dream. A dream of embedding videos in a web page without using third party services such as youtube or vimeo. For a while it seemed that I found the solution: using ffmpeg to convert the source videos to highly optimized h264 mp4 files. I &lt;a href="https://rybakov.com/blog/ffmpeg/"&gt;wrote&lt;/a&gt; about my process before. The drawback is, that you only get one quality setting. Use a high bitrate and the video will load slowly or stutter on slow connections. Use a low bitrate and it will load smoothly but never looked quite as beautiful as it should. You can never win.&lt;/p&gt;
&lt;p&gt;Luckily, there is a solution: Dynamic Adaptive Streaming over HTTP (MPEG-DASH). The concept is quite simple: you generate a few versions of your video with different bitrates, a manifest file that links to those versions, and let the browser decide - according to the current bandwidth - which version to load.&lt;/p&gt;
&lt;p&gt;But see for yourself:&lt;br /&gt;
&lt;a href="../project/political_choreography_old/"&gt;A single page with three autoplaying videos&lt;/a&gt;, using the standard html5 video.&lt;br /&gt;
&lt;a href="../project/political_choreography/"&gt;And the same page, but with MPEG DASH&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Every modern browser &lt;a href="http://caniuse.com/#feat=mediasource"&gt;supports&lt;/a&gt; MPEG-DASH through the use of media source extensions. Well, except iOS Safari and Opera Mini. For those, an additional HLS stream - or a fallback to a normal mp4 file - can be used.
Media source extension support in the browsers means that you still have to use an additional js player such as &lt;a href="https://github.com/Dash-Industry-Forum/dash.js"&gt;dash.js&lt;/a&gt; or &lt;a href="https://github.com/google/shaka-player"&gt;shaka player&lt;/a&gt; to play your MPEG DASH streams.&lt;/p&gt;
&lt;p&gt;So, lets convert our videos with some command line magic. You will need &lt;em&gt;ffmpeg&lt;/em&gt; for the conversion and &lt;em&gt;MP4box&lt;/em&gt;(part of &lt;em&gt;gpac&lt;/em&gt;) to create the manifest file. On a mac, the easiest way to get those is through &lt;a href="http://brew.sh/"&gt;Homebrew&lt;/a&gt;.
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;brew install ffmpeg gpac&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Convert the source file called input.mov into an audio file and two video files:
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    ffmpeg -y -i &lt;span style="color: #e6db74;"&gt;"input.mov"&lt;/span&gt; -c:a aac -b:a 192k -vn &lt;span style="color: #e6db74;"&gt;"output_audio.m4a"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    ffmpeg -y -i &lt;span style="color: #e6db74;"&gt;"input.mov"&lt;/span&gt; -preset slow -tune film -vsync passthrough -an -c:v libx264 -x264opts &lt;span style="color: #e6db74;"&gt;'keyint=25:min-keyint=25:no-scenecut'&lt;/span&gt; -crf &lt;span style="color: #ae81ff;"&gt;22&lt;/span&gt;  -maxrate 5000k -bufsize 10000k -pix_fmt yuv420p -f mp4 &lt;span style="color: #e6db74;"&gt;"output_5000.mp4"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    ffmpeg -y -i &lt;span style="color: #e6db74;"&gt;"input.mov"&lt;/span&gt; -preset slow -tune film -vsync passthrough -an -c:v libx264 -x264opts &lt;span style="color: #e6db74;"&gt;'keyint=25:min-keyint=25:no-scenecut'&lt;/span&gt; -crf &lt;span style="color: #ae81ff;"&gt;23&lt;/span&gt;  -maxrate 2000k -bufsize 4000k -pix_fmt yuv420p -f mp4 &lt;span style="color: #e6db74;"&gt;"output_2000.mp4"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;What do all those options mean?&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Wed, 13 Sep 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/mpeg-dash/</guid></item><item><title>Anonymous Functions in R and Python</title><link>https://lukesingham.com/anonymous-functions-in-r-python/</link><description>&lt;blockquote&gt;
&lt;p&gt;What's in a name? That which we call a rose by any other name would smell as sweet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="normal-functions"&gt;Normal functions &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#normal-functions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before moving to anonymous functions, let's start with what normal functions look like.&lt;/p&gt;
&lt;h4 id="in-r"&gt;In R &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#in-r"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Define a function&lt;/span&gt;&lt;br /&gt;functionName &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="token keyword"&gt;function&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;variables&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Function definition... do some stuff&lt;/span&gt;&lt;br /&gt;    print&lt;span class="token punctuation"&gt;(&lt;/span&gt;paste&lt;span class="token punctuation"&gt;(&lt;/span&gt;variables&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"doing stuff"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Call the function&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; functionName&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"boring strings"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token string"&gt;"boring strings doing stuff"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="in-python"&gt;In Python &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#in-python"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Define function&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;def&lt;/span&gt; &lt;span class="token function"&gt;functionName&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;variables&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="token comment"&gt;# Do some stuff&lt;/span&gt;&lt;br /&gt;    &lt;span class="token keyword"&gt;print&lt;/span&gt; variables&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"doing stuff"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Call the function&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; functionName&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"boring strings"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;boring strings doing stuff&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="anonymous-functions"&gt;Anonymous Functions &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#anonymous-functions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Have no identity, no name, but still do stuff! They will not live in the global environment. Like a person without a name, you would not be able to look the person up in the address book.&lt;/p&gt;
&lt;p&gt;The anonymous function can be called like a normal function &lt;code&gt;functionName()&lt;/code&gt;, except the functionName is switched for logic contained within parentheses &lt;code&gt;(fn logic goes here)()&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="in-r-2"&gt;In R &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#in-r-2"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Doing the same stuff anonymously&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;variables&lt;span class="token punctuation"&gt;)&lt;/span&gt; print&lt;span class="token punctuation"&gt;(&lt;/span&gt;paste&lt;span class="token punctuation"&gt;(&lt;/span&gt;variables&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"doing stuff"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"code"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token string"&gt;"code doing stuff"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="in-python-2"&gt;In Python &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#in-python-2"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Python introduces the &lt;code&gt;lambda&lt;/code&gt; keyword for anonymous functions, in contrast to R which sticks with the &lt;code&gt;function&lt;/code&gt; keyword.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Doing the same stuff anonymously&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;lambda&lt;/span&gt; variable&lt;span class="token punctuation"&gt;:&lt;/span&gt; variable &lt;span class="token operator"&gt;+&lt;/span&gt; &lt;span class="token string"&gt;" doing stuff"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"code"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token string"&gt;'code doing stuff'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="r-convention"&gt;R Convention &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#r-convention"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most common convention is to use anonymous functions when using the &lt;code&gt;*apply&lt;/code&gt; family of functions. For example, you might want to do an operation across a set of columns in a dataset.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Create a dataset&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; data.frame&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;  col1 &lt;span class="token operator"&gt;=&lt;/span&gt; c&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"element1"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"element2"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  col2 &lt;span class="token operator"&gt;=&lt;/span&gt; c&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"element1"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"element2"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  stringsAsFactors &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;FALSE&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# lapply an anonymous function to the columns of the dataset&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; lapply&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token keyword"&gt;function&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;x&lt;span class="token punctuation"&gt;)&lt;/span&gt; paste&lt;span class="token punctuation"&gt;(&lt;/span&gt;x&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"doing stuff"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;$&lt;/span&gt;col1&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token string"&gt;"element1 doing stuff"&lt;/span&gt; &lt;span class="token string"&gt;"element2 doing stuff"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token operator"&gt;$&lt;/span&gt;col2&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token string"&gt;"element1 doing stuff"&lt;/span&gt; &lt;span class="token string"&gt;"element2 doing stuff"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="python-convention"&gt;Python Convention &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#python-convention"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Doing the exact operation as above in python:&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; pandas &lt;span class="token keyword"&gt;as&lt;/span&gt; pd&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Create DataFrame&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;"element1"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"element1"&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;"element2"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"element2"&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;    columns&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'col1'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'col2'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;apply&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;lambda&lt;/span&gt; x&lt;span class="token punctuation"&gt;:&lt;/span&gt; x &lt;span class="token operator"&gt;+&lt;/span&gt; &lt;span class="token string"&gt;" doing stuff"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;                   col1                  col2&lt;br /&gt;&lt;span class="token number"&gt;0&lt;/span&gt;  element1 doing stuff  element1 doing stuff&lt;br /&gt;&lt;span class="token number"&gt;1&lt;/span&gt;  element2 doing stuff  element2 doing stuff&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will generally see lambdas used with higher order functions like &lt;code&gt;map()&lt;/code&gt;, &lt;code&gt;reduce()&lt;/code&gt; and &lt;code&gt;filter()&lt;/code&gt;. E.g.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Map an anonymous function against all elements of df['col1']&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token builtin"&gt;map&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;lambda&lt;/span&gt; x&lt;span class="token punctuation"&gt;:&lt;/span&gt; x &lt;span class="token operator"&gt;+&lt;/span&gt; &lt;span class="token string"&gt;" doing stuff"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'col1'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'element1 doing stuff'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'element2 doing stuff'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may also see a lambda used to define a function. e.g.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;functionName &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;lambda&lt;/span&gt; x&lt;span class="token punctuation"&gt;:&lt;/span&gt; x &lt;span class="token operator"&gt;+&lt;/span&gt; &lt;span class="token string"&gt;" doing stuff"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is poor practice when a standard function definition would have been sufficient. The Python community has a bit of a split over the use of anonymous functions (lambdas) vs. &lt;a href="https://www.digitalocean.com/community/tutorials/understanding-list-comprehensions-in-python-3"&gt;list comprehensions&lt;/a&gt;. The &lt;a href="https://en.wikipedia.org/wiki/Benevolent_dictator_for_life"&gt;benevolent dictator&lt;/a&gt; of the Python community &lt;a href="https://en.wikipedia.org/wiki/Guido_van_Rossum"&gt;Guido van Rossum&lt;/a&gt; has &lt;a href="https://www.artima.com/weblogs/viewpost.jsp?thread=98196"&gt;argued for lambda's complete removal from python 3&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="in-conclusion"&gt;In Conclusion &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#in-conclusion"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Anonymous functions can make your code base harder to read. It can also make debugging harder. However, they can save you time from having to define yet another function in your code base. When should you use anonymous functions? According to &lt;a href="http://hadley.nz/"&gt;Hadley&lt;/a&gt; &lt;em&gt;&amp;quot;when it’s not worth the effort to give it a name&amp;quot;&lt;/em&gt;. A good example is when you won't use the function anywhere else in your code. Or when you want to &lt;code&gt;apply()&lt;/code&gt; a couple of pre-defined functions in one call e.g. &lt;code&gt;lapply(df, function(x) secondFunction(firstFunction(x)))&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources &lt;a class="direct-link" href="https://lukesingham.com/anonymous-functions-in-r-python/#resources"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.curiousefficiency.org/posts/bloggercom1999blog-9320223post-110439602874040740.html"&gt;Anonymous functions in Python&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://adv-r.had.co.nz/Functional-programming.html#anonymous-functions"&gt;Hadley on Anonymous Functions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://dbader.org/blog/python-lambda-functions"&gt;Lambda Functions in Python: What Are They Good For?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Wed, 13 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/anonymous-functions-in-r-python/</guid></item><item><title>How to handle validations involving several fields?</title><link>https://goshacmd.com/validations-several-fields/</link><author>Gosha Spark</author><pubDate>Wed, 13 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/validations-several-fields/</guid></item><item><title>Snap configuration: the configure hook</title><link>https://kyrofa.com/posts/snap-configuration-the-configure-hook/</link><description>You&amp;rsquo;ve heard it a million times: snaps bundle their dependencies. People seem to understand and accept the technical aspects of this, but today I want to talk about a more philosophical aspect. If you&amp;rsquo;re used to more traditional packaging, then you&amp;rsquo;re used to each project being standalone, e.g. Apache is its own package, with its own configuration; PHP is its own package, with its own configuration; and so on. As you begin creating a snap, perhaps one that bundles Apache, it&amp;rsquo;s easy to automatically gravitate toward wanting to make those config files available to your users as well.</description><author>kyrofa's blog</author><pubDate>Tue, 12 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/snap-configuration-the-configure-hook/</guid></item><item><title>Using tf&amp;amp;ndash;idf to analyse U.S. Presidential Inauguration Speeches</title><link>https://bastian.rieck.me/blog/2017/inauguration_speeches_tf_idf/</link><description>&lt;p&gt;Previously, I wrote about &lt;a href="https://bastian.rieck.me/blog/2017/inauguration_speeches_brief/"&gt;a brief analysis of U.S. Presidential
Inauguration Speeches&lt;/a&gt;.
I have since extended the analysis slightly using &lt;a href="https://en.wikipedia.org/wiki/Tf%E2%80%93idf"&gt;&amp;ldquo;tf–idf&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For those of you who are unaware of this technique, it refers to
a statistical method for assessing the importance of certain words in
a corpus of documents. Without going into too much detail, the method
determines which words are &lt;em&gt;most relevant&lt;/em&gt; for a given document of the
corpus, yielding a high-dimensional vector whose entries refer to the
common vocabulary of the corpus.&lt;/p&gt;
&lt;p&gt;I picked the five most relevant words for every speech to essentially
obtain an extremely pithy summary of words that are relevant for the
given speech only. Since there are 59 speeches in total, I first decided
to do a small visualization of the last eight presidents only, starting
from George H.W. Bush in 1989. Here are the results; the x-axis
represents the time, while the y-axis shows the five most important
words, scaled by their relative frequency in the speech:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_last_eight_tf_idf.svg"&gt;&lt;img alt="A visualization of the relative importance of words in the last eight inauguration speeches of U.S. presidents" src="https://bastian.rieck.me/images/inauguration_speeches_last_eight_tf_idf.svg" width="800" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;So, what can we see in this visualization? Here are some of my thoughts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;don&lt;/em&gt; in the speech of George H.W. Bush is a shortened form of
&lt;em&gt;don’t&lt;/em&gt;. The algorithm picked up on his usage in the speech,
which contains beautiful imagery such as this:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;For the first time in this century, for the first time in perhaps all
history, man does not have to invent a system by which to live. We
don&amp;rsquo;t have to talk late into the night about which form of government
is better. We don&amp;rsquo;t have to wrest justice from the kings. We only have
to summon it from within ourselves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It is also interesting to note that the &lt;em&gt;new breeze&lt;/em&gt; George H.W. Bush
is talking about is detected as a unique feature of his speech.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The speeches of Bill Clinton allude to the change that started after
the end of the Cold War, as well as the promises that arise in the new
century to come.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second speech of George W. Bush tries to rally Americans in the
War on Terror. Liberty and freedom are part of the underlying theme,
these of course being American ideals that are worth fighting for.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;With Barack Obama, a sort of &lt;em&gt;rebirth&lt;/em&gt; takes place. He speaks to the
new generation, expressing his hope that American becomes a new
nation, and aligns everyone that &lt;em&gt;today&lt;/em&gt;—not tomorrow—is
the day to address these challenges. In his second speech, the great
journey towards equality is presented to the Americans, making it
clear that &lt;em&gt;change&lt;/em&gt; does not stop.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;With Donald Trump, the narrative changes. The important words are now
the dreams of people, such as the hope that they will find new jobs.
It is interesting to note that only the speeches at a time of
crisis or abrupt change (Cold War or the War on Terror) exhibit
the same occurrence of the words &lt;em&gt;America&lt;/em&gt; and &lt;em&gt;American&lt;/em&gt;. Maybe
Donald Trump is trying to invoke a connection to these events in his
speech?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are only my random thoughts—I think it is fascinating that
tf–idf is capable of picking up on these themes in such a reliable
manner. Maybe a more competent person wants to comment on these
findings? I look forward to any feedback you might have. In the
meantime, please enjoy a variant of the visualization above that
contains &lt;a href="https://bastian.rieck.me/blog/images/inauguration_speeches_all_tf_idf.svg"&gt;&lt;em&gt;all&lt;/em&gt; speeches of &lt;em&gt;all&lt;/em&gt; presidents so
far&lt;/a&gt;. You will have to
scroll around a lot for this. By the way, I have added the code to &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches"&gt;the
GitHub
repository&lt;/a&gt;.
You may be particularly interested in
&lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches/blob/master/tf_idf_analysis.py"&gt;&lt;code&gt;tf_idf_analysis.py&lt;/code&gt;&lt;/a&gt;,
which demonstrates the tf–idf analysis of all speeches. Moreover,
I added a &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches/blob/master/create_topics.gp"&gt;gnuplot
script&lt;/a&gt;
that demonstrates how to create the visualizations attached to this blog
post.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Mon, 11 Sep 2017 22:41:21 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/inauguration_speeches_tf_idf/</guid></item><item><title>More experiments with `libclang`</title><link>https://bastian.rieck.me/blog/2017/libclang_experiments/</link><description>&lt;p&gt;In late 2015, I started fiddling with &lt;code&gt;libclang&lt;/code&gt; in order to analyse
abstract syntax trees. After multiple queries reached me via e-mail,
I decided to create a public repository of my experiments.&lt;/p&gt;
&lt;p&gt;The repository is called
&lt;a href="https://github.com/Pseudomanifold/libclang-experiments"&gt;&lt;code&gt;libclang-experiments&lt;/code&gt;&lt;/a&gt; and resides on my
GitHub account.  It contains the code for the first blog post about &lt;code&gt;libclang&lt;/code&gt;, which presented some
basic routines for &lt;a href="https://bastian.rieck.me/blog/2015/baby_steps_libclang_ast/"&gt;walking an abstract syntax tree&lt;/a&gt;, as
well as code for the second blog post, which dealt with &lt;a href="https://bastian.rieck.me/blog/2016/baby_steps_libclang_function_extents/"&gt;counting the extents of
a function&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that since &lt;code&gt;libclang&lt;/code&gt; is somewhat fiddly to use, the repository also provides a &lt;code&gt;CMake&lt;/code&gt; module
for actually &lt;em&gt;finding&lt;/em&gt; the library on your computer. Please refer to the
&lt;a href="https://github.com/Pseudomanifold/libclang-experiments/blob/master/CMakeLists.txt"&gt;&lt;code&gt;CMakeLists.txt&lt;/code&gt;&lt;/a&gt;
of the repository for usage information—and do not hesitate to contact me, either via e-mail
or by opening an &lt;a href="https://github.com/Pseudomanifold/libclang-experiments/issues"&gt;issue&lt;/a&gt; on GitHub if
you have any questions.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Mon, 11 Sep 2017 16:00:59 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/libclang_experiments/</guid></item><item><title>Use Mutually Understandable Names for Priorities in Project Management Tools</title><link>https://www.databasesandlife.com/priorities/</link><description>&lt;p&gt;So today I got access to a customer&amp;rsquo;s new JIRA task management system. Unsurprisingly, every task has a field &lt;em&gt;priority&lt;/em&gt;, from &lt;em&gt;highest&lt;/em&gt;, &lt;em&gt;high&lt;/em&gt;, &lt;em&gt;low&lt;/em&gt; etc. It&amp;rsquo;s understandable that tasks might be sorted by urgency, to communicate that the most urgent stuff should be done first.
But these aren&amp;rsquo;t good names.
I have had the following experience at various previous customers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fundamentally a task management system is about communication between the team, and to/from management. If I am working alone, I can just use a text file for tasks, I don&amp;rsquo;t need a JIRA. Everyone thinks they know what a &lt;em&gt;high&lt;/em&gt; priority task is, but like the fact that we wonder if everyone else sees colors the same way as us, I don&amp;rsquo;t think there&amp;rsquo;s any evidence different people agree on what &lt;em&gt;high&lt;/em&gt; means. If you open JIRA and some important things are in &lt;em&gt;normal&lt;/em&gt; and other irrelevant stuff is in &lt;em&gt;high&lt;/em&gt;, you start to ignore the priority.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Mon, 11 Sep 2017 09:37:27 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/priorities/</guid></item><item><title>Free will in a deterministic universe</title><link>https://nutcroft.mataroa.blog/blog/free-will-in-a-deterministic-universe/</link><description>&lt;blockquote&gt;
&lt;p&gt;Originally written in June 2014. Revised and published in September 2017. Thank you, @handsomegeorge, for the notes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The purpose of this essay is to inform the reader about the philosophical views on the topic of free will. The existence of free will, though it may seem as a far-fetched and non-everyday issue, it has some very important consequences on our lives. For instance, let’s examine happiness. It is said that in order to be happy you need to pick and do the things that you like, things that define you. Firstly, though, you have to find what these things are. In order to be sure about these you need to act based on your own free will.&lt;/p&gt;
&lt;p&gt;Free will has been discussed as an issue since ancient times. This can be considered as an indication of its significance. Many philosophers contributed with their views on free will. These opinions have been classified into four broad categories, which I will analyze later on.&lt;/p&gt;
&lt;p&gt;I deemed appropriate to start my argument with an important, yet not clearly defined concept. This is randomness. It may seem simple enough; a random event is one we cannot predict. In order to predict an event, you have to observe and measure its causes. This means that if an event’s causes are immeasurable then this event is truly random. To elaborate, when a die is thrown, we can neither control our hand’s force nor measure any other forces that are being exerted at the die. This inability of ours to take exact measurements of all these variables is where we support the argument of the die’s randomness. However, this does not mean that these variables are inherently unmeasurable.&lt;/p&gt;
&lt;p&gt;Free will initially may feel as a non-issue, but if we give it some thought we will realize it is not a simple concept at all. Every action we take has some specific causes. Since, as I showed above, there is nothing random then the causes of our actions are not random either. They were also caused by some other non-random events. Continuing this way, we can constantly go back until the first event we know (or at least assume) that existed: the Big Bang. This is the event that we can picture as the first link of a chain. A different Big Bang would result in different subsequent events and thus a different chain. This pattern of thinking describes the deterministic view on the universe. In this way, even our thoughts, as part of the universe can be described as deterministic, which means that it was inevitable for them to happen. We can resonate in the following way: every thought has a trigger-thought behind it i.e. a thought that caused it. This trigger-thought has its own triggers-thoughts. Continuing in the same way we did with the events, there is one original thought, which in this case is not very important because its bearer (a human) is influenced to a great degree by their external environment. The universe, though, does not have such external influences — at least, none that we know of.&lt;/p&gt;
&lt;p&gt;I mentioned that views on free will are classified into four major categories. These are hard determinism, compatibilism, hard incompatibilism, and libertarianism.&lt;/p&gt;
&lt;p&gt;If someone adheres to hard determinism then they accept the deterministic view of the universe, while they deny the existence of free will. This can be easily understood. Free will is defined as being able to make choices unconstrained by certain factors. Nonetheless, a deterministic universe implies that any choice you make will be influenced by factors which could not have happened otherwise, and actually be predicted. Therefore, free will is incompatible with a deterministic universe.&lt;/p&gt;
&lt;p&gt;Compatibilists, on the other hand, claim that free will is indeed compatible with a deterministic universe. Arguments for this view can be supported by a different definition of free will. Some definitions include that free will means the lack of physical restraints, or that free will is defined as dictated by events such as the die throw. This means that randomness is synonymous to unpredictability, and since randomness is possible, determinism is not and events that cannot be predicted can happen. Another view on this by Daniel Dennett is that if we exclude an omnipotent God then because of chaos and epistemic limits on the precision of our knowledge of the current state of the world, the future is ill-defined for all finite beings. The only well-defined things are “expectations”, which are the choices we have on a specific case and we choose one of them on each case or event.&lt;/p&gt;
&lt;p&gt;John Locke, regarded as a proponent of hard incompatibilism claimed that “free will” as a phrase is absurd. Contemporary philosopher Galen Strawson, agreeing with Locke, claims that free will is impossible because man cannot create himself or his mental states “ex nihilo”, i.e. “out of nothing” in Latin. Hard incompatibilists do not agree with the existence of determinism, but they do not necessarily imply that the lack of it is in any way correlated to free will.&lt;/p&gt;
&lt;p&gt;Another most interesting view, that falls under the umbrella of hard incompatibilism, is by Eliezer Yudkowsky, an AI researcher with controversial opinions. As far as free will is concerned, he claims it being a cognitive element representing the basic game-theoretical unit of moral responsibility. In a way, this means that if someone has free will then we can say he is responsible for his physical and mental state. According to Yudkowsky, free will does not exist in reality with the common definition we use; it is the representation of the algorithm our mind uses to make decisions. In this case, the dilemma I stated: whether free will is possible since determinism implies that everything can be predicted, does not stand as a question; free will is irrelevant to determinism.&lt;/p&gt;
&lt;p&gt;Libertarianism, the fourth of the major views is a position that argues that free will is indeed logically incompatible with a deterministic universe, but humans do have free will, therefore, determinism is false. Essentially, libertarians’ arguments merge the notion of free will’s existence of compatibilists with the lack of determinism. Robert Kane, one of the leading contemporary philosophers on free will, talks about the existence of alternative possibilities, which resembles Dennett’s idea of expectations.&lt;/p&gt;
&lt;p&gt;Although all arguments about free will are divided into four categories, there is a high degree of disagreement between philosophers, even about this classification. This is not unexpected at all, taking into consideration the fact that we cannot be sure about most of the arguments.&lt;/p&gt;
&lt;p&gt;Quantum mechanics, a branch of physics which deals with physical phenomena at nanoscopic scales, has some important extensions to randomness. Werner Heisenberg, one of the pioneers of quantum mechanics, introduced the uncertainty principle, which states that we cannot measure the exact position and velocity of a particle at the same time. We could theorize that this means there is true randomness in physics and the universe, but we cannot prove the fact that, despite us, humans, even the universe does not know the exact measurements of all variables of particles. This debate is part of many, regarding quantum mechanics, between Albert Einstein and Niels Bohr. Einstein believed that randomness is a reflection of humanity’s inability and ignorance while Bohr claimed it being a universe-level fundamental property.&lt;/p&gt;
&lt;p&gt;Another argument which exposes this probabilistic nature of quantum mechanical phenomena is the Double-slit experiment; which also demonstrates the role of an observer-consciousness, making it one of the most absurd and counter­intuitive manifestations of reality.&lt;/p&gt;
&lt;p&gt;Certainly, there are definitions for randomness in other science disciplines too. For example, computer scientists argue about pseudo-random and cryptographically secure pseudo-random number generators. In biology, the diversity of life is attributed to random genetic mutations. In statistics, statistically random can refer to a numeric sequence when it contains no recognizable patterns. The usage of the concept in these cases adds more complicacy to its definition, as the fundamental notion is not clear. Apart from the convoluted saturation of the word, it is also clear how fundamental randomness is across all of science.&lt;/p&gt;
&lt;p&gt;In conclusion, many views have been heard since the antiquity on the topic of free will. Unfortunately, none of them is convincing enough for the advocates of the other views. The rise of quantum physics in the last centuries, though, has had some unexpected consequences on this topic because of the theory’s relations to randomness. Hopefully cracking quantum mechanics will also mean the unraveling of randomness, determinism, and ideally free will and eventually consciousness.&lt;/p&gt;</description><author>nutcroft</author><pubDate>Mon, 11 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nutcroft.mataroa.blog/blog/free-will-in-a-deterministic-universe/</guid></item><item><title>Hugo readDir and generating dynamic JSON</title><link>https://www.wints.org/notes/2017.09.11/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I&amp;rsquo;m using Hugo to generate a JSON feed for images + meta data. Part of the JSON is showing all the images in a directory. So:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static
  |__color
        |__blue
            |__blue_close_1.jpg
            |__blue_far_1.jpg
        |__green
            |__green_close_1.jpg
            |__green_far_2.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To build a JSON template that lists the .jpg files in each directory, I need to write a generic &lt;code&gt;readDir&lt;/code&gt; statement, which wasn&amp;rsquo;t possible by usual means. E.G these DO NOT work:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{{ $colorDir := "/static/color/"{{ .Title }} }}
{{ $colorDir := "/static/color/{{ .Title }}" }}
{{ $colorDir := "/static/color/.Title" }}
{{ $colorDir := "/static/color/" .Title }}

{{ range := (readDir $colorDir ) }} {{ .Name }} {{ end }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;How to do this was &lt;a href="https://discourse.gohugo.io/t/partial-to-generate-an-image-gallery-by-reading-a-directory/2547/3"&gt;buried in the support forums&lt;/a&gt;. Any of these work:&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 11 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.09.11/</guid></item><item><title>Snap install-time setup: the install hook</title><link>https://kyrofa.com/posts/snap-install-time-setup-the-install-hook/</link><description>When it comes to developing snaps, there&amp;rsquo;s a particular confusion out there that I see over and over again: build-time versus run-time. For example: &amp;ldquo;I&amp;rsquo;m building a snap, but I can&amp;rsquo;t seem to convince Snapcraft to place my config file in $SNAP_DATA.&amp;rdquo; In this post, I want to show you how to get the results you want.
First of all, we need to clear something up. Snapcraft can&amp;rsquo;t actually do this for you.</description><author>kyrofa's blog</author><pubDate>Mon, 11 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/snap-install-time-setup-the-install-hook/</guid></item><item><title>Better database migrations in Postgres</title><link>/2017/09/10/better-postgres-migrations/</link><description>&lt;p&gt;As your database grows and scales there are some operations that you need to take more care of than you did when you were just starting. When working with your application in your dev environment you may not be fully aware of the cost of some operations until you run them against production. And at some point most of us have been guilty of it, running some migration that starts at 5 minutes, then 15 minutes in it&amp;rsquo;s still running, and suddenly production traffic is impacted.&lt;/p&gt;
&lt;p&gt;There are two operations that tend to happen quite frequently, each with some straightforward approaches to mitigate having any noticable amount of downtime. Let&amp;rsquo;s look at each of the operations, how they work and then how you can approach them in a safer way.&lt;/p&gt;
&lt;h3 id="adding-new-columns"&gt;
&lt;div&gt;
Adding new columns
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Adding a new column is actually quite cheap in Postgres. When you do this it updates its underlying tracking of the columns that exist–which is almost instant. The part that becomes expensive is when you have some constraint against the column. A constraint could be a primary or foreign key, or some uniqueness constraint. Here Postgres has to scan through all the records in the table to ensure that it&amp;rsquo;s not being violated. Adding some constraint such as &lt;code&gt;not null&lt;/code&gt; does happen some, but is not the most common cause.&lt;/p&gt;
&lt;p&gt;The most common reason for slowness of adding a new column is that most frameworks make it very simple for you to set a default value for the new column. It&amp;rsquo;s one thing to do this for all new records, but when you do this when an existing table it means the database has to read all the records and re-write them with the new default value attached. This isn&amp;rsquo;t so bad for a table with a few hundred records, but for a few hundred million run it then go get yourself coffee, or lunch, or a 5 course meal because you&amp;rsquo;ll be waiting for a while.&lt;/p&gt;
&lt;p&gt;In short, &lt;code&gt;not null&lt;/code&gt; and setting a default value (on creation) of your new column will cause you pain. The solution is to not do those things. But, what if you want to have a default value and don&amp;rsquo;t want to allow &lt;code&gt;nulls&lt;/code&gt;. There&amp;rsquo;s a few simple steps you can take, by essentially splitting your migration up from 1 step to 4 migrations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add your new column &lt;em&gt;that allows nulls&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Start writing your default value on all new records and updates&lt;/li&gt;
&lt;li&gt;Gradually backfill the default value&lt;/li&gt;
&lt;li&gt;Apply your constraint&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Yes, this is a little more work, but it doesn&amp;rsquo;t impact production in nearly the same magnitude.&lt;/p&gt;
&lt;h3 id="indexes"&gt;
&lt;div&gt;
Indexes
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Index creation like most DDL operations holds a lock while it&amp;rsquo;s occurring, this means any new data has to wait for the index to be created and then the new writes flow through. Again when firsting creating the table or on a small table this time is not very noticable. On a large database though, you can again wait minutes to possibly even hours. &lt;em&gt;It&amp;rsquo;s a bit ironic when you think about it that adding an index to speed things up can slow things down while it&amp;rsquo;s happening.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Postgres of course has the answer for this with &lt;code&gt;CONCURRENT&lt;/code&gt; index creation. What this does is gradually build up the index in the background. You can create your index concurrently with: &lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt;. As soon as the index is created and available as long as you did what you were hoping to Postgres will swap over to using it on queries.&lt;/p&gt;
&lt;h3 id="a-tool-to-help"&gt;
&lt;div&gt;
A tool to help
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s a good practice to understand what is happening when you run a migration and its performance impact. That said you don&amp;rsquo;t have to manage this all on your own. At least for Rails there&amp;rsquo;s a tool to help enforce more of these as you&amp;rsquo;re developing to catch it earlier. &lt;a href="https://github.com/ankane/strong_migrations"&gt;Strong migrations&lt;/a&gt; aims to catch many of these expensive operations for you to have your back, if you&amp;rsquo;re on Rails consider giving it a look.&lt;/p&gt;
&lt;p&gt;Have other tools or tips that can help with database migrations in Postgres? &lt;a href="https://www.twitter.com/craigkerstiens"&gt;Drop me a note&lt;/a&gt; and I&amp;rsquo;ll work to add them to the list.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 10 Sep 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/09/10/better-postgres-migrations/</guid></item><item><title>Basic imenu in helpful-mode</title><link>https://xenodium.com/basic-imenu-in-helpful-mode</link><description>&lt;p&gt;I'm finding Wilfred Hughes's &lt;a href="https://github.com/Wilfred/helpful"&gt;helpful-mode&lt;/a&gt;, well… rather helpful. However, I'm missing imenu support. Here's a hacky way to get basic imenu.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/basic-imenu-for-helpful-mode/helpful-imenu.png" /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(defun helpful--create-imenu-index ()
  &amp;quot;Create an `imenu' index for helpful.&amp;quot;
  (beginning-of-buffer)
  (let ((imenu-items '()))
    (while (progn
             (beginning-of-line)
             ;; Not great, but determine if looking at heading:
             ;; 1. if it has bold face.
             ;; 2. if it is capitalized.
             (when (and (eq 'bold (face-at-point))
                        (string-match-p
                         &amp;quot;[A-Z]&amp;quot;
                         (buffer-substring (line-beginning-position)
                                           (line-end-position))))
               (add-to-list 'imenu-items
                            (cons (buffer-substring (line-beginning-position)
                                                    (line-end-position))
                                  (line-beginning-position))))
             (= 0 (forward-line 1))))
    imenu-items))

(defun helpful-mode-hook-function ()
  &amp;quot;A hook function for `helpful-mode'.&amp;quot;
  (setq imenu-create-index-function #'helpful--create-imenu-index))

(add-hook 'helpful-mode-hook
          #'helpful-mode-hook-function)
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 10 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/basic-imenu-in-helpful-mode</guid></item><item><title>Working with Rust</title><link>https://boyter.org/2017/09/working-rust/</link><description>&lt;p&gt;For a while I have been wanting to play with a new programming language. Professionally I work with Java, C#, Python and JavaScript and so I went looking for something complimentary to them.&lt;/p&gt;
&lt;p&gt;My first stop was was Go. I started by implementing a vector space search in it which you can see here &lt;a href="https://github.com/boyter/golangvectorspace"&gt;https://github.com/boyter/golangvectorspace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While I liked the syntax (I still cannot think in Go), the libraries and the performance I realized that Go is close to a hybrid of Java and Python for me. It has the &lt;a href="http://www.boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/"&gt;performance of Java&lt;/a&gt; with the Python style syntax. This is fine but I really wanted to push what I already am familiar with.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 10 Sep 2017 00:59:08 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/09/working-rust/</guid></item><item><title>Art Friday: Eclipse</title><link>http://michaelhoney.com/writing/2017/9/8/art-friday-eclipse</link><description>&lt;figure class="
              sqs-block-image-figure
              intrinsic
            "&gt;
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                &lt;img alt="" height="1000" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1504852361362-X3YAK59Y45TS9HOYVMWE/eclipse-4000-201798-16-25-30.png?format=1000w" width="1000" /&gt;

            
          
        
          
        

        
      
        &lt;/figure&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Fri, 08 Sep 2017 09:33:02 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2017/9/8/art-friday-eclipse</guid></item><item><title>Tips on Creating Reusable Components</title><link>https://dylanpaulus.com/posts/2017/tips-on-creating-reusable-components/</link><description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;A huge selling point of React is its use of composable, reusable components. Everything is built off the idea of &lt;code&gt;V = F(d)&lt;/code&gt;, or view/UI is created by some function acting on data/state. How do we create more advanced user interface? Well, just add more functions to the party (For example &lt;code&gt;V = G(F(E(S(d))))&lt;/code&gt;). That's cute, why does this matter? Thinking of our components as functions, even if we use &lt;em&gt;class&lt;/em&gt;, will help us create more reusable components. It even helps us write super helpful utility functions called &lt;a href="/posts/higher-order-components/"&gt;Higher Order Components&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We'll look at ways to improve our reusability and composition of components by using an example component a long the way. For this article, we'll use a component that adds an Icon to a button.&lt;/p&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class IconButton extends React.Component {
  render() {
    &amp;lt;Button onClick={this.props.onClick}&amp;gt;
      &amp;lt;Icon /&amp;gt; {this.props.text}
    &amp;lt;/Button&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And to consume the button,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IconButton text="Click Me!" onClick={() =&amp;gt; alert("Click!")} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not bad.. easy to use, and to the point. But, some part of me thinks this could be better. Let's walk through a few suggestions on making this component more reusable.&lt;/p&gt;
&lt;h3&gt;Keep it Simple, Jack&lt;/h3&gt;
&lt;p&gt;Continuing on the topic of thinking of components as functions, keep components simple. Components that do too many things are dangerous. They are easy to break, and a pain to maintain. Instead, split functionality into separate components, then compose those components to make something functional. This makes it really easy to maintain features, and to swap out functionality when requirements change.&lt;/p&gt;
&lt;p&gt;Going to the IconButton example, we really don't need an IconButton component. What if tomorrow we need an IconInput button? We not only have two separate, but pretty similar components to maintain! We can fix this by using composition. What we really want is something that 'adds an icon' to a component. Let's make a new component called IconAdder.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class IconAdder extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;Icon /&amp;gt; {this.props.component}
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to consume it&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IconAdder
  component={&amp;lt;Button onClick={() =&amp;gt; alert("Click!")}&amp;gt;Click Me!&amp;lt;/Button&amp;gt;}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IconAdder allows us to throw any ol' component we want into it, and it'll add an Icon to it. Nice.&lt;/p&gt;
&lt;h3&gt;Hello There, Children!&lt;/h3&gt;
&lt;p&gt;One thing I come across a lot is the overuse of component properties. Components should almost never be used as properties. It ends up making components hard to use, and in the end, we are fighting with React. In React, every component has a property called children (&lt;code&gt;props.children&lt;/code&gt;). This says, whatever we pass between this component's tags, we'll insert here. Let's see an example &lt;code&gt;props.children&lt;/code&gt; in the IconAdder component.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class IconAdder extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;Icon /&amp;gt; {this.props.children}
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to consume it&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IconAdder&amp;gt;
  &amp;lt;Button onClick={() =&amp;gt; alert("Click!")}&amp;gt;Click Me!&amp;lt;/Button&amp;gt;
&amp;lt;/IconAdder&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;Button&amp;gt;&lt;/code&gt; component will be inserted in IconAdder's &lt;code&gt;{this.props.children}&lt;/code&gt;! Much better!&lt;/p&gt;
&lt;h3&gt;Injecting HTML Types&lt;/h3&gt;
&lt;p&gt;I wrote an article on this &lt;a href="/posts/injecting-react-tag-types/"&gt;subject here&lt;/a&gt; already so I'll be brief.&lt;/p&gt;
&lt;p&gt;As someone consuming a component, I want as little pollution of my code as possible. Pollution in this case could be anything: event handlers, code size, or even HTML elements. In the case of our IconAdder component, a parent &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; wrapper gets added to every component using it. It would be great if we could get rid of the div, and just make it our child component. Well... we're in luck. We can specify a tag property, and then use that property. This lets the end-user be in control of their DOM structure.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class IconAdder extends React.Component {
  render() {
    const { tag, onClick, children } = this.props;
    const Tag = tag;

    return (
      &amp;lt;Tag onClick={onClick}&amp;gt;
        &amp;lt;Icon /&amp;gt; {children}
      &amp;lt;/Tag&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to consume it&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IconAdder tag={Button} onClick={() =&amp;gt; alert("Click!")}&amp;gt;
  Click Me!
&amp;lt;/IconAdder&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another benefit of using a 'tag' property, is let's say that we want to support React Router's &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; component, but we also need to support the classic HTML &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag. We can easily swap these two out by just changing the 'tag' prop!&lt;/p&gt;
&lt;h3&gt;Allow Extension&lt;/h3&gt;
&lt;p&gt;Nothing grinds my gears like getting a fresh new component, but realizing I want to make the font bold. So, I add a quick &lt;code&gt;style={ { fontWeight: 800 } }&lt;/code&gt; to the component, refresh, and nothing changes. (Warning: what is about to be shown requires a transpiler).&lt;/p&gt;
&lt;p&gt;We should allow our components to be reasonably editable, while protecting what we need to. This can be done by the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Rest_in_Object_Destructuring"&gt;rest operator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Right now, our IconAdder component won't accept a style, className, or title prop. Oh yeah, and what about in the future if we need to use IconAdder on a &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag. We'll need to support href also. Let's use the rest operator to support all of these properties!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class IconAdder extends React.Component {
  render() {
    const { tag, onClick, children, ...rest } = this.props;
    const Tag = tag;

    return (
      &amp;lt;Tag onClick={onClick} {...rest}&amp;gt;
        &amp;lt;Icon /&amp;gt; {children}
      &amp;lt;/Tag&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to consume it&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IconAdder
  tag={Button}
  onClick={() =&amp;gt; alert("Click!")}
  style={{ fontWeight: "800" }}
  title="A button for clicking"&amp;gt;
  Click Me!
&amp;lt;/IconAdder&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;...rest&lt;/code&gt; will grab whatever properties we haven't taken off in the destructuring (&lt;code&gt;const { a, b, c} = this.props;&lt;/code&gt;), and assign it, in this case, to a variable called &lt;code&gt;rest&lt;/code&gt;. We then apply all those properties to our &lt;code&gt;&amp;lt;Tag&amp;gt;&lt;/code&gt; component by destructuring the &lt;code&gt;rest&lt;/code&gt; object into the individual props. As shown in the consumption of IconAdder, we can now add whatever other properties we want!&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;These are a few tips I use when creating components to keep them easier to consume, and extend. In summary, think of every component as a function. It will consume some input, and produce an output. The children property is your friend, use it when it makes sense! Dynamically injecting the component type can turn multiple similar components, into one highly reusable component. Finally, allow components to receive extra props, and have the properties/styles override the base implementation when possible.&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Fri, 08 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2017/tips-on-creating-reusable-components/</guid></item><item><title>2017-09-08</title><link>https://ho.dges.online/pictures/2017-09-08/</link><description/><author>ho.dges.online</author><pubDate>Fri, 08 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-09-08/</guid></item><item><title>ECAL session notes: Open-Ended Simulations</title><link>https://liza.io/ecal-session-notes-open-ended-simulations/</link><description>&lt;p&gt;As before, what follow is a &lt;em&gt;very slightly&lt;/em&gt; cleaned up version of the notes I took during the third ISAL summer school session at ECAL 2017. Also as before, note that this is very rough, made while I was reviewing them tonight. Apologies for any typos or other mistakes.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Thu, 07 Sep 2017 18:25:45 GMT</pubDate><guid isPermaLink="true">https://liza.io/ecal-session-notes-open-ended-simulations/</guid></item><item><title>ECAL session notes: Digital Evolution</title><link>https://liza.io/ecal-session-notes-digital-evolution/</link><description>&lt;p&gt;As before, what follow is a &lt;em&gt;very slightly&lt;/em&gt; cleaned up version of the notes I took during the second ISAL summer school session at ECAL 2017. Also as before, note that this is very rough, made while I was reviewing them tonight. Apologies for any typos or other mistakes.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Wed, 06 Sep 2017 22:11:58 GMT</pubDate><guid isPermaLink="true">https://liza.io/ecal-session-notes-digital-evolution/</guid></item><item><title>Avoid using out-of-date operating system images in Docker by always using the `docker build --pull`</title><link>https://www.databasesandlife.com/docker-build-pull-option/</link><description>&lt;p&gt;I wrote down a note on my task list on the current project, &amp;ldquo;Investigate whether &lt;code&gt;docker build&lt;/code&gt; always gets the latest version of the base image&amp;rdquo;. The answer is, it does not, by default. Always use the &lt;code&gt;--pull&lt;/code&gt; option to get the latest version.&lt;/p&gt;
&lt;p&gt;When installing any software, it&amp;rsquo;s important to have security updates applied to all its components, including the operating system. When security fixes are released, new Docker base images are produced, and you can rebuild your software based on the new images, test your software, and deploy it. You should be doing this regularly.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Wed, 06 Sep 2017 16:41:32 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/docker-build-pull-option/</guid></item><item><title>Behind the Scenes at a VC Fund, Part 3: Fund Structure, Fundraising, Investor Relations, and FAQs</title><link>https://www.codingvc.com/p/behind-the-scenes-at-a-vc-fund-part-3-fund-structure-fundraising-investor-relations-and-faqs</link><description>VCs have 3 principal jobs: picking startups to invest in, helping startups after investing, and raising capital for investing.</description><author>Coding VC</author><pubDate>Wed, 06 Sep 2017 05:58:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/behind-the-scenes-at-a-vc-fund-part-3-fund-structure-fundraising-investor-relations-and-faqs</guid></item><item><title>Splitting a concatenated RAxML-style PHYLIP file</title><link>https://jonathanchang.org/blog/splitting-a-concatenated-raxml-style-phylip-file/</link><description>&lt;p&gt;I’ve written a little script in Python 3 that will unconcatenate a RAxML-style PHYLIP + partitions file. I’ve used it recently to do a gene tree-species tree analysis for phylogenetic inference. It’s a little slow since it doesn’t manage file handles well (or at all), but it should use very little memory and therefore be able to handle very large concatenated alignments.&lt;/p&gt;
  
  &lt;p&gt;Here’s a short worked example using the data from the &lt;a href="https://sco.h-its.org/exelixis/web/software/raxml/hands_on.html"&gt;RAxML “hands-on” tutorial&lt;/a&gt;&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;
      &lt;p&gt;Download the script and all data files&lt;/p&gt;
      &lt;div class="language-bash highlighter-rouge"&gt;
        &lt;div class="highlight"&gt;
          &lt;pre class="highlight"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://gist.githubusercontent.com/jonchang/34c2e8e473ec2e8f50574671e62c3365/raw/unconcatenate_phylip.py
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://sco.h-its.org/exelixis/resource/download/hands-on/dna.phy
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://sco.h-its.org/exelixis/resource/download/hands-on/simpleDNApartition.txt
&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Run the script&lt;/p&gt;
      &lt;div class="language-bash highlighter-rouge"&gt;
        &lt;div class="highlight"&gt;
          &lt;pre class="highlight"&gt;&lt;code&gt;python3 unconcatenate_phylip.py dna.phy simpleDNApartition.txt
&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Examine the output&lt;/p&gt;
      &lt;div class="highlighter-rouge"&gt;
        &lt;div class="highlight"&gt;
          &lt;pre class="highlight"&gt;&lt;code&gt;INFO: Working on 10 taxa
INFO: Wrote to dna_DNA_p1.phylip
INFO: Wrote to dna_DNA_p2.phylip
&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;By default, the output is written in the PHYLIP format and is named like &lt;code&gt;{INPUT_FILE}_{PARTITION_NAME}.{FORMAT}&lt;/code&gt;. For FASTA output, pass &lt;code&gt;--type=fasta&lt;/code&gt;. You can also specify a prefix to add to the output file names with &lt;code&gt;--prefix=subdir/&lt;/code&gt;, and optionally trim gaps and drop sequences consisting of only gaps with &lt;code&gt;--trim&lt;/code&gt;. Check the video above for a quick demonstration of all the options.&lt;/p&gt;
      &lt;p&gt;You can also enable detailed output with &lt;code&gt;--verbose&lt;/code&gt;.&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;&lt;strong&gt;This currently doesn’t support partition formats that partition by e.g., 1st + 2nd postition and 3rd position.&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;&lt;a href="https://gist.github.com/jonchang/34c2e8e473ec2e8f50574671e62c3365"&gt;See the source on GitHub&lt;/a&gt;.&lt;/p&gt;</description><author>Jonathan Chang</author><pubDate>Wed, 06 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jonathanchang.org/blog/splitting-a-concatenated-raxml-style-phylip-file/</guid></item><item><title>Debugging Cron</title><link>https://www.wints.org/notes/2017.09.06/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
Cron job wasn&amp;rsquo;t running. Couldn&amp;rsquo;t tell why.
I had done the following in the crontab:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;set the SHELL to &amp;lsquo;bash&amp;rsquo;&lt;/li&gt;
&lt;li&gt;used full paths for everything&lt;/li&gt;
&lt;li&gt;cd&amp;rsquo;d to the correct directory in the cronjob&lt;/li&gt;
&lt;li&gt;activated the correct virtualenv in the cronjob&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Still did not work.&lt;/p&gt;
&lt;h5 id="logging"&gt;Logging &lt;a href="#logging"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;I then found out that I could enable logging for cron by:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[whatever cmd] &amp;gt;&amp;gt; /home/dhruv/projects/prod/cron.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;File Descriptor 1 = stdout
File Descriptor 2 = stderr&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Wed, 06 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.09.06/</guid></item><item><title>REST API with Node.js and Swagger</title><link>https://danielpecos.com/2017/09/06/rest-api-with-node-js-and-swagger/</link><description>&lt;p&gt;&lt;img alt="Swagger for Node.js" class="size-fp-small aligncenter" height="296" src="https://danielpecos.com/assets/2017/09/swaggerfornodejs.jpg" width="640" /&gt;In this tutorial I&amp;rsquo;ll show how to piece together the required NPM modules to build a REST API in Node.js with proper Swagger documentation. We&amp;rsquo;re going to use Express as the HTTP framework, and the Swagger documentation will be written as inline comments within the code, as close as possible to the handling endpoint or models that will implement the contract, so it will be harder for them to eventually diverge.&lt;/p&gt;
&lt;p&gt;First of all, these are the main modules we are going to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;swagger-jsdoc&lt;/strong&gt; to extract the documentation from the comments in the source code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;swagger-ui-express&lt;/strong&gt; to build on-the-fly an HTML version of the documentation (which will allow us also to live test it)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;swagger-model-validator&lt;/strong&gt; to check that the input &amp;amp; outputs of the request match the models defined for the endpoints&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s start with the handlers for the REST endpoints:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// api/controllers/stocks.js

router.get('/', (req, res, next) =&amp;gt; {
  const response = dao.retrieveAll()
  res.send(response)
})

router.get('/:id', (req, res, next) =&amp;gt; {
  const response = dao.retrieve(parseInt(req.params.id, 10))
  res.send(response)
})

router.put('/:id', (req, res, next) =&amp;gt; {
  const response = dao.update(parseInt(req.params.id, 10), req.body.lastUpdate)
  res.send(response)
})

router.post('/', (req, res, next) =&amp;gt; {
  const response = dao.create(req.body)
  res.send(response)
})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nothing especial hear, just plain Express handlers, using GET, PUT and POST HTTP verbs.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s write the Swagger documentation as JSON documents within JS multiline comments:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// api/models/stock-model.js

/**
 * @swagger
 * definitions:
 *   Stock:
 *     type: object
 *     required:
 *       - id
 *       - name
 *       - currentPrice
 *       - lastUpdate
 *     properties:
 *       id:
 *         type: number
 *       name:
 *         type: string
 *       currentPrice:
 *         type: number
 *       lastUpdate:
 *         type: number
 *   Stocks:
 *     type: array
 *     items:
 *       $ref '#definitions/Stock'
 */
export default class Stock {
  constructor (id, name, currentPrice, lastUpdate) {
    this.id = id
    this.name = name
    this.currentPrice = currentPrice
    this.lastUpdate = lastUpdate
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;// api/controllers/stocks.js

/**
 * @swagger
 * /stocks:
 *   get:
 *     description: Retrieve the full list of stocks
 *     tags:
 *       - stocks
 *     produces:
 *       - application/json
 *     responses:
 *       200:
 *         description: stocks
 *         schema:
 *           $ref: '#/definitions/Stocks'
 */
router.get('/', (req, res, next) =&amp;gt; {
  const response = dao.retrieveAll()
  res.send(response)
})

/**
 * @swagger
 * /stocks/{id}:
 *   get:
 *     description: Retrieve an specific stock
 *     tags:
 *       - stocks
 *     produces:
 *       - application/json
 *     parameters:
 *       - name: id
 *         description: id of the stock to retrieve
 *         in: path
 *         required: true
 *         type: number
 *     responses:
 *       200:
 *         description: stock
 *         schema:
 *           $ref: '#/definitions/Stock'
 */
router.get('/:id', (req, res, next) =&amp;gt; {
  const response = dao.retrieve(parseInt(req.params.id, 10))
  res.send(response)
})

...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now that we have all the documentation in place, let&amp;rsquo;s define a new endpoint to serve the live documentation:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// api/controllers/swagger.js

const options = {
  swaggerDefinition: {
    info: {
      title: 'REST - Swagger',
      version: '1.0.0',
      description: 'REST API with Swagger doc',
      contact: {
        email: 'contact@danielpecos.com'
      }
    },
    tags: [
      {
        name: 'stocks',
        description: 'Stocks API'
      }
    ],
    schemes: ['http'],
    host: 'localhost:3000',
    basePath: '/api'
  },
  apis: ['./api/controllers/stocks.js', './api/models/stock-model.js']
}

const swaggerJSDoc = require('swagger-jsdoc')
const swaggerUi = require('swagger-ui-express')
const swaggerSpec = swaggerJSDoc(options)

router.get('/json', function (req, res) {
  res.setHeader('Content-Type', 'application/json')
  res.send(swaggerSpec)
})

router.use('/', swaggerUi.serve, swaggerUi.setup(swaggerSpec))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see in the next screenshot, the docs are live and working against the endpoints served by the same application:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://danielpecos.com/assets/2017/09/Screenshot_20170905_233237.png?ssl=1"&gt;&lt;img alt="Swagger UI" class="aligncenter size-medium" height="300" src="https://danielpecos.com/assets/2017/09/Screenshot_20170905_233237.png" width="291" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And you can even test them in realtime!&lt;/p&gt;
&lt;img alt="Swagger UI - Endpoint test" class="aligncenter size-medium" height="300" src="https://danielpecos.com/assets/2017/09/Screenshot_20170905_233349.png" width="291" /&gt;
&lt;p&gt;Finally let&amp;rsquo;s put some code that will allow us to check that the inputs &amp;amp; outputs of the different endpoints match the models defined in Swagger:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// api/controllers/stocks.js
...
router.put('/:id', (req, res, next) =&amp;gt; {
  Swagger.validateModel('TimeStamp', req.body)
  const response = dao.update(parseInt(req.params.id, 10), req.body.lastUpdate)
  Swagger.validateModel('Stock', response)
  res.send(response)
})
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we have a proper (and documented) REST API that we can hand over to any developer, making her life easier and more productive.&lt;/p&gt;
&lt;p&gt;You can find this example in this GitHub repository:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dpecos/rest-swagger-example"&gt;https://github.com/dpecos/rest-swagger-example&lt;/a&gt;&lt;/p&gt;</description><author>GeekWare - Daniel Pecos Martínez</author><pubDate>Wed, 06 Sep 2017 00:07:29 GMT</pubDate><guid isPermaLink="true">https://danielpecos.com/2017/09/06/rest-api-with-node-js-and-swagger/</guid></item><item><title>Debugging in PhpStorm with Xdebug locally, in Vagrant or in Docker</title><link>https://tricht.eu/post/debugging-in-phpstorm-with-xdebug-locally-in-vagrant-or-in-docker/</link><description>&lt;p&gt;Do you use PhpStorm and have you ever wondered what all those fancy debugging features were? Or could you just not get Xdebug running in Docker or your Vagrant machine? Wonder no more!&lt;/p&gt;</description><author>Michael van Tricht</author><pubDate>Tue, 05 Sep 2017 22:33:40 GMT</pubDate><guid isPermaLink="true">https://tricht.eu/post/debugging-in-phpstorm-with-xdebug-locally-in-vagrant-or-in-docker/</guid></item><item><title>ECAL session notes: Historical and Philosophical Perspectives on Artificial Life</title><link>https://liza.io/ecal-session-notes-historical-and-philosophical-perspectives-on-artificial-life/</link><description>&lt;p&gt;What follow is a &lt;em&gt;very slightly&lt;/em&gt; cleaned up version of the notes I took during the first ISAL summer school session at ECAL 2017. Note that this is very rough, I was just reviewing my notes and thought I may as well put them into a post format at the same time to revisit later. Apologies for any typos or other mistakes.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Tue, 05 Sep 2017 20:02:17 GMT</pubDate><guid isPermaLink="true">https://liza.io/ecal-session-notes-historical-and-philosophical-perspectives-on-artificial-life/</guid></item><item><title>Composable, Programmatic Animations for Games</title><link>https://blog.varunramesh.net/posts/composable-animations/</link><description>This post describes a method for creating animations in games programmatically, while still retaining composability.</description><author>Varun Ramesh's Blog</author><pubDate>Tue, 05 Sep 2017 03:14:22 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/composable-animations/</guid></item><item><title>Validating a React form upon submit</title><link>https://goshacmd.com/submit-time-validation-react/</link><author>Gosha Spark</author><pubDate>Tue, 05 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/submit-time-validation-react/</guid></item><item><title>Bogosort in Practice</title><link>https://xavd.id/blog/post/bogosort-in-practice/</link><description>If you actually implemented Bogosort, how bad could it be?&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/bogosort-in-practice/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Tue, 05 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/bogosort-in-practice/</guid></item><item><title>My Pardot landing page starter kit</title><link>https://daniel.do/article/pardot-starter-kit</link><description>Because building Pardot landing pages sucks.</description><author>Daniel Immke</author><pubDate>Tue, 05 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/pardot-starter-kit</guid></item><item><title>Day 1 of ECAL 2017 - ISAL Summer School</title><link>https://liza.io/day-1-of-ecal-2017-isal-summer-school/</link><description>&lt;p&gt;Today was the first day of ECAL (European Conference on Artificial Life) 2017 in Lyon, France and my first year attending. It&amp;rsquo;s lucky I managed to go this year, because apparently this is the last ECAL! Next time it will be turning into the International Conference on Artificial Life and will be held much farther away (I &lt;em&gt;think&lt;/em&gt; it is meant to be held in Japan). Although I am already getting my hopes up to go again, not only for the conference but to visit Japan once more!&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Mon, 04 Sep 2017 22:55:54 GMT</pubDate><guid isPermaLink="true">https://liza.io/day-1-of-ecal-2017-isal-summer-school/</guid></item><item><title>Unifying Dynamic Type Tests and Type Refinement</title><link>https://blog.varunramesh.net/posts/understanding-dynamic-typechecks/</link><description>Some typecheckers understand dynamic type tests, thus avoiding downcasting.</description><author>Varun Ramesh's Blog</author><pubDate>Mon, 04 Sep 2017 09:44:30 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/understanding-dynamic-typechecks/</guid></item><item><title>Python's os.path.isdir() quirk</title><link>https://www.wints.org/notes/2017.09.04/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Python&amp;rsquo;s &lt;code&gt;os.path.isdir()&lt;/code&gt; is a much used function, but today, I wasn&amp;rsquo;t getting the expected results.
My directory looks like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;|_root/
    |_colors/
        |_blue/
        |   |_blue1.jpg
        |   |_blue2.jpg
        |_red
            |_red1.jpg
            |_red2.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I ran the code snippet below, I was getting all nothing. &lt;code&gt;os.path.isdir()&lt;/code&gt; was return &amp;lsquo;False&amp;rsquo; on all of the color folders:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;colors_dir = os.path.join(os.path.abspath("root"), "colors")

for i in os.listdir(colors_dir):
    if os.path.isdir(i):
        print i
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id="solution"&gt;Solution &lt;a href="#solution"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;You need the entire path to the entry for &lt;code&gt;os.path.isdir()&lt;/code&gt; to detect file|folder correctly. So:&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 04 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.09.04/</guid></item><item><title>The World's End</title><link>https://olshansky.info/movie/the_worlds_end/</link><description>Olshansky's review of The World's End</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 04 Sep 2017 01:28:06 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_worlds_end/</guid></item><item><title>Postgres backups: Logical vs. Physical an overview</title><link>/2017/09/03/postgres-backups-physical-vs-logical/</link><description>&lt;p&gt;It&amp;rsquo;s not a very disputed topic that you should backup your database, and further test your backups. What is a little less discussed, at least for Postgres, is the types of backups that exist. Within Postgres there are two forms of backups and understanding them is a useful foundation for anyone working with Postgres. The two backup types are&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Physical: which consist of the actual bytes on disk,&lt;/li&gt;
&lt;li&gt;Logical: which is a more portable format.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s dig into each a bit more so you can better assess which makes sense for you.&lt;/p&gt;
&lt;h3 id="logical-backups"&gt;
&lt;div&gt;
Logical backups
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Logical backups are the most well known type within Postgres. This is what you get when you run &lt;code&gt;pg_dump&lt;/code&gt; against a database. There are a number of different formats you can get from &lt;a href="http://postgresguide.com/utilities/backup-restore.html"&gt;logical backups&lt;/a&gt; and Postgres does a good job of making it easy to compress and configure this backup how you see fit.&lt;/p&gt;
&lt;p&gt;When a logical backup is run against a database it is not throttled, this introduces a noticable load on your database.&lt;/p&gt;
&lt;p&gt;As it&amp;rsquo;s reading the data from disk and generating (in layman terms) a bunch of SQL &lt;code&gt;INSERT&lt;/code&gt; statements, it has to actually see the data. It&amp;rsquo;s of note that older Postgres databases (read: prior to 9.3) there were no checksums against your database. Checksums are just one tool for you to help check against data corruption. Because a logical dump has to actually read and generate the data to insert it will discover any corruption that exists for you.&lt;/p&gt;
&lt;p&gt;This portable format is also very useful to pull down copies from production to different environments. I.e. if you need a copy of production data down on your local laptop &lt;code&gt;pg_dump&lt;/code&gt; is the way to do it. Logical backups are also database specific, but then allow you to dump only certain tables.&lt;/p&gt;
&lt;p&gt;All in all logical backups bring some good features, but come at two cost:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Load on your system&lt;/li&gt;
&lt;li&gt;The backup contains data as of the time when it ran&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="physical-backups"&gt;
&lt;div&gt;
Physical backups
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Physical backups are another option when it comes to backing up your database. As we mentioned earlier it is the physical bytes on disk. To understand physical backups we need to know a bit more under the covers about how Postgres works.&lt;/p&gt;
&lt;p&gt;Postgres, under the covers, is essentially one giant append only log. When you insert data it gets written to the log known as the write-ahead log (commonly called WAL). When you update data a new record gets written to the WAL. When you delete data a new record gets written to the WAL. Nearly all changes in Postgres including to indexes and otherwise cause an update to the WAL.&lt;/p&gt;
&lt;p&gt;With physical backups what you require to be able to create a restore of your database is two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;base backup&lt;/code&gt;, which is a copy of the bytes on disk as of that point and time&lt;/li&gt;
&lt;li&gt;Additional segments of the WAL to put the database in some consistent state.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A physical backup only requires a small amount of WAL to restore the database to some valid state, &lt;em&gt;but&lt;/em&gt; this also gives you some new flexibility. With a base backup plus WAL you can start to replay transactions up to a specific point in time. This is often how point-in-time recovery is performed within Postgres. If you accidentally drop a table, yes&amp;hellip; it happens, you can:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find a base backup before you dropped the table&lt;/li&gt;
&lt;li&gt;Restore that base backup&lt;/li&gt;
&lt;li&gt;Replay wal segments up to roughly that time just before you dropped the table.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re considering setting up physical backups, consider using a tool like &lt;a href="https://www.citusdata.com/blog/2017/08/18/introducing-wal-g-faster-restores-for-postgres/"&gt;WAL-G&lt;/a&gt; to help.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="logical-vs-physical-which-to-choose"&gt;
&lt;div&gt;
Logical vs. Physical which to choose
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Both are useful and provide different benefits. At smaller scale, say under 100 GB of data logical backups via &lt;code&gt;pg_dump&lt;/code&gt; are something you should absolutely be doing. Because backups happen quickly on smaller databases you may be able to get out without functionality like point-in-time recovery. At larger scale, as you approach 1 TB physical backups start to become your only option. Because of the load introduced by logical backups and the time lapse between capturing them they become less suitable for production.&lt;/p&gt;
&lt;p&gt;Hopefully this primer helps provide a high level overview of the two primary types of backups that exist as options for Postgres. Of course there is much deeper you can go on each, but consider ensuring you have at least one of the two if not both in place. Oh and make sure to test them, an un-tested backup isn&amp;rsquo;t a backup at all.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 03 Sep 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/09/03/postgres-backups-physical-vs-logical/</guid></item><item><title>Refactoring a Node.js codebase using Async/Await</title><link>https://thomashunter.name/posts/2017-09-03-refactoring-a-nodejs-codebase-using-async-await</link><author>Thomas Hunter II</author><pubDate>Sun, 03 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-09-03-refactoring-a-nodejs-codebase-using-async-await</guid></item><item><title>[9.02.17] Mountainslider: Collapsible Electric Mountainboard</title><link>httpss://transistor-man.com/mountainslider.html</link><description>Build log of a portable electric mountainboard that shrinks and fits in a normal checked bag, able to be brought on an overseas flight.</description><author>transistor-man.com</author><pubDate>Sat, 02 Sep 2017 11:38:38 GMT</pubDate><guid isPermaLink="true">httpss://transistor-man.com/mountainslider.html</guid></item><item><title>React Image Filter</title><link>https://muffinman.io/blog/react-image-filter-component/</link><description>&lt;article class="article"&gt;&lt;p&gt;On the project I&amp;#x27;m currently working on, client&amp;#x27;s logo is displayed in two versions,
black on the white background and vice versa.
To make their life easier, so they don&amp;#x27;t have to upload two assets, I suggested SVG.
Alas they can&amp;#x27;t use SVGs (kinda long story), so I just applied CSS &lt;code&gt;filter: invert(1);&lt;/code&gt;, but...&lt;/p&gt;
&lt;p&gt;...you guessed it - it doesn&amp;#x27;t work in IE and Edge :(&lt;/p&gt;
&lt;p&gt;So I started reading about &lt;a href="https://developer.mozilla.org/en/docs/Web/SVG/Element/filter"&gt;SVG filters&lt;/a&gt;
and found a way to invert a image. But it got me interested,
so I kept going and made a React component for all sorts of color filters.&lt;/p&gt;
&lt;p&gt;Play with the &lt;a href="https://muffinman.io/react-image-filter/"&gt;interactive demo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Documenation available on &lt;a href="https://github.com/Stanko/react-image-filter"&gt;GitHub&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/react-image-filter"&gt;npm&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="React filter demo" height="1272" src="./image-filter-1.jpg" width="1904" /&gt;&lt;/figure&gt;
&lt;p&gt;SVG filters include &lt;code&gt;feColorMatrix&lt;/code&gt; which is a matrix for color transformation.
Changing the matrix value you can achieve all of the CSS filters.&lt;/p&gt;
&lt;p&gt;It accepts 5x4 matrix. Two examples:&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Base matrix (no filter)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Invert colors matrix&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token operator"&gt;-&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt; &lt;span class="token number"&gt;0&lt;/span&gt; &lt;span class="token operator"&gt;-&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt; &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt; &lt;span class="token operator"&gt;-&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt; &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;  &lt;span class="token number"&gt;1&lt;/span&gt;  &lt;span class="token number"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wasn&amp;#x27;t lazy so I made interactive way of changing values in matrix.
Every value has it&amp;#x27;s own range slider. This way you can see the changes right away.&lt;/p&gt;
&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="React filter controls" height="612" src="./image-filter-controls.png" width="1998" /&gt;&lt;/figure&gt;
&lt;p&gt;Soon I encountered another problem.
As applying SVG filters in CSS also doesn&amp;#x27;t work in IE and Edge, I used SVG &lt;code&gt;&amp;lt;image /&amp;gt;&lt;/code&gt; tag.
But SVG wouldn&amp;#x27;t scale to the image size.&lt;/p&gt;
&lt;p&gt;Then it hit me, I can solve it by using a simple hack. Component is rendering a wrapper div with SVG inside.
So I added a &lt;code&gt;&amp;lt;img /&amp;gt;&lt;/code&gt; using the same image and div resizes to fit the image.
Here comes the hack - I&amp;#x27;ve hidden the image using &lt;code&gt;visibility: hidden&lt;/code&gt; and made SVG absolute and 100% width/height.
This way SVG always keeps image aspect ratio.&lt;/p&gt;
&lt;p&gt;SVGs are awesome :)&lt;/p&gt;
&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="React filter demo" height="1270" src="./image-filter-2.jpg" width="1910" /&gt;&lt;/figure&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sat, 02 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-image-filter-component/</guid></item><item><title>How to update npm using nvm</title><link>https://muffinman.io/blog/nvm-updating-npm/</link><description>&lt;article class="article"&gt;&lt;p&gt;If you are JavaScript developer and not using &lt;a href="https://github.com/creationix/nvm"&gt;nvm&lt;/a&gt; you might want to look at it.
Node Version Manager is easy way to install, manage and work with multiple node versions.&lt;/p&gt;
&lt;p&gt;Recently I got npm update notification, that looks something like this:&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="npm update notification" height="116" src="./npm-update.png" width="505" /&gt;&lt;/figure&gt;
&lt;p&gt;For some reason, when I had node installed through nvm, &lt;code&gt;npm i -g npm&lt;/code&gt; didn&amp;#x27;t work. However, when I was using a &amp;quot;system&amp;quot; node version, installed from Node.js website, it did. I can&amp;#x27;t remember the exact error, but it was probably something with my &lt;code&gt;PATH&lt;/code&gt; configuration.&lt;/p&gt;
&lt;p&gt;So I tried to find a path where global packages are installed when using nvm. Once I found it, it was super easy to update &lt;code&gt;npm&lt;/code&gt; in that specific folder.&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# navigate to nvm&amp;#x27;s node lib folder&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# (replace v8.4.0 with your version)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; ~/.nvm/versions/node/v8.4.0/lib/
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# update npm right there&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; &lt;span class="token function"&gt;npm&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# reopen your terminal&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;#x27;s it. Great thing is that npm can update itself. And this works for any other global npm package.&lt;/p&gt;
&lt;p&gt;Or, as suggested in the comments, just use nvm&amp;#x27;s command:&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;nvm install-latest-npm
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sat, 02 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/nvm-updating-npm/</guid></item><item><title>The bittersweet end of a year of independence</title><link>https://ntietz.com/blog/bittersweet-end-to-independence/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;Just over a year ago, I left the &lt;a href="https://crosschx.com/"&gt;startup&lt;/a&gt; I was working for and started my own &lt;a href="http://caturra.io/"&gt;business&lt;/a&gt;. My intention was to do freelance work ("consulting", to all my clients) until I was able to launch my first product, and then shift into being a product company. My ambitions and confidence were very high. In this last year, I have accomplished a great deal and have a lot of pride in the work I did, as well as what I have learned. Nothing took the path I expected it to, but I wouldn't change that at all. With that in mind, sadly, I am winding down my consulting work and taking on a new full-time job. I'll explain why at the end, but first I want to share some a little bit about what I have experienced in the last year and why it was valuable.&lt;/p&gt;
&lt;h1 id="why-i-left-my-job"&gt;Why I left my job&lt;/h1&gt;
&lt;p&gt;It's valid to ask why I would even bother starting a business. It is a much harder path than getting another full-time job, with more stress, and with more risk. There are, however, some simple and clear reasons why I left my job. There were three primary reasons I left: I wanted to work on things with more autonomy; I wanted to control my work environment more; and I wanted to make more money.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Autonomy&lt;/strong&gt;: one thing that is important to me is owning the ideas/products I'm working on and developing them holistically, with a stake in the results. At the end of the day, I am more motivated if I am working on something very important to me, and it leads to greater results. I also thought that if I were working on my own I would develop better skills since I would need them and could not lean on anyone else for that; this was later proven correct, since working on my own projects led me to learn front-end development with an urgency I could not have previously imagined.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment&lt;/strong&gt;: my previous company had an open office, with lots of exposed concrete, metal, and wood. Needless to say, it was a very loud environment. I've learned that I am simply not productive in that environment. Among other issues, I have &lt;a href="https://en.wikipedia.org/wiki/Misophonia"&gt;misophonia&lt;/a&gt; (it is at its worst when I am tired or stressed), a peanut allergy, depression, and anxiety. These all made open offices very difficult for me to work in, and controlling my own environment and working remote has led me to being far happier and far more productive than when I worked in a physical office. Everyone is different; for me, controlling my environment has made a world of difference in ways I could not imagine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Money&lt;/strong&gt;: It was no secret at my last company that we were underpaid. My manager told me as much. This wasn't enough to make me want to leave on my own, but combined with a desire for more autonomy and for a work environment that worked better for me, it definitely increased my motivation to leave.&lt;/p&gt;
&lt;p&gt;At the time I left, my reasons for leaving were not quite as clear to me. I had some reasons and I had the story I told as I left. It was not a lie: I did want to leave to work on my own products. It just took this last year for me to fully realize &lt;em&gt;why&lt;/em&gt; I wanted to leave to work on my own products. At the end of the day, that office environment was not a good fit for me, and in the absence of a good fit, a lot of other small issues become big issues.&lt;/p&gt;
&lt;p&gt;So with that, I left with grand ideas of a few products I could make, and had a few clients lined up to keep the money rolling in until my products were launched.&lt;/p&gt;
&lt;h1 id="how-i-spent-the-last-year"&gt;How I spent the last year&lt;/h1&gt;
&lt;p&gt;When I left my job, I gave myself a plan. I would spend about half of my week working for clients, and I would spend the other half of my week learning new skills and working on my products. None of my product ideas worked out, because I did not have the skills to do front-end development when I started trying to make some web-app products. I did learn a lot, and actually worked on some very cool client projects.&lt;/p&gt;
&lt;p&gt;For one major property management software company, I rewrote their ETL pipeline using some big data tools and techniques so that it could scale and could run two orders of magnitude faster. This client's work was boring in some ways, but I'm indebted to my friend who introduced me to the team (I owe you a coffee, if you're reading this) because landing this client gave me the ability to quit my job.&lt;/p&gt;
&lt;p&gt;I also worked with the &lt;a href="http://www.un.org/en/index.html"&gt;world's biggest bureaucracy&lt;/a&gt; to modernize some of their old data systems and make it so that some really important data is more accessible, thereby enabling the internal teams to save real lives. This project was awesome in many ways, because it's rare to work on a project that has such a clear line to lives saved. It was also frustrating in some ways, which hopefully I'll be able to write another post about.&lt;/p&gt;
&lt;p&gt;Along the way I had some various small clients, who I consulted for on data engineering related topics, built small web-apps, etc. These were nothing to write home about, but they did give me a lot of insight into business and the value my code can add (or the lack thereof).&lt;/p&gt;
&lt;p&gt;In April, I also co-founded &lt;a href="https://dacatime.com/"&gt;DACA Time&lt;/a&gt;, developed the prototype, and built up a small team of volunteers to help me with some of the development tasks. This would not have been possible if I had been traditionally employed, since I was spending 20+ hours a week on this at some points.&lt;/p&gt;
&lt;h1 id="flexibility-saved-my-life-and-my-career"&gt;Flexibility saved my life and my career&lt;/h1&gt;
&lt;p&gt;I started my business so that I could have the flexibility to develop products while still paying my bills, but flexibility turned out being valuable to me for many more reasons than just that, in ways I could not have predicted.&lt;/p&gt;
&lt;p&gt;First and foremost, I believe that having flexibility saved my life and my career. In February, I was diagnosed with depression and anxiety. It was bad at that point: I had attempted to harm myself; I was only functional for 20-24 hours per week (I could work, then I would shut down); I had no interest in doing anything and was considering quitting tech entirely; and I spent probably half my time curled up and crying. Let me repeat that: my friends and clients had no idea that anything was wrong, but I was barely holding it together during work and was seriously considering doing permanent damage to myself or quitting my line of work entirely.&lt;/p&gt;
&lt;p&gt;I believe that if I had had a normal job, I would have not been able to hold it together even that long. That may or may not have been better for me, but I do know that having flexibility made it a lot easier for me to get to a doctor to seek treatment, and it made it a lot easier to take time off for mental health.&lt;/p&gt;
&lt;p&gt;This flexibility is also what led to me attending &lt;a href="http://givebackhack.com/"&gt;GiveBackHack&lt;/a&gt; and co-founding &lt;a href="https://dacatime.com/"&gt;DACA Time&lt;/a&gt;, which both showed me how much I can do as a software engineer, and reinvigorated my passion for software engineering, product design, and making a damn difference in the world.&lt;/p&gt;
&lt;h1 id="consulting-taught-me-a-lot"&gt;Consulting taught me a lot&lt;/h1&gt;
&lt;p&gt;During the course of the last year, I expected to learn a lot, and I did - but not the things I expected to learn. I expected to dive deep into machine learning, AI, and data engineering, and become a world-class expert in my narrow niche. It turns out, running a business actually doesn't teach you advanced mathematics, but does teach you some other practical things - who knew?  ¯\_(ツ)_/¯&lt;/p&gt;
&lt;p&gt;Being a consultant let me see how businesses worked on the business-end of things, rather than just the development side. I learned more about how my work directly impacts revenue, which is a lesson I will carry close to my heart through the rest of my work.&lt;/p&gt;
&lt;p&gt;I was also better able to determine my market value. When you're on your own, every client you get is a chance to re-negotiate your pay, so you can try over and over and eventually have a really good idea of your market value. I still don't know what my consulting rates should have been, but my clients were &lt;em&gt;way&lt;/em&gt; too happy with the price they paid for those rates to have been close to what the market would bear.&lt;/p&gt;
&lt;p&gt;The importance of networking and communication was also made really clear, since all my clients (literally every single one) came from my network. Focusing on communicating complex technical details to non-technical clients or less-technical folks became very very important, and made me realize how much value can be added just through clear communication; or how much value can be lost when the details are not communicated clearly. If no one knows who you are, what you can do, or what you did for them, then you cannot deliver them any value.&lt;/p&gt;
&lt;h1 id="go-forth-and-start-a-business"&gt;Go forth and start a business&lt;/h1&gt;
&lt;p&gt;If you are at all on the fence about starting your own business, you should do it. You will learn a lot about yourself, about the business world, and possibly about software development, and you will come away from it a much stronger contributor than if you just remained a normal software developer. You're better off taking the plunge and finding out that you don't like it, with some great stories to tell, rather than wondering if you could have or should have done it.&lt;/p&gt;
&lt;p&gt;If you are considering this and want to talk about how to get started, reach out to me and we can set up a coffee or a chat sometime.&lt;/p&gt;
&lt;h1 id="why-i-m-winding-down-my-business"&gt;Why I'm winding down my business&lt;/h1&gt;
&lt;p&gt;Self-employment has treated me really well, and I am in a much better position than I was a year ago in terms of happiness, fulfillment, and mental health. So why am I leaving self-employment behind to take a full-time job again?&lt;/p&gt;
&lt;p&gt;Well, there are a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;My wife and I are both self-employed. This creates are few challenges. Good insurance is super expensive, and my mental health treatment this winter/spring made me painfully aware of how expensive ultrasounds are. Additionally, banks are unfortunately &lt;em&gt;not&lt;/em&gt; very fond of lending money to two self-employed people, especially since I do not have a long history of it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I really really miss being part of a real team. When you're a consultant, you just have a very different relationship with everyone on a team than if you are a member of that team, and it's very isolating. When combined with being 100% remote and having less human contact, this can be challenging. I want to be part of a team again so we can rally together to do great things, so we can lean on each other, so we can be &lt;em&gt;friends&lt;/em&gt; instead of being clients/consultants.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consulting just isn't making me happy. My skill is as an individual contributor, not at running a business or being a manager. Running my own business required me to manage a lot of aspects of the software development process that I'm not good at, and it required me to manage a lot about my business that was very inefficient for me. (Next time around, and I promise there will be a next time, my wife is going to help with the business side of things, and I will outsource as much of the rest of these tasks as I can.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So on that note, I'm really happy and sad at the same time to say that I'm going to stop working as a consultant and will be moving back into a full-time job. Some of my friends know what company I'm joining, but it isn't public until after I've officially started (if you're curious, watch my LinkedIn profile). This is really bittersweet for me. There are so many advantages and good things about being with a company, but it comes with a certain loss of freedom and autonomy as well (and a loss of time to put towards DACA Time). I'm really confident that the team I'm joining is a great one, composed of great people, so I will be able to retain a lot of the flexibility which I have thrived with (otherwise, I wouldn't do this), but it remains a bittersweet end to a year of independence.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Sat, 02 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/bittersweet-end-to-independence/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>How I quit social media</title><link>https://daniel.do/article/quitting-social-media</link><description>Earlier this year I quit social media. I would recommend trying it.</description><author>Daniel Immke</author><pubDate>Sat, 02 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/quitting-social-media</guid></item><item><title>Quick Thoughts: Less Twitter</title><link>https://peterlyons.com/problog/2017/09/quick-thoughts-less-twitter/</link><description>&lt;h3 id="less-twitter"&gt;Less Twitter&lt;/h3&gt;
&lt;p&gt;So I started journaling my quick thoughts basically at the beginning of 2016 and only managed to post them to my blog once. So it goes, I guess. I have a backlog of them, most of which I'll just ignore and I'll post the highlights below.&lt;/p&gt;
&lt;p&gt;With my twitter feed becoming unpleasant due to so much Trump noise, I've reduced my use a twitter a lot. I've somewhat switched to reddit which is better organized into narrow topics. Instead of tweeting I'm just making little notes in my quick thought journal which I'll just post on my blog.&lt;/p&gt;
&lt;p&gt;On to the 2016 backlog...&lt;/p&gt;
&lt;h3 id="chesterton-s-fence"&gt;Chesterton's Fence&lt;/h3&gt;
&lt;p&gt;I often think this when looking at my own code.
&lt;a href="http://mcntyr.com/52-concepts-cognitive-toolkit/"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="why-babel-with-node"&gt;Why babel with node&lt;/h3&gt;
&lt;p&gt;At the beginning of 2016 I was frustrated and baffled as to why with node.js 6.3 supporting almost all of ES2015 natively, why would someone introduce the babel transpiler into a node-only server side project. So much ouch for so little benefit.&lt;/p&gt;
&lt;h3 id="promise-edge-cases"&gt;Promise Edge Cases&lt;/h3&gt;
&lt;p&gt;Promise library docs have special sections for delays/setTimeout, browsers, databases, etc. async.js has no such special cases.&lt;/p&gt;
&lt;h3 id="postgresql-toast"&gt;PostgreSQL TOAST&lt;/h3&gt;
&lt;p&gt;TOAST stands for The Oversized-Attribute Storage Technique, probably the best acronym in the history of Computer Science.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rachbelaid.com/introduction-to-postgres-physical-storage/"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="git-and-wip-commits"&gt;Git and WIP commits&lt;/h3&gt;
&lt;p&gt;How about a git that deals with both tiny WIP changes and larger more meaningful units?&lt;/p&gt;
&lt;h3 id="easier-to-reason"&gt;Easier to Reason&lt;/h3&gt;
&lt;p&gt;For every X units of complexity removed by "Easier to Reason About" techniques, programmers will take the opportunity to introduce &amp;gt;X other techniques that make things more complicated.&lt;/p&gt;
&lt;p&gt;I've also more recently experienced this phenomenon with serverless patterns. For every X units of complexity managed services and serverless patterns eliminate, programmers will add at least X complexity units in bizarre hacks, purported cost optimizations, etc.&lt;/p&gt;
&lt;h3 id="long-term-low-supervision"&gt;Long Term Low Supervision&lt;/h3&gt;
&lt;p&gt;Thinking back on the fact that I've at least twice had long-term (&amp;gt; 1 year) projects with shockingly low supervision. One was leading a small team, one was mostly solo with light collaboration/devops stuff. Both went really well from my perspective.&lt;/p&gt;
&lt;h3 id="writing-less-damn-code"&gt;Writing Less Damn Code&lt;/h3&gt;
&lt;p&gt;[http://www.heydonworks.com/article/on-writing-less-damn-code](Writing Less Damn Code)&lt;/p&gt;
&lt;h3 id="software-is-about-people"&gt;Software Is About People&lt;/h3&gt;
&lt;p&gt;For all this talk on podcasts about "software is about people" there are a lot of architecture articles that make no mention of team size or team quantity.&lt;/p&gt;
&lt;h3 id="aws"&gt;AWS&lt;/h3&gt;
&lt;p&gt;Ha ha https://www.aws.org is the American Welding Society&lt;/p&gt;
&lt;h3 id="consulting-feast-or-famine"&gt;Consulting Feast or Famine&lt;/h3&gt;
&lt;p&gt;My consulting work had been in famine mode for 6+ weeks. Full stop on work pending project sponsorship. Suddenly client calls a meeting and is like "How quickly can we get a demo working?". So I guess it's feast mode for the next 2 months or so. This is good because I could use some extra savings to cover my time at the Recurse Center this fall when I won't have any income.&lt;/p&gt;
&lt;h3 id="relative-dates"&gt;Relative Dates&lt;/h3&gt;
&lt;p&gt;meetup.com's message app says a message is from 1092 days ago. Wow. Such friendly UX. Such superior to an actual date.&lt;/p&gt;
&lt;h3 id="unusual-call-volume"&gt;Unusual Call Volume&lt;/h3&gt;
&lt;p&gt;Stop trying to explain long customer support queues as "unexpected load". Bullshit. It's because you just don't give a fuck. Own it.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 01 Sep 2017 17:43:35 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/09/quick-thoughts-less-twitter/</guid></item><item><title>How To: Deploy a Simple Java Web Service with AWS Lambda and API Gateway</title><link>https://www.mikekasberg.com/blog/2017/08/31/how-to-deploy-aws-lambda.html</link><description>&lt;p&gt;AWS is incredible technology, making it easy for anyone to deploy a web service
without needing to worry about managing servers. In this quick tutorial, we’re
going to see how to deploy a simple web service to AWS Lambda and make that
service available on the internet with AWS API Gateway. Let’s get started.&lt;/p&gt;

&lt;h2 id="start-with-a-seed"&gt;Start with a Seed&lt;/h2&gt;

&lt;p&gt;AWS supports Node.js, Python, Java, and C#. For this tutorial, we’ll be using
Java. As an example, we’re going to write a web service that can add two numbers
and return the result. What it does isn’t important - we’re focusing on the
setup here. The easiest way to start is by cloning a seed project to put the
framework in place. We’ll use my &lt;a href="https://github.com/mkasberg/aws-lambda-java-template"&gt;AWS Java
Seed&lt;/a&gt;, available on
Github. (&lt;em&gt;Warning: As of 2020, this seed is a couple years old and hasn’t been
updated. Consider finding a newer seed, or at least upgrade to newer versions of
the software after getting started.&lt;/em&gt;)&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ git clone git@github.com:mkasberg/aws-lambda-java-template.git 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point, if you want, you can remove the &lt;code class="language-plaintext highlighter-rouge"&gt;origin&lt;/code&gt; remote from your
repository clone, since we won’t be pushing our code back to it (&lt;code class="language-plaintext highlighter-rouge"&gt;git remote
remove origin&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id="write-some-code"&gt;Write Some Code&lt;/h2&gt;

&lt;p&gt;Open the project in your favorite Java IDE (I’m using
&lt;a href="https://www.jetbrains.com/idea/"&gt;IntelliJ&lt;/a&gt;). The project uses Maven for
dependency management (see pom.xml), and already includes the dependencies you
need to get started with AWS Lambda. Let’s run the compile target now (&lt;code class="language-plaintext highlighter-rouge"&gt;mvn
compile&lt;/code&gt;). The code should compile without errors. Let’s also run the tests
(&lt;code class="language-plaintext highlighter-rouge"&gt;mvn test&lt;/code&gt;). The API seed comes with a single test, which should pass.&lt;/p&gt;

&lt;p&gt;Now let’s dig into the code a bit. The &lt;code class="language-plaintext highlighter-rouge"&gt;Application&lt;/code&gt; class is a great place to
start. &lt;code class="language-plaintext highlighter-rouge"&gt;Application#handleRequest()&lt;/code&gt; is the method that will be called when our
Lambda service receives a request (forwarded from API gateway). We can parse the
&lt;code class="language-plaintext highlighter-rouge"&gt;inputStream&lt;/code&gt; into a &lt;code class="language-plaintext highlighter-rouge"&gt;JSONObject&lt;/code&gt;, and the URL parameters will be under the
&lt;code class="language-plaintext highlighter-rouge"&gt;queryStringParameters&lt;/code&gt; key. Let’s write some code to add the numbers that are
sent to our service on URL parameters &lt;code class="language-plaintext highlighter-rouge"&gt;a&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;b&lt;/code&gt;. Here’s our new
&lt;code class="language-plaintext highlighter-rouge"&gt;handleRequest()&lt;/code&gt; method:&lt;/p&gt;

&lt;div class="language-java highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InputStream&lt;/span&gt; &lt;span class="n"&gt;inputStream&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;OutputStream&lt;/span&gt; &lt;span class="n"&gt;outputStream&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;requestJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONTokener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputStream&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;responseJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Headers&lt;/span&gt;
    &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;headerJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;headerJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requestJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getJSONObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"queryStringParameters"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;responseJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"statusCode"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"200"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JSONException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Send numbers to be added on URL parameters a &amp;amp; b."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;responseJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"statusCode"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"400"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Assemble the response.&lt;/span&gt;
    &lt;span class="n"&gt;responseJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;responseJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"headers"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headerJson&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;OutputStreamWriter&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OutputStreamWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputStream&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;responseJson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unit tests are an important part of a codebase, and this tutorial wouldn’t be
complete without tests for the code we modified. If we run our unit tests now,
they’ll fail. It is easy for us to write unit tests to ensure that our code will
work when it comes time to deploy. We’ll unit test the public &lt;code class="language-plaintext highlighter-rouge"&gt;handleRequest()&lt;/code&gt;
method by mocking the input and output streams with byte array streams. We’ll
also test a request that’s missing some parameters. Again, the framework to get
this started comes with the seed project, so we only have to change a little
code.&lt;/p&gt;

&lt;div class="language-java highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testHandleRequest&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;InputStream&lt;/span&gt; &lt;span class="n"&gt;lambdaRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ByteArrayInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"{\"queryStringParameters\":{\"a\":2,\"b\":3}}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;ByteArrayOutputStream&lt;/span&gt; &lt;span class="n"&gt;lambdaResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ByteArrayOutputStream&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handleRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lambdaRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lambdaResponse&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;byteArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lambdaResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toByteArray&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"{\"headers\":{\"Content-Type\":\"application/json\"},\"body\":\"{\\\"result\\\":5}\",\"statusCode\":\"200\"}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byteArray&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testBadRequest&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;InputStream&lt;/span&gt; &lt;span class="n"&gt;lambdaRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ByteArrayInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"{\"queryStringParameters\":{\"a\":2}}"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;ByteArrayOutputStream&lt;/span&gt; &lt;span class="n"&gt;lambdaResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ByteArrayOutputStream&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handleRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lambdaRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lambdaResponse&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;byteArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lambdaResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toByteArray&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"{\"headers\":{\"Content-Type\":\"application/json\"},\"body\":\"{\\\"message\\\":\\\"Send numbers to be added on URL parameters a &amp;amp; b.\\\",\\\"status\\\":\\\"error\\\"}\",\"statusCode\":\"400\"}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byteArray&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="package-and-deploy-the-lambda-application"&gt;Package and Deploy the Lambda Application&lt;/h2&gt;

&lt;p&gt;Our tests are passing! Let’s package the application into a deployable jar. This
is easy - just use the Maven package step (&lt;code class="language-plaintext highlighter-rouge"&gt;mvn package&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;After creating the jar, deploy it to AWS:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Sign in to the &lt;a href="https://console.aws.amazon.com/console/home"&gt;AWS Console&lt;/a&gt; and
navigate to &lt;a href="https://console.aws.amazon.com/lambda/home?region=us-east-1"&gt;AWS
Lambda&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Hit the “Create Function” button.&lt;/li&gt;
  &lt;li&gt;Choose “Author from Scratch”.&lt;/li&gt;
  &lt;li&gt;Add a trigger, and select “API Gateway” as the trigger mechanism.&lt;/li&gt;
  &lt;li&gt;Name your API Gateway. Leave the deployment stage at “prod”, and select an
“Open” security mechanism for now.&lt;/li&gt;
  &lt;li&gt;Give your new Lambda function a name (like “Addition Lambda”) and
description. Make sure to choose “Java 8” as the runtime.&lt;/li&gt;
  &lt;li&gt;Use the upload button to upload a jar, and upload
“aws-lambda-java-template-0.0.1.jar” (or similar if you renamed your project)
from the &lt;code class="language-plaintext highlighter-rouge"&gt;target&lt;/code&gt; folder.&lt;/li&gt;
  &lt;li&gt;Enter &lt;code class="language-plaintext highlighter-rouge"&gt;at.goosefraba.aws.lambda.template.Application&lt;/code&gt; (or similar if you
renamed your project) as the handler.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create a new role for your lambda function from an existing template. “Basic
Edge Lambda permissions” should be sufficient.
  &lt;img alt="AWS Lambda Configuration" src="https://www.mikekasberg.com/images/aws-lambda-howto/BasicInfo.png" /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Hit the “Create Function” button to finish creating your function.&lt;/li&gt;
  &lt;li&gt;That’s it! You should see a public URL under your API Gateway. Let’s use this
URL to test our function.
  &lt;img alt="AWS Lambda API Config" src="https://www.mikekasberg.com/images/aws-lambda-howto/GatewayConfig.png" /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can see our function work by visiting the public URL and providing &lt;code class="language-plaintext highlighter-rouge"&gt;a&lt;/code&gt; and
&lt;code class="language-plaintext highlighter-rouge"&gt;b&lt;/code&gt; as URL parameters.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Running API" src="https://www.mikekasberg.com/images/aws-lambda-howto/API-Test.png" /&gt;&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Fri, 01 Sep 2017 07:15:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/08/31/how-to-deploy-aws-lambda.html</guid></item><item><title>EuroScipy 2017</title><link>https://bastibe.de/2017-09-01-euroscipy.html</link><description>&lt;p&gt;The second conference I attended this year was the &lt;a href="https://www.euroscipy.org/2017/"&gt;EuroScipy 2017&lt;/a&gt; in Erlangen. I gave a &lt;a href="https://www.youtube.com/watch?v=mc8ru37dwf8"&gt;Talk about Audio in Python&lt;/a&gt; and a &lt;a href="https://youtu.be/qTgk2DUM6G0?t=10m15s"&gt;Lightning Talk about my Python/Matlab bridge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My most striking impression of EuroScipy is that every person I talked to was working on something interesting, and could talk about his/her topic clearly and with enthusiasm. This mirrors my feelings from last year's Chaos Communication Congress, where the short scientific section stood out for its clarity and passion. I also enjoyed the fact that attendees were international and diverse, and exuded a heart-warming sense of community.&lt;/p&gt;
&lt;p&gt;Even though each scientific discipline has their own data sets, features, and models, everyone seemed to use a common set of methods (statistics, signal processing, machine learning) for working with that data. And, absolutely everybody used &lt;a href="http://jupyter.org/"&gt;Jupyter Notebooks&lt;/a&gt; for tutorials and teaching, and almost all data analyses were done in &lt;a href="http://pandas.pydata.org/"&gt;Pandas&lt;/a&gt;. This is particularly heartening since these technologies are geared towards reproducible research and open data.&lt;/p&gt;
&lt;p&gt;The hot topic of the conference clearly was machine learning and neural networks. However, the current confusion of competing frameworks and network architectures does not seem to be a good long-term solution. I hope that this ecosystem will eventually reach its NumPy moment, and collapse into a single, unified package. Then, neural networks might find their place as just another machine learning method with a few reusable parametrized prototype implementations in scikit-learn. Tools like &lt;a href="https://keras.io/"&gt;Keras&lt;/a&gt; look like good steps towards this goal.&lt;/p&gt;
&lt;p&gt;Finally, there was a lot of talk about “the reproducibility crisis” in science, and possible steps to improve the scientific process. In particular, I learned that it is absolutely necessary to not look at your test data before the final evaluation, to avoid overfitting your brain. You need to split your data into a development set for training, a validation set for parameter tuning, and a totally separate evaluation set for the final evaluation. In a similar way, it is important to state your hypotheses &lt;em&gt;in writing&lt;/em&gt; before you test them, to avoid “HARKing” (Hypothesis After the Results are Known; aka “Noise Mining”, “P-Hacking”, or “Procedural Overfitting”). I dearly hope that &lt;a href="https://cos.io/rr/"&gt;Registered Reports&lt;/a&gt; will catch on, and absolve us from these all too human biases.&lt;/p&gt;
&lt;p&gt;In conclusion, EuroScipy 2017 was a ton of fun, and educational in many ways that I did not expect. If you are a scientific programmer, or if you maintain a scientific Python module, or if you are plain interested in scientific Python, I can highly recommend going to EuroScipy next year.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Fri, 01 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-09-01-euroscipy.html</guid></item><item><title>So why write a blog?</title><link>https://daniel.do/article/so-why-write-a-blog</link><description>I want to share my knowledge and help others the way people helped me.</description><author>Daniel Immke</author><pubDate>Fri, 01 Sep 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/so-why-write-a-blog</guid></item><item><title>Django’s Request-Response Cycle</title><link>https://nitinnain.com/djangos-request-response-cycle/</link><description>Understanding the Request-Response Cycle is a crucial step in setting up for any WebServer. An example of the request-response cycle is when you &amp;#8220;request&amp;#8221; a web page by entering a URL in your browser and a web server sends a web page as &amp;#8216;response&amp;#8217; to your browser. Of course, there&amp;#8217;re usually several HTTP requests that [&amp;#8230;]</description><author>Nitin Nain</author><pubDate>Wed, 30 Aug 2017 17:31:52 GMT</pubDate><guid isPermaLink="true">https://nitinnain.com/djangos-request-response-cycle/</guid></item><item><title>Flash Boys, a short review</title><link>https://faingezicht.com/articles/2017/08/30/flash/</link><description>If you've ever taken an economics class, you probably know about &lt;a href="http://www.investopedia.com/terms/a/arbitrage.asp"&gt;arbitrage&lt;/a&gt;: exploiting the price differences of an asset on different markets by buying low, selling high, and pocketing the difference. I recently finished reading Michael Lewis' _&lt;a href="https://en.wikipedia.org/wiki/Flash_Boys"&gt;Flash Boys&lt;/a&gt;_, a book that sheds light on the many faces of arbitrage in the 21st century. _Flash Boys_ is a story about the extent to which Wall Street banks, hedge funds, and other financial institutions apply high frequency trading (HFT) techniques to gain an edge over other players in the most competitive financial markets.

The book tells three separate, tangentially related stories. First, the story of how one unassuming trader - Brad Katsuyama - observed the irregularities that big players caused on the stock market, and what he did about it. Katsuyama left his job at the Royal Bank of Canada to start &lt;a href="https://www.iextrading.com/"&gt;IEX&lt;/a&gt;, an exchange with built-in delays that would guarantee a level playing field for all market participants. His story takes up the bulk of the book. Second, the story of Sergey Aleynikov, the Wall Street programmer who was prosecuted for stealing trade secrets (aka, copying code) from his ex-employer, Goldman Sachs. Lewis' _Vanity Fair_ &lt;a href="https://www.vanityfair.com/news/2013/09/michael-lewis-goldman-sachs-programmer"&gt;profile of Aleynikov&lt;/a&gt; is worth reading on its own. Lastly, the book discusses &lt;a href="https://en.wikipedia.org/wiki/Spread_Networks"&gt;Spread Networks&lt;/a&gt; and its infamous fiber optic cable. Running from New York to Chicago, Spread's line promised to shave off fractions of a second from each transaction, providing those willing to pay for it with a minuscule but significant advantage. By braiding these three narratives, Lewis provides the reader with a set of broad explanations of the complexity of modern finance, and the peculiarities of the policy and technological decisions that got us where we are.

The book is well written, very entertaining, and extremely controversial in the finance world. A lot has been said about the objectivity and bias of Lewis' portrayal of the high frequency traders, and I'm not going to try to defend or deny either view in this post. Instead, I'll try to summarize what I thought were the most interesting aspects.

#### HFT is a bad name
If there was one thing I learned from reading this book, it was that HFT is an awfully named concept. As a software engineer with a degree in economics you'd think I'd know better, but until now I really thought that HFT stood for making _many_ trades, as the "high frequency" would imply. However, the reality is that HFT is not about the _quantity_ of trades, but making higher _quality_ trades by capitalizing on faster assymetric access to information, higher precision, and extremely low latency decision making, to realize gains. The high frequency does not refer to the trades, but to the granularity of the data in play.

#### Counterintuitive Game Theory
In one of the scenes, there is a discussion about Spread Network's pricing. When asking the big banks how much they'd be willing to pay, the buyers tried to negotiate for a higher price! This seems counter intuitive, but a _"13.10-millisecond round trip between New York and Chicago"_ is only worth it if you're the only one who can exploit it, so you'd better make sure you're the only one able to pay for it before you pay for it.

#### Waste
&gt; “The best minds of my generation are thinking about how to make people click ads.”
&gt;
&gt;-Jeff Hammerbacher[^1]

Or, if you are to believe _Flash Boys_, the best financial engineers of our generation are thinking about how to scalp a penny per share by being a microsecond faster than the rest. Whether HFT provides real value to the market &lt;a href="https://noahpinionblog.blogspot.com/2014/04/no-one-really-knows-if-hft-is-good-or.html"&gt;is unclear&lt;/a&gt;, but I am certain that whatever value it provides is less than the input cost of building the necessary infrastructure for it. Not too long ago, the stock market operated in 1/16th of a dollar, and things were just fine. The added precision gained by accurately pricing to the penny by the microsecond is, in my view, not worth it.

#### Front Running
Traditionally, a broker could profit by making trades based on the knowledge of their clients' pending orders - &lt;a href="http://www.investopedia.com/terms/f/frontrunning.asp"&gt;front running&lt;/a&gt; their own books. While unethical, the practice seems to be quite common. Katsuyama's grand discovery was that the HFT firms had come up with a new way to do this.

![HFT front running](https://cdn.faingezicht.com/HFT.png)
&lt;small&gt; Image taken from &lt;a href="https://en.wikipedia.org/wiki/THOR_(trading_platform"&gt;Wikipedia&lt;/a&gt;)&lt;/small&gt;

Since information reaches different exchanges at different times, a fast enough player could see that an order coming to exchange A would only be partially fulfilled. By assuming the parallel order would reach exchange B next, said player could use the information from the trade in exchange A to place the opposite end of the trade at a higher price in B, and pocket that spread. By timing when orders were routed to each exchange, Katsuyama's team could work around this phantom liquidity, and get the securities they wanted at the advertised prices.

#### Fake Orders and Complexity
A corollary of the above front running example is that HFTs require knowledge and decision making power to be as close as possible to each exchange. The orders on the other side of the trades Katsuyama and team were missing were only meant to probe the market. They were other investors' traps to gain information about their intentions, and not at all to be traded.

The orders at A were placed knowing they'd lose money, but would risklessly get them back trading in B.

For this added complexity, Lewis blames "Reg NMS," an SEC directive that intended to ensure the buyer gets the "best available price" from a consolidated "national best bid and offer" (NBBO) feed. Since centralizing said feed takes time, the HFTs could capitalize on that added latency to make their own guesses as to what the NBBO will be before the "real" prices were ready. Thus, the traders were economically incentivized to add direct links to all the exchanges, and once those were in place, they could have an inside view of the trades before anyone else.

#### The Victims
One thing that Lewis seems to skip over is the fact that the average retail investor is not really affected by high frequency trading, or at least not directly. I presume the book is fuzzy on this on purpose, to make the reader feel outraged about mom and pop getting screwed by the big banks.

However, if you're buying 100 shares of Apple on E*TRADE, no one will front run you, and your trade will probably be filled just fine[^2]. If you're buying into an ETF, then sure, you might be losing a few pennies to the dark pools via your broker, but then we're talking about the big boys fighting each other over those pennies on extremely large volume trades. Why your broker still thinks that being in a dark pool, and trusting their owners, is a good call is a question I have  answers for.

--

Anyway, go read it. The interconnectedness of all these auto-triggering algorithms lead to strange places, and learning a bit about how these self-reinforcing feedback loops work was definitely worthwhile. If anything, it surely showed me how much more I need to learn about how markets work.

---
&lt;small&gt;&lt;em&gt;Photo: &lt;a href="https://www.flickr.com/photos/132084522@N05/17086570218/"&gt;"Charging Bull - New York City"&lt;/a&gt; by Sam Valadi, taken from Flickr.&lt;/em&gt;&lt;/small&gt;

[^1]: &lt;a href="https://www.bloomberg.com/news/articles/2011-04-14/this-tech-bubble-is-different"&gt;This Tech Bubble Is Different&lt;/a&gt;, by Ashlee Vance
[^2]: Matt Levine's &lt;a href="https://www.bloomberg.com/news/articles/2016-10-12/beyond-flash-boys-matt-levine-interviews-iex-s-brad-katsuyama"&gt;interview with Katsuyama&lt;/a&gt; has a section on this.</description><author>Avy Faingezicht</author><pubDate>Wed, 30 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/08/30/flash/</guid></item><item><title>Change prompt for virtualenv</title><link>https://www.wints.org/notes/2017.08.30/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I use &lt;a href="https://virtualenv.pypa.io/en/stable/"&gt;virutalenv&lt;/a&gt; and &lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/"&gt;virtualenvwrapper&lt;/a&gt; tomanage my development environments. Virtualenvwrapper consolidates all your virtualenvs into a single location, and can link a directory to a virtualenv.
Once in a while, I need to change the name of my repo and/or virtual environment. This means I have to change a bunch of other stuff.&lt;/p&gt;
&lt;h5 id="how-to"&gt;How To &lt;a href="#how-to"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;If the project directory is moved/changed/renamed, modify the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In the virtualenvs directory (usually ~/.virtualenvs/&amp;lt;virtualenv_name&amp;gt;) there is a &amp;lsquo;.project&amp;rsquo; file. Modify the path here to get the &lt;em&gt;workon&lt;/em&gt; command to work correctly.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Wed, 30 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.08.30/</guid></item><item><title>Making a Mailing List for a Jekyll Blog Using Sendy</title><link>https://www.hallada.net/2017/08/30/making-mailing-list-jekyll-blog-using-sendy.html</link><description>&lt;p&gt;When my beloved &lt;a href="https://en.wikipedia.org/wiki/Google_Reader"&gt;Google Reader&lt;/a&gt; was
discontinued in 2013, I stopped regularly checking RSS feeds. Apparently, &lt;a href="https://trends.google.com/trends/explore?date=all&amp;amp;q=rss"&gt;I am
not alone&lt;/a&gt;. It seems
like there’s a new article every month arguing either that &lt;a href="https://hn.algolia.com/?q=&amp;amp;query=rss%20dead&amp;amp;sort=byPopularity&amp;amp;prefix&amp;amp;page=0&amp;amp;dateRange=all&amp;amp;type=story"&gt;RSS is dead or RSS
is not dead
yet&lt;/a&gt;.
Maybe RSS will stick around to serve as a cross-site communication backbone, but
I don’t think anyone will refute that RSS feeds are declining in consumer use.
Facebook, Twitter, and other aggregators are where people really go. However, I
noticed that I still follow some small infrequent blogs through mailing lists
that they offer. I’m really happy to see an email sign up on blogs I like,
because it means I’ll know when they post new content in the future. I check my
email regularly unlike my RSS feeds.
&lt;!--excerpt--&gt;&lt;/p&gt;

&lt;p&gt;Even though I’m sure my blog is still too uninteresting and unheard of to get
many signups, I still wanted to know what it took to make a blog mailing list.
RSS is super simple for website owners, because all they need to do is dump all
of their content into a specially formatted XML file, host it, and let RSS
readers deal with all the complexity. In my blog, &lt;a href="https://github.com/thallada/thallada.github.io/blob/master/feed.xml"&gt;I didn’t even need a
Jekyll
plugin&lt;/a&gt;.
Email is significantly more difficult. With email, the website owner owns more
of the complexity. And, spam filters make it unfeasible to roll your own email
server. A couple people can mark you as spam, and BAM: now you are blacklisted
and you have to move to a new IP address. This is why most people turn to a
hosted service like &lt;a href="https://mailchimp.com/"&gt;Mailchimp&lt;/a&gt;. Though, I was
dissatisfied with that because of the &lt;a href="https://mailchimp.com/pricing/"&gt;high costs and measly free
tier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/ses/"&gt;Amazon Simple Email Service (SES)&lt;/a&gt; deals with all
the complexity of email for you and is also
&lt;a href="https://aws.amazon.com/ses/pricing/"&gt;cheap&lt;/a&gt;. In fact, it’s free unless you have
more than 62,000 subscribers or post way more than around once a month, and even
after that it’s a dime for every 1,000 emails sent. Frankly, no one can really
compete with what Amazon is offering here.&lt;/p&gt;

&lt;p&gt;Okay, so that covers sending the emails, but what about collecting and storing
subscriptions? SES doesn’t handle any of that. I searched around a long time for
something simple and free that wouldn’t require me setting up a server &lt;sup id="fnref:1"&gt;&lt;a class="footnote" href="#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;. I
eventually ended up going with &lt;a href="https://sendy.co/"&gt;Sendy&lt;/a&gt; because it looked like
a well-designed product exactly for this use case that also handled drafting
emails, email templates, confirmation emails, and analytics. It costs a one-time
fee of $59 and I was willing to fork that over for quality software. Especially
since most other email newsletter services require some sort of monthly
subscription that scales with the number of emails you are sending.&lt;/p&gt;

&lt;p&gt;Unfortunately, since Sendy is self-hosted, I had to add a dynamic server to my
otherwise completely static Jekyll website hosted for free on &lt;a href="https://pages.github.com/"&gt;Github
Pages&lt;/a&gt;. You can put Sendy on pretty much anything
that runs PHP and MySQL including the cheap &lt;a href="https://aws.amazon.com/ec2/instance-types/"&gt;t2.micro Amazon EC2 instance
type&lt;/a&gt;. If you are clever, you might
find a cheaper way. I already had a t2.medium for general development,
tinkering, and hosting, so I just used that.&lt;/p&gt;

&lt;p&gt;There are many guides out there for setting up MySQL and Apache, so I won’t go
over that. But, I do want to mention how I got Sendy to integrate with
&lt;a href="https://nginx.org/en/"&gt;nginx&lt;/a&gt; which is the server engine I was already using. I
like to put separate services I’m running under different subdomains of
my domain hallada.net even though they are running on the same server and IP
address. For Sendy, I chose &lt;a href="http://list.hallada.net"&gt;list.hallada.net&lt;/a&gt; &lt;sup id="fnref:2"&gt;&lt;a class="footnote" href="#fn:2" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;.
Setting up another subdomain in nginx requires &lt;a href="https://askubuntu.com/a/766369"&gt;creating a new server
block&lt;/a&gt;. There’s &lt;a href="https://gist.github.com/refringe/6545132"&gt;a great Gist of a config for
powering Sendy using nginx and
FastCGI&lt;/a&gt;, but I ran into so many
issues with the subdomain that I decided to use nginx as a proxy to the Apache
mod_php site running Sendy. I’ll just post my config here:&lt;/p&gt;

&lt;div class="language-nginx highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;list.hallada.net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html/sendy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/l/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/l/([a-zA-Z0-9/]+)&lt;/span&gt;$ &lt;span class="n"&gt;/l.php?i=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/t/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/t/([a-zA-Z0-9/]+)&lt;/span&gt;$ &lt;span class="n"&gt;/t.php?i=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/w/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/w/([a-zA-Z0-9/]+)&lt;/span&gt;$ &lt;span class="n"&gt;/w.php?i=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/unsubscribe/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/unsubscribe/(.*)&lt;/span&gt;$ &lt;span class="n"&gt;/unsubscribe.php?i=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/subscribe/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/subscribe/(.*)&lt;/span&gt;$ &lt;span class="n"&gt;/subscribe.php?i=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8080/sendy/&lt;/span&gt;&lt;span class="p"&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;Basically, this proxies all of the requests through to Apache which I configured
to run on port 8080 by changing the &lt;code class="language-plaintext highlighter-rouge"&gt;Listen&lt;/code&gt; directive in
&lt;code class="language-plaintext highlighter-rouge"&gt;/etc/apache2/ports.conf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I also had to add &lt;code class="language-plaintext highlighter-rouge"&gt;RewriteBase /sendy&lt;/code&gt; to the end of the &lt;code class="language-plaintext highlighter-rouge"&gt;.htcaccess&lt;/code&gt; file in
the sendy directory (which, for me, was in &lt;code class="language-plaintext highlighter-rouge"&gt;/var/www/html/sendy&lt;/code&gt;). This
basically forces Sendy to use urls that start with &lt;code class="language-plaintext highlighter-rouge"&gt;http://list.hallada.net&lt;/code&gt;
instead of &lt;code class="language-plaintext highlighter-rouge"&gt;http://list.hallada.net/sendy&lt;/code&gt; which I thought was redundant since I
am dedicating the whole subdomain to sendy.&lt;/p&gt;

&lt;p&gt;A perplexing issue I ran into was that Gmail accounts were completely dropping
(not even bouncing!) any emails I sent to them if I used my personal email
&lt;code class="language-plaintext highlighter-rouge"&gt;tyler@hallada.net&lt;/code&gt; as the from address. I switched to &lt;code class="language-plaintext highlighter-rouge"&gt;tyhallada@gmail.com&lt;/code&gt; for
the from address and emails went through fine after that &lt;sup id="fnref:4"&gt;&lt;a class="footnote" href="#fn:4" rel="footnote"&gt;3&lt;/a&gt;&lt;/sup&gt;. &lt;a href="https://forums.aws.amazon.com/thread.jspa?messageID=802461&amp;amp;#802461"&gt;The issue seems
unresolved&lt;/a&gt;
as of this post.&lt;/p&gt;

&lt;p&gt;Lastly, I needed to create a form on my website for readers to sign up for the
mailing list. Sendy provides the HTML in the UI to create the form, which I
&lt;a href="https://github.com/thallada/thallada.github.io/blob/master/_includes/mail-form.html"&gt;tweaked a
little&lt;/a&gt;
and placed in a &lt;a href="https://jekyllrb.com/docs/includes/"&gt;Jekyll includes template
partial&lt;/a&gt; that I could include on both the
post layout and the blog index template. I refuse to pollute the internet with
yet another annoying email newsletter form that pops up while you are trying to
read the article, so you can find my current version at the bottom of this
article where it belongs &lt;sup id="fnref:5"&gt;&lt;a class="footnote" href="#fn:5" rel="footnote"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;All in all, setting up a mailing list this way wasn’t too bad except for the part
where I spent way too much time fiddling with nginx configs. But, I always do
that, so I guess that’s expected.&lt;/p&gt;

&lt;p&gt;As for the content of the newsletter, I haven’t figured out how to post the
entirety of a blog post into the HTML format of an email as soon as I commit a
new post yet. So, I think for now I will just manually create a new email
campaign in Sendy (from an email template) that will have a link to the new
post, and send that.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;

      &lt;p&gt;It would be interesting to look into creating a &lt;a href="https://www.google.com/forms/about/"&gt;Google
Form&lt;/a&gt; that submits rows to a &lt;a href="https://www.google.com/sheets/about/"&gt;Google
Sheet&lt;/a&gt; and then triggering a &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS
Lambda&lt;/a&gt; service that iterates over the rows
using something like &lt;a href="https://developers.google.com/sheets/api/quickstart/python"&gt;the Google Sheets Python
API&lt;/a&gt; and sending
an email for every user using the &lt;a href="http://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-api.html"&gt;Amazon SES
API&lt;/a&gt;
(&lt;a href="https://github.com/pankratiev/python-amazon-ses-api"&gt;python-amazon-ses-api&lt;/a&gt;
might also be useful there). &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 ran into a hiccup &lt;a href="http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domain-procedure.html"&gt;verifying this domain for Amazon
SES&lt;/a&gt;
using the &lt;a href="https://www.namecheap.com/"&gt;Namecheap&lt;/a&gt; advanced DNS settings
because it only allowed me to set up one MX record, but I already had one
for my root hallada.net domain that I needed. So, I moved to &lt;a href="https://aws.amazon.com/route53/"&gt;Amazon’s Route
53&lt;/a&gt; instead &lt;sup id="fnref:3"&gt;&lt;a class="footnote" href="#fn:3" rel="footnote"&gt;5&lt;/a&gt;&lt;/sup&gt; which made setting up the
&lt;a href="http://docs.aws.amazon.com/ses/latest/DeveloperGuide/easy-dkim.html"&gt;DKIM
verification&lt;/a&gt;
really easy since Amazon SES gave a button to create the necessary DNS
records directly in my Route 53 account. &lt;a class="reversefootnote" href="#fnref:2"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:4"&gt;
      &lt;p&gt;Obviously a conspiracy by Google to force domination of Gmail. &lt;a class="reversefootnote" href="#fnref:4"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:5"&gt;
      &lt;p&gt;Yes, I really hate those pop-ups. &lt;a class="reversefootnote" href="#fnref:5"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:3"&gt;

      &lt;p&gt;As &lt;a href="https://www.washingtonpost.com/business/is-amazon-getting-too-big/2017/07/28/ff38b9ca-722e-11e7-9eac-d56bd5568db8_story.html"&gt;Amazon continues its plan for world
domination&lt;/a&gt;
it appears I’m moving more and more of my personal infrastructure over to
Amazon as well… &lt;a class="reversefootnote" href="#fnref:3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>Tyler Hallada - Blog</author><pubDate>Wed, 30 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hallada.net/2017/08/30/making-mailing-list-jekyll-blog-using-sendy.html</guid></item><item><title>Send a fax from the command line with Python and Phaxio</title><link>https://sean.lane.sh/posts/2017/08/Send-a-fax-from-the-command-line-with-Python-and-Phaxio/</link><description>&lt;p&gt;If you want to send a simple fax quickly, cheaply, and painlessly, Phaxio and Python make a nice combo. Below is a litte script that I wrote, based on this &lt;a href="https://www.petekeen.net/command-line-faxing"&gt;Ruby script by Pete Keen&lt;/a&gt; that is slightly out of date. There are Phaxios Python libraries, but I ran into a couple issues, and this seems to be the most brain-dead simple solution. Pros: No external dependencies. Cons: It uses the &lt;code&gt;shell=True&lt;/code&gt; parameter for &lt;code&gt;subprocess.call&lt;/code&gt;, but that shouldn&amp;rsquo;t be an issue since you&amp;rsquo;re only using this to send a quick fax at 2 AM and you don&amp;rsquo;t want to pay UPS/FedEx/whomever too much money for that privilege tomorrow, right?&lt;/p&gt;
&lt;p&gt;Note that I&amp;rsquo;m not affiliated with Phaxio in any way, it just happens to be late, I needed to send a fax, and they checked all the right boxes. I stumbled on Phaxio, but for someone just wanting to send a quick fax once every year or so, it&amp;rsquo;s great. Pricing is about $0.07 a page (and I received $1.00 account credit just for signing up at the time of writing this), so it&amp;rsquo;s perfect for my use case.&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Sign up for an account with &lt;a href="https://www.phaxio.com/"&gt;Phaxio: https://www.phaxio.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Get your API Keys: &lt;a href="https://console.phaxio.com/api_credentials"&gt;Phaxio API Credentials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Put them into the script below (You can also use the Test keys to make sure this works before trying too.)&lt;/li&gt;
&lt;li&gt;Run the script, for example, if I saved the script to &lt;code&gt;fax.py&lt;/code&gt;, I&amp;rsquo;m sending to Tommy Tutone, and my file to send is &lt;code&gt;letter.pdf&lt;/code&gt;, I would use the following: &lt;code&gt;./fax.py +15558675309 /path/to/letter.pdf&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;from&lt;/span&gt; subprocess &lt;span style="color: #f92672;"&gt;import&lt;/span&gt; call
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;import&lt;/span&gt; sys
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;if&lt;/span&gt; len(sys&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;argv) &lt;span style="color: #f92672;"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;2&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	print(&lt;span style="color: #e6db74;"&gt;"Usage: send_fax NUMBER FILENAME..."&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	exit(&lt;span style="color: #f92672;"&gt;-&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;number &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; sys&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;argv[&lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;]   
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;api_key &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;'put_api_key_here'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;api_secret &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;'put_api_secret_here'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;command_args &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  &lt;span style="color: #e6db74;"&gt;"curl"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  &lt;span style="color: #e6db74;"&gt;"https://api.phaxio.com/v2/faxes"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  &lt;span style="color: #e6db74;"&gt;"-u '&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;{}&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;:&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;{}&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'"&lt;/span&gt;&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;format(api_key, api_secret),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  &lt;span style="color: #e6db74;"&gt;"-F 'to=&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;{}&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'"&lt;/span&gt;&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;format(number)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;for&lt;/span&gt; file &lt;span style="color: #f92672;"&gt;in&lt;/span&gt; sys&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;argv[&lt;span style="color: #ae81ff;"&gt;2&lt;/span&gt;:]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	command_args&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;append(&lt;span style="color: #e6db74;"&gt;"-F 'file=@&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;{}&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'"&lt;/span&gt;&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;format(file))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;call(&lt;span style="color: #e6db74;"&gt;' '&lt;/span&gt;&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;join(command_args), shell&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script can be found in this GitHub Gist here: &lt;a href="https://gist.github.com/seanlane/67504bf39696de8c0bc88ad89844f9df"&gt;https://gist.github.com/seanlane/67504bf39696de8c0bc88ad89844f9df&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to fork it and suggest improvements.&lt;/p&gt;</description><author>Posts on Sean Lane</author><pubDate>Wed, 30 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2017/08/Send-a-fax-from-the-command-line-with-Python-and-Phaxio/</guid></item><item><title>So you completed the official React tutorial. What's next?</title><link>https://goshacmd.com/next-steps-official-react-tutorial/</link><author>Gosha Spark</author><pubDate>Tue, 29 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/next-steps-official-react-tutorial/</guid></item><item><title>xmlstarlet, xpath, and confusion</title><link>https://rjp.is/blogging/posts/what-am-i-doing-wrong/</link><description>In which we fail to account for XML namespaces.</description><author>infrequent oscillations</author><pubDate>Mon, 28 Aug 2017 12:06:08 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/what-am-i-doing-wrong/</guid></item><item><title>I think it’s worth noting that in order to use await, the function directly enclosing the test code…</title><link>https://olshansky.info/posts/2017-08-27-i-think-its-worth-noting-that-in-order-to-use-await-the-function-directly-enclosing-the-test-code/</link><description>Helpful resource: https://stackoverflow.com/questions/42299594/await-is-a-reserved-word-error-inside-async-function.</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 28 Aug 2017 08:14:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-08-27-i-think-its-worth-noting-that-in-order-to-use-await-the-function-directly-enclosing-the-test-code/</guid></item><item><title>Behind the Scenes at a VC Fund, Part 2: Helping Founders and Time Allocation</title><link>https://www.codingvc.com/p/behind-the-scenes-at-a-vc-fund-part-2-helping-founders-and-time-allocation</link><description>VCs have 3 principal jobs: picking startups to invest in, helping startups after investing, and raising capital for investing.</description><author>Coding VC</author><pubDate>Mon, 28 Aug 2017 01:18:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/behind-the-scenes-at-a-vc-fund-part-2-helping-founders-and-time-allocation</guid></item><item><title>Game of Thrones: Season 7</title><link>https://olshansky.info/tv/game_of_thrones_season_7/</link><description>Olshansky's review of Game of Thrones: Season 7</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 27 Aug 2017 16:31:08 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/game_of_thrones_season_7/</guid></item><item><title>Tabby's Star</title><link>https://walkabout165.blogspot.com/2017/08/tabbys-star.html</link><description>I've found the discussion and speculation around Tabby's Star intriguing. This is the one where a near-steady ~ 0.3 - 2% dimming per year is being observed, with intermittent, near instantaneous 1%-22% dips in brightness being observed anywhere from a month to a couple years apart. &amp;nbsp;Many theories have been posed and many debunked. &amp;nbsp;My favorite theory / debunk combination is that there is a vessel approaching us from Tabby's star; however the parallax as observed across the span of Earth's orbit would show the "vessel" only intermittently occluding the Tabby's Star's disk as seen from Earth. (Or otherwise we have to imagine an "impossibly" sized vessel, but more realistically perhaps one leaving a very largely expanding trail of exhaust behind it, especially since the effects would be cumulative along a straight-line path towards us . . . )&lt;br /&gt;
&lt;br /&gt;
So I decided to imagine another theory that i've since seen only a little discussion of - that of a large amount of interstellar traffic - e.g. commercial traffic, between two stars whose joining pathway occludes our observation cone to Tabby's star. &amp;nbsp;Unfortuntely I don't have a map of the stars in our view to Tabby's Star (i e in the constellation Cygnus or its neighbors) to be able to propose which two stars could be playing that role. Or perhaps Tabby's Star itself is one terminus to that path (or even a central, i.e. transhipment, hub to many stars?) .&lt;br /&gt;
&lt;br /&gt;
The traffic could simply be so voluminous in nature (or emit sufficient exhaust as in the "approaching vessel" case) as to measurably occlude the light from Tabby's Star. &amp;nbsp;The steady increase in dimming could be attributed to the same kind of typically steadily increasing growth rate of economic flows that we see in simple commerce here on Earth. &amp;nbsp;Intermittent significant dips could be due to whatever the interstellar equivalent is of the odd freight train passing through, as contrasted with the more frequent small truck in this analogy.&lt;br /&gt;
&lt;br /&gt;
What criteria to propose to debunk this theory?</description><author>The Walkabout Blog</author><pubDate>Sun, 27 Aug 2017 11:14:27 GMT</pubDate><guid isPermaLink="true">https://walkabout165.blogspot.com/2017/08/tabbys-star.html</guid></item><item><title>Fascism is bad</title><link>https://faingezicht.com/photos/2017/08/27/sfrally/</link><description>Not sure how we got to a point where the title of this post is not taken as a fact.

Over the last few weeks there was a lot of talk about neo-nazi and fascist sympathizers coming to San Francisco to stage a big rally. Knowing that the Bay Area is very left leaning, it is very likely that the goal of the event was to incite the locals, and to get some favorable sound bites on how there is "violence on both sides," and such. The original protest was meant to be at Crissy Field and after getting some pressure it was demoted to a news conference in Alamo Square Park. The SFPD shut it down, closing the park and putting a big fence around it, so the Patriot Prayer people ended up doing their talk in Pacifica - a small town south of San Francisco.

At the same time, several counter-protests started around the city, and when I heard there was one coming down Mission Street, I knew I had to go photograph it.

One thing that stuck out to me about this protest was that it was really a ton of small protests all joined together: anti-racism, anti-homophobia, anti-gentrification, anti-Islamophobia, and more.</description><author>Avy Faingezicht</author><pubDate>Sun, 27 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/08/27/sfrally/</guid></item><item><title>Web Audio Conference and JavaScript</title><link>https://bastibe.de/2017-08-29-wac-and-javascript.html</link><description>&lt;p&gt;I am not much of a web programmer. I have written the odd website, I have supervised a few student projects, but I have never worked on any nontrivial JavaScript code base. Nevertheless, last week, I attended the &lt;a href="http://wac.eecs.qmul.ac.uk/"&gt;Web Audio Conference 2017&lt;/a&gt; in London. To put it succinctly: The web is home to fascinating people, but the technology is full of problems.&lt;/p&gt;
&lt;p&gt;Those people sure were amazing, though. I talked to a musician/programmer, who spent the last few years writing his own sequencer web app, and did an amazing live performance in his web browser! I witnessed another guy live coding a synthesizer in a web app on stage as a music piece. We attended a gastronomical concert with smartphone-synchronized distributed olfactory and audible experiences. And we played the piano, with each participant controlling one key from his smartphone. It was all truly inspiring!&lt;/p&gt;
&lt;p&gt;All of this was built on JavaScript, however. One musical performance reached its climax when the musician queued too many samples and synthesizers and JavaScript crashed. The crowd cheered, but this still highlights how JavaScript, garbage collection pauses, and heap exhaustion are real problems. And there was not a single talk that did not long for dedicated Audio Workers to fix some of these problems.&lt;/p&gt;
&lt;p&gt;But more than that, I learned that most of these apps have to pile frameworks upon frameworks just to get a simple demo app going. This is inescapable, since JavaScript is just not usable as an application platform without these frameworks. I take this as a warning: One should build a project from scratch every now and then, just to keep a realistic feel of how deep one's technology stack really is.&lt;/p&gt;
&lt;p&gt;All of these people are using JavaScript as an application platform. I would wager that an application platform is basically something like ①: layout, ②: widgets, ③: data bindings, and ④: event handling. If you think about it, JavaScript without libraries currently covers at most ① (CSS) and maybe ② (using HTML Custom Elements), though not at all at the same level as true GUI frameworks such as Qt or Cocoa. For ③ and ④, you have to add something like Ember, React, or Angular. It is strange to me that the JavaScript ecosystem does not seem to gravitate towards integrated frameworks but seems to prefer this wild west of codependent libraries.&lt;/p&gt;
&lt;p&gt;Then again, limitations breed genius, and the limits of the platform no doubt fueled the amazing feats these web audio people pulled off at WAC. It is truly inspiring what miracles dedicated people can pull off if they set their mind on them. And let's not forget that the Web Audio API itself is the work of a single person (per browser) as well.&lt;/p&gt;
&lt;p&gt;So, in summary, I learned a lot at WAC. I learned that web technologies are not ideal as an application platform. I learned that deep framework stacks are not desirable, yet often necessary. But above all, I learned that all this does not stop people from writing astonishing applications with those technologies. More power to the crazy ones!&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Sun, 27 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-08-29-wac-and-javascript.html</guid></item><item><title>Links - August 26, 2017</title><link>https://faingezicht.com/links/2017/08/26/links/</link><description/><author>Avy Faingezicht</author><pubDate>Sat, 26 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/08/26/links/</guid></item><item><title>How Do We Know Methane (CH4) Is Tetrahedral?</title><link>https://www.masterorganicchemistry.com/2017/08/25/how-do-we-know-methane-is-tetrahedral/</link><description>What Do The Valence Electrons Of Carbon Tell Us About The Bonding In CH4? (Hint: since the dipole moment of CH4 is zero, the answer</description><author>Master Organic Chemistry</author><pubDate>Fri, 25 Aug 2017 12:00:51 GMT</pubDate><guid isPermaLink="true">https://www.masterorganicchemistry.com/2017/08/25/how-do-we-know-methane-is-tetrahedral/</guid></item><item><title>The Fourth Turning: An American Prophecy—What the Cycles of History Tell Us About America's Next Rendezvous with Destiny</title><link>https://olshansky.info/book/the_fourth_turning/</link><description>Olshansky's review of The Fourth Turning: An American Prophecy—What the Cycles of History Tell Us About America's Next Rendezvous with Destiny by William Strauss</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 25 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/the_fourth_turning/</guid></item><item><title>Processing custom events in kernel.terminate</title><link>https://jfoucher.com/2017/08/symfony-process-custom-events-in-kernel-terminate.html</link><description>&lt;h3 id="what-is-the-kernelterminate-event"&gt;What is the kernel.terminate event?&lt;/h3&gt;

&lt;p&gt;It is the last event that is triggered in Symfony, just after the response has been sent to the client (only on php-fpm). This means that we can do some heavy lifting here because our response time is not affected. The client gets the response quickly and our processing will occur afterwards.&lt;/p&gt;

&lt;p&gt;The Symfony SwiftMailer bundle does this by default, so we should be ok with emails, but my latest project needs to connect to various APIs on some events, and this takes quite some time.&lt;/p&gt;

&lt;p&gt;In this post I will explain the method I use to make them run in the &lt;code class="language-plaintext highlighter-rouge"&gt;kernel.terminate&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;For a primer about Symfony events, I recommend the &lt;a href="https://symfony.com/doc/current/reference/events.html"&gt;official Symfony documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="custom-events"&gt;Custom events&lt;/h3&gt;

&lt;p&gt;Custom events are trigerred from our own code, generally in the controller, and it goes something like this:&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;&lt;span class="cd"&gt;/** 
* @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface 
*/&lt;/span&gt;
&lt;span class="c1"&gt;//Get the event dispatcher from the container
&lt;/span&gt;
&lt;span class="nv"&gt;$dispatcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'event_dispatcher'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//Create our custom event
&lt;/span&gt;
&lt;span class="nv"&gt;$event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NewUserEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//Dispatch the event
&lt;/span&gt;
&lt;span class="nv"&gt;$dispatcher&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AppEvents&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NEW_USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id="the-event-subscriber"&gt;The event subscriber&lt;/h3&gt;

&lt;p&gt;Then we have an EventSubscriber that will listen to our custom events, in my case it’s called &lt;code class="language-plaintext highlighter-rouge"&gt;ApiSubscriber&lt;/code&gt; and is located in &lt;code class="language-plaintext highlighter-rouge"&gt;src/EventSubscriber&lt;/code&gt;. In this case it listens to two different events: 
&lt;code class="language-plaintext highlighter-rouge"&gt;AppEvents::NEW_USER&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;AppEvents::DELETE_USER&lt;/code&gt;.&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApiSubscriber&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;EventSubscriberInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$container&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;Symfony\Component\DependencyInjection\ContainerInterface&lt;/span&gt; &lt;span class="nv"&gt;$container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$container&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getSubscribedEvents&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="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;AppEvents&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NEW_USER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'newUser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nc"&gt;AppEvents&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;DELETE_USER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'deleteUser'&lt;/span&gt;&lt;span class="p"&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;//...
&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id="configure-the-service"&gt;Configure the service&lt;/h3&gt;

&lt;p&gt;You will notice that I inject the container as it makes it easy to get everything we need, such as parameters or other services.&lt;/p&gt;

&lt;p&gt;Don’t forget to configure the event subscriber in &lt;code class="language-plaintext highlighter-rouge"&gt;app/config/services.yml&lt;/code&gt; like so:&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-yaml"&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
    &lt;span class="na"&gt;api.subscriber&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
        &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AppBundle\EventSubscriber\ApiSubscriber&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
        &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@service_container"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;kernel.event_subscriber&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now our event subscriber is ready for action whenever we trigger the event from our controllers.&lt;/p&gt;

&lt;h3 id="handle-your-custom-event"&gt;Handle your custom event&lt;/h3&gt;

&lt;p&gt;The event handling function is where the magic happens. Say when a new user is created, the &lt;code class="language-plaintext highlighter-rouge"&gt;AppEvents::NEW_USER&lt;/code&gt; is triggered and the &lt;code class="language-plaintext highlighter-rouge"&gt;ApiSubscriber::newUser&lt;/code&gt; function is called.&lt;/p&gt;

&lt;p&gt;Here it is, I’ll explain later&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NewUserEvent&lt;/span&gt; &lt;span class="nv"&gt;$newUserEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the request from our custom event
&lt;/span&gt;
    &lt;span class="nv"&gt;$request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$newUserEvent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Add custom attributes to the request, so we can retrieve them later in the kernel.terminate event
&lt;/span&gt;
    &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$newUserEvent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="s1"&gt;'thing_api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'thing_api_key'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'thing_api_user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'thing_api_user'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="c1"&gt;// Add our custom listener to the kernel.terminate event
&lt;/span&gt;
    &lt;span class="c1"&gt;// We will see later what the createThingOnApi static function looks like
&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'event_dispatcher'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'kernel.terminate'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'createThingOnApi'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// This would also work but is not as clean in my opinion
&lt;/span&gt;
    &lt;span class="c1"&gt;// $this-&amp;gt;container-&amp;gt;get('event_dispatcher')-&amp;gt;addListener('kernel.terminate', function(PostResponseEvent $event) {
&lt;/span&gt;
        &lt;span class="c1"&gt;// Do things on the API
&lt;/span&gt;
    &lt;span class="c1"&gt;// });
&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, from this code it is clear what happens. We first get the request from our custom event, then we set custom attributes on the request (simply because we need to retrieve them later from our static function) and finally we add a new listener (our static function, could also be an anonymous function) to the kernel.terminate event.&lt;/p&gt;

&lt;h3 id="do-the-job"&gt;Do the job&lt;/h3&gt;

&lt;p&gt;The final piece of the puzzle is our &lt;code class="language-plaintext highlighter-rouge"&gt;createThingOnApi&lt;/code&gt; static function that will do the real work.&lt;/p&gt;

&lt;p&gt;Here it is:&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createThingOnApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PostResponseEvent&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRequest&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;attributes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$attrs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"type"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"newUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="c1"&gt;//...
&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nv"&gt;$ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.thing.com/users"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_CUSTOMREQUEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POSTFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'Content-Length: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data_string&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'X-Auth-Key: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$attrs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'thing_api_key'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'X-Auth-User: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$attrs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'thing_api_user'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&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;/figure&gt;

&lt;p&gt;This basically retrives our data from the request attributes, and then make some sort of curl request to an external API.&lt;/p&gt;

&lt;h3 id="all-done-"&gt;All done !&lt;/h3&gt;

&lt;p&gt;Do this and watch your response times go way down (&lt;a href="https://symfony.com/doc/current/components/http_kernel.html#component-http-kernel-kernel-terminate"&gt;only on php-pfm&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I’m not saying the is the best or even the only method to achieve this, just the one I personally use. the alternative would be some sort of mesasge queue, but it still seems like premature optimisation for an app of this size. If you have other options to achieve this, let me know in the comments on HN.&lt;/p&gt;

&lt;h3 id="profiler-results"&gt;Profiler results&lt;/h3&gt;

&lt;p class="image"&gt;&lt;img alt="Profiler results" src="/uploads/2017/08/symfony-kernel.terminate.png" /&gt;&lt;/p&gt;</description><author>Geeky Nuggets</author><pubDate>Fri, 25 Aug 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://jfoucher.com/2017/08/symfony-process-custom-events-in-kernel-terminate.html</guid></item><item><title>Documentation Style Guide</title><link>https://blog.harterrt.com/docs-style-guide.html</link><description>&lt;p&gt;I just wrote up a style guide for our 
&lt;a href="https://docs.telemetry.mozilla.org"&gt;team's documentation&lt;/a&gt;.
The documentation is rendered using Gitbook and hosted on Github Pages.
You can find the 
&lt;a href="https://github.com/mozilla/firefox-data-docs/pull/41"&gt;PR here&lt;/a&gt;
but I figured it's worth sharing here as well.&lt;/p&gt;
&lt;h2 id="style-guide"&gt;Style Guide&lt;/h2&gt;
&lt;p&gt;Articles should be written in
&lt;a href="https://daringfireball.net/projects/markdown/syntax"&gt;Markdown&lt;/a&gt;
(not &lt;a href="http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/"&gt;AsciiDoc&lt;/a&gt;).
Markdown is usually …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 24 Aug 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/docs-style-guide.html</guid></item><item><title>How to create or restore efi partition in ubuntu</title><link>https://shyamjos.com/how-to-restore-or-create-efi-partition-in-ubuntu/</link><description>&lt;h2 class="relative group" id="what-type-of-file-system-is-used-in-efi-partition-"&gt;What Type of file system is used in EFI partition ? &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#what-type-of-file-system-is-used-in-efi-partition-"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;EFI partition in Ubuntu is basically a FAT partition with label &amp;ldquo;EFI&amp;rdquo;&lt;/p&gt;
&lt;h2 class="relative group" id="how-to-create--restore-an-efi-partition-"&gt;How to create / restore an efi partition ? &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#how-to-create--restore-an-efi-partition-"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Just reformat or create a normal FAT file system partition with a size of 512MB (can be any size) and label it as &amp;ldquo;EFI&amp;rdquo;, You can use fdisk command if you are comfortable with cli or you can use gparted tool from a live media of Ubuntu to create new efi partition.&lt;/p&gt;
&lt;h2 class="relative group" id="how-can-i-reinstall-grub-efi-bootloader-after-creating-or-restoring-efi-partition-"&gt;How can I reinstall Grub efi bootloader after creating or restoring efi partition ? &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#how-can-i-reinstall-grub-efi-bootloader-after-creating-or-restoring-efi-partition-"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;After restoring or formatting efi partition your system will not boot since bootloader needs to be reinstalled on the new efi partition, follow this &lt;a href="https://shyamjos.com/reinstall-grub2-efi-bootloader-ubuntu/" rel="noreferrer" target="_blank"&gt;tutorial to reinstall grub efi bootloader in your Ubuntu&lt;/a&gt; system.&lt;/p&gt;</description><author>Shyam Jos</author><pubDate>Thu, 24 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://shyamjos.com/how-to-restore-or-create-efi-partition-in-ubuntu/</guid></item><item><title>How to reinstall grub2 efi bootloader on ubuntu</title><link>https://shyamjos.com/reinstall-grub2-efi-bootloader-ubuntu/</link><description>&lt;p&gt;In this tutorial I will show you how to reinstall grub2 bootloader on a ubuntu system with efi partition.&lt;/p&gt;
&lt;h2 class="relative group" id="boot-from-a-live-usbcd"&gt;Boot from a live usb/cd &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#boot-from-a-live-usbcd"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Boot from the ubuntu live usb/cd and select the option &amp;ldquo;try ubuntu without installing&amp;rdquo;&lt;/p&gt;
&lt;h2 class="relative group" id="check-if-efi-is-enabled-in-bios"&gt;Check if EFI is enabled in bios &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#check-if-efi-is-enabled-in-bios"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Enter below command in terminal\&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ -d /sys/firmware/efi ] &amp;amp;&amp;amp; echo "EFI boot on HDD" || echo "Legacy boot on HDD"
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you see &amp;ldquo;EFI boot on HDD&amp;rdquo; Message then you are already running on efi mode or if you see &amp;ldquo;Legacy boot on HDD&amp;rdquo; message then your system is not running on efi mode, you must change the boot options to efi before proceeding to next step.&lt;/p&gt;
&lt;p&gt;Note: First you have to find the partition name where ubuntu is installed, You can use &amp;ldquo;sudo fdisk -l&amp;rdquo; to list all hard disks and partitions in your computer. In my case /dev/sda is the name of my harddisk, /dev/sda2 is the partition where ubuntu is installed (root partition) and /dev/sda1 was the efi partition.&lt;/p&gt;
&lt;h2 class="relative group" id="mount-and-chroot-into-local-filesystem"&gt;Mount and chroot into local filesystem &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#mount-and-chroot-into-local-filesystem"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Note: You have to replace the sda with device name of your HDD, In most cases it is sda, assuming that you have only one hard disk installed.&lt;/p&gt;
&lt;p&gt;Note: If you get any errors while trying to mount your efi partition (&lt;code&gt;/dev/sda1&lt;/code&gt;), You may need to reformat your efi partition, In case if it got corrupted or if you accidentally formatted it. &lt;a href="https://linuxsuperuser.com/how-to-restore-or-create-efi-partition-in-ubuntu/" rel="noreferrer" target="_blank"&gt;Follow this tutorial to restore or reformat your efi partition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Open terminal and enter below command\&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo mount /dev/sda2 /mnt\
sudo mount /dev/sda1 /mnt/boot/efi\
for i in /dev /dev/pts /proc /sys /run; do sudo mount -B $i /mnt$i; done\
sudo chroot /mnt\
grub-install /dev/sda\
update-grub\
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Important : &lt;em&gt;&lt;strong&gt;use blkid command to check UUID of your efi partition, check if it matches the value in your /etc/fstab entry , otherwise ubuntu will not boot , You may need to update the UUID especially if you have formatted EFI partition . (Eg: sudo blkid /dev/sda1)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it! Now reboot to test the bootloader&lt;/p&gt;</description><author>Shyam Jos</author><pubDate>Thu, 24 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://shyamjos.com/reinstall-grub2-efi-bootloader-ubuntu/</guid></item><item><title>Beer and Probes</title><link>https://blog.harterrt.com/probes.html</link><description>&lt;p&gt;Quick post to clear up some terminology.
But first, an analogy to clear up my thinking:&lt;/p&gt;
&lt;h2 id="analogy"&gt;Analogy&lt;/h2&gt;
&lt;p&gt;Temperature control is a big part of brewing beer.
Throughout the brewing process I use a thermometer
to measure the temperature of the soon-to-be beer.
Because I take several temperature readings throughout the …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Wed, 23 Aug 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/probes.html</guid></item><item><title>Linux Delay Accounting</title><link>https://andrestc.com/post/linux-delay-accounting/</link><description>&lt;p&gt;Ever wondered how long is your program spending while waiting for I/O to finish? Or if it is spending lots
of time while waiting for a turn to run on one of the cpus? Linux provides &lt;a href="https://www.kernel.org/doc/Documentation/accounting/"&gt;delay accounting information&lt;/a&gt; that may help answering these and other questions. Delay information is available for many types of resources:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;waiting for a CPU (while being runnable)&lt;/li&gt;
&lt;li&gt;completion of synchronous block I/O initiated by the task&lt;/li&gt;
&lt;li&gt;swapping in pages&lt;/li&gt;
&lt;li&gt;memory reclaim&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These information is available in nanoseconds, on a per pid/tid basis, and is pretty useful to find out if your system resources are saturated by the number of concurrent tasks running on the machine. You can either: reduce the amount of work being done on the machine by removing unecessary processes or adjust the priority (cpu priority, io priority and rss limit) for important tasks.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Tue, 22 Aug 2017 19:42:26 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/linux-delay-accounting/</guid></item><item><title>Eclipse</title><link>https://faingezicht.com/photos/2017/08/22/eclipse/</link><description>Yesterday morning, instead of going straight to the office, I grabbed my camera and took photos of the skygazers around SoMa. If you were trying to see the eclipse at 2nd street and Folsom, there's a good chance I have a photo of you craning.</description><author>Avy Faingezicht</author><pubDate>Tue, 22 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/08/22/eclipse/</guid></item><item><title>Coming from Node.js: Ruby on Rails and Django</title><link>https://nutcroft.mataroa.blog/blog/coming-from-nodejs-ruby-on-rails-and-django/</link><description>&lt;p&gt;For almost three years now I have been working with Node.js, along with the rest of the gang, Express, Mongo, Angular and React.&lt;/p&gt;
&lt;p&gt;I had never worked with Ruby on Rails, Django or any other batteries-included web frameworks, but I had been always hearing that the pros outweigh the cons in many cases, and especially in a CRUD web application. CRUDs did play a major role in the Node.js applications I was working on, so I decided to try Rails and Django to see if indeed and particularly how much better they are.&lt;/p&gt;
&lt;p&gt;I decided to play with those two since they were the most famous and appealing.&lt;/p&gt;
&lt;h2 id="ruby-on-rails"&gt;Ruby on Rails&lt;/h2&gt;
&lt;p&gt;Ruby on Rails was created by &lt;a href="https://twitter.com/dhh"&gt;DHH&lt;/a&gt;, the CTO of Basecamp (then 37signals) who extracted Rails after working with Ruby on 37signals.&lt;/p&gt;
&lt;p&gt;One of the most surprising features of Rails is the underlying philosophy of &lt;a href="http://rubyonrails.org/doctrine/#convention-over-configuration"&gt;Convention over Configuration&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, if you have a controller method named &lt;code&gt;new&lt;/code&gt;, then if Rails finds an HTML template named &lt;code&gt;new.erb.html&lt;/code&gt; it will automatically render it! It is the convention that if there is a template with the same name as the method, in a directory with the controller name, it will be rendered.&lt;/p&gt;
&lt;p&gt;That, at first, seemed kind of over the top and scary, but I have grown to really liking it. It saves time and lines while not getting in the way.&lt;/p&gt;
&lt;p&gt;The next thing that amazed me was the way you can have a model with REST endpoints.&lt;/p&gt;
&lt;p&gt;Assuming we have a model, &lt;code&gt;Post&lt;/code&gt;, you can just say &lt;code&gt;resources :posts&lt;/code&gt; in your routes file and you get all REST endpoints, just like that, one line.&lt;/p&gt;
&lt;p&gt;In order to do this using Node.js and Express quite a few hours have to be spent. Additionally to the hours you need to set up the whole project, file architecture, ORM, routing, testing, etc.&lt;/p&gt;
&lt;p&gt;The last, of the top 3 things that impressed me is how Rails passes view parameters from the controller methods to the template. They just pass every variable defined! You don’t have to create an object with the ones you want, Rails sends everything for you, and you can use the one you want.&lt;/p&gt;
&lt;p&gt;This makes so much sense. If you defined a variable in the controller, 90% you are going to use it in the template; there is no need to tweak that object all the time.&lt;/p&gt;
&lt;p&gt;Also, separation of development, production and testing environments is done by default, which is neat.&lt;/p&gt;
&lt;p&gt;The things I didn’t like include the quite complex templating language, especially for forms (more details below) and the fact that Rails is very keen on breaking changes. This also makes googling very annoying because you don’t know if that specific StackOverflow answer works for 5.X version.&lt;/p&gt;
&lt;h2 id="django"&gt;Django&lt;/h2&gt;
&lt;p&gt;Django has a similar birth, open sourced after being developed for the website of the Lawrence Journal-World newspaper. Its creators are Adrian Holovaty and Simon Willison.&lt;/p&gt;
&lt;p&gt;One of Django’s core philosophy, that inherits from Python, is &lt;a href="https://docs.djangoproject.com/en/1.11/misc/design-philosophies/#explicit-is-better-than-implicit"&gt;Explicit is better than implicit&lt;/a&gt;, which actually is the exact opposite of Rails’ one with convention over configuration. Despite all that, one of the things that I like about Django is how much fewer files and directories I had in my project than in the case of Rails.&lt;/p&gt;
&lt;p&gt;Always using REST models, separate controllers, various namespacing techniques and other architecture decisions make Rails grow a large number of files even for a small project. Of course, those files are usually much smaller than the Django ones, but I have come to prefer to have, e.g., all my forms in one 100-lines &lt;code&gt;forms.py&lt;/code&gt; file instead of 10 separate files, with 10 lines each, inside a &lt;code&gt;forms&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;Django follows this philosophy. One &lt;code&gt;models.py&lt;/code&gt; file, one &lt;code&gt;forms.py&lt;/code&gt;, one &lt;code&gt;views.py&lt;/code&gt; file; when a project grows large enough you can transition to multiple files.&lt;/p&gt;
&lt;p&gt;Since I talked about &lt;code&gt;views.py&lt;/code&gt;, now is a good time to talk about naming. Django calls its controllers &lt;code&gt;views&lt;/code&gt; and its views &lt;code&gt;templates&lt;/code&gt; (and its models &lt;code&gt;models&lt;/code&gt;). In case you were wondering, its “controller” is the framework itself.&lt;/p&gt;
&lt;p&gt;One of the major features of Django is its apps. It is a way to divide a web application into parts, and it’s not optional. This frustrated me in the beginning; had I wanted to break my app into parts I would go microservices which are more hip.&lt;/p&gt;
&lt;p&gt;Thankfully, I scraped that incarnation and followed &lt;a href="https://www.stavros.io/"&gt;Stavros&lt;/a&gt;’ advice (he’s a Django oldtimer) to have a &lt;code&gt;main&lt;/code&gt; app and throw all business logic inside there.&lt;/p&gt;
&lt;p&gt;Of the things I liked the most in Django is the way it handles forms. Rails does forms on the templates, and the &lt;code&gt;erb&lt;/code&gt; templating language wasn’t the easiest to work with. Various confusing tags like &lt;code&gt;label&lt;/code&gt; and &lt;code&gt;label_tag&lt;/code&gt;, along with too much logic made it the most frustrating thing using Rails.&lt;/p&gt;
&lt;p&gt;Django’s handling was &lt;em&gt;almost&lt;/em&gt; like a breeze. You can have a &lt;code&gt;ModelForm&lt;/code&gt; which automatically creates all input fields for a model, and then you can override the things you want. Some were harder to find than others, but once you understand the philosophy and the terms (&lt;code&gt;Field&lt;/code&gt;, &lt;code&gt;Widget&lt;/code&gt;, etc) it becomes pretty easy.&lt;/p&gt;
&lt;p&gt;Another nice thing is that Django has an integrated admin interface in the &lt;code&gt;/admin&lt;/code&gt; endpoint of your application. It is pretty useful, I missed it in Rails.&lt;/p&gt;
&lt;p&gt;While, as I said, I didn’t like the large number of files and directories in Rails, there were some things that I also missed in Django.&lt;/p&gt;
&lt;p&gt;Firstly, Django refuses to serve static files in production. It does not have a suitable module for doing that, and you either need to install a separate package, &lt;code&gt;whitenoise&lt;/code&gt;, or upload and serve static assets directly from a CDN. In my use case though, with dokku (and with Heroku) a module to do this would be useful.&lt;/p&gt;
&lt;p&gt;This, along with with the fact that Django doesn’t handle by default stuff like separation of development/production/testing environments and database url parsing made the deployment a little bit more cumbersome than Rails and Node.js, but still pretty easy with dokku.&lt;/p&gt;
&lt;p&gt;To conclude with Django, the only thing I’m concerned with is REST endpoints. There is Django REST framework but I have not tried it, and I’ve heard it doesn’t have the most straightforward documentation.&lt;/p&gt;
&lt;p&gt;All in all, I liked Rails and Django and I’m very interested in working more with them. Finally, despite risking oversimplification of any project’s requirements I’d say that I would choose Django for CRUDs, and Rails for REST APIs. The shortcuts they provide, respectively for those use cases, are awesome.&lt;/p&gt;</description><author>nutcroft</author><pubDate>Tue, 22 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nutcroft.mataroa.blog/blog/coming-from-nodejs-ruby-on-rails-and-django/</guid></item><item><title>AI &amp;amp; The Great Reorientation</title><link>https://blog.eutopian.io/ai-the-great-reorientation/</link><description>600 words, 3 minutes. Photograph of UK&amp;rsquo;s first cash machine installation 1967. Martins Bank Archive.
In this bite-sized post I&amp;rsquo;m going to talk about the lag between initial adoption of transformative technology and the increase in productivity it&amp;rsquo;s supposed to bring. I&amp;rsquo;m going to talk about the disappointment felt when such technology meets established, dogmatic structures in business (or government), and what executives can do about it. Not all new technologies have the potential to transform business but those that do demand special care, because they are a pill that you swallow not a topical cream.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Mon, 21 Aug 2017 21:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/ai-the-great-reorientation/</guid></item><item><title>A brief analysis of U.S. Presidential Inauguration Speeches</title><link>https://bastian.rieck.me/blog/2017/inauguration_speeches_brief/</link><description>&lt;p&gt;The current political climate in the United States appears to be somewhat heated, to say the least. The current president, Donald J.  Trump, is considered by many to be the &lt;a href="https://www.theguardian.com/commentisfree/2016/oct/26/donald-trump-outsider-system-elections"&gt;product of an ever-declining political culture&lt;/a&gt;, in which many people feel increasingly
&lt;a href="https://hbr.org/ideacast/2016/11/why-the-white-working-class-voted-for-trump"&gt;disenfranchised&lt;/a&gt; and hopeless.&lt;/p&gt;
&lt;p&gt;I was wondering whether these changes in political culture would show up
as patterns—and where better to look for patterns than in the
inauguration speeches of U.S. presidents? These speeches are meant to
give a grand vision of the new term. Ideally, they should &lt;em&gt;unite&lt;/em&gt; but
also &lt;em&gt;rally&lt;/em&gt; the voters to support the new administration and look
forward to the subsequent years.&lt;/p&gt;
&lt;p&gt;In this post, I am going to show you how to obtain all inauguration
speeches, perform a brief language analysis on them, and report some
interesting results. Onwards!&lt;/p&gt;
&lt;h1 id="getting-the-data"&gt;Getting the data&lt;/h1&gt;
&lt;p&gt;Thanks to the good folks of &lt;a href="https://en.wikisource.org/wiki/Main_Page"&gt;Wikisource&lt;/a&gt;, obtaining all speeches is quite easy. There is a &lt;a href="https://en.wikisource.org/wiki/Category:U.S._Presidential_Inaugural_Addresses"&gt;special category&lt;/a&gt; for all speeches, and since the formatting of every speech contains (more or less) the same tags, it is a simple exercise in using &lt;a href="https://www.crummy.com/software/BeautifulSoup"&gt;BeautifulSoup&lt;/a&gt; to obtain and store all the speeches. See &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches/blob/master/get_speeches.py"&gt;my Python script&lt;/a&gt; for more details. As a result, each speech is stored in the format of &lt;code&gt;YYYY_Name.txt&lt;/code&gt;. We thus have &lt;code&gt;1789_George_Washington.txt&lt;/code&gt;, for example. Other than that, the text files are left &lt;em&gt;as-is&lt;/em&gt;. I did not make any attempts at extracting more information from them.&lt;/p&gt;
&lt;h1 id="analysing-the-data"&gt;Analysing the data&lt;/h1&gt;
&lt;p&gt;The simplest form of analysis that one might apply to these speeches
involves basic word counting or &lt;em&gt;tokenization&lt;/em&gt; in general. I will go
a small step further and use &lt;a href="https://en.wikipedia.org/wiki/Stemming"&gt;&amp;ldquo;stemming&amp;rdquo;&lt;/a&gt;
to reduce every word to their root form.&lt;/p&gt;
&lt;p&gt;This procedure gives us a way to answer the following questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How long is the speech (in sentences)?&lt;/li&gt;
&lt;li&gt;How long is the speech (in words)?&lt;/li&gt;
&lt;li&gt;What is the average sentence length?&lt;/li&gt;
&lt;li&gt;What is the number of unique &lt;em&gt;words&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;What is the number of unique &lt;em&gt;lemmas&lt;/em&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last question is worth explaining. A &lt;em&gt;lemma&lt;/em&gt; in the sense of NLP
or &lt;em&gt;natural language processing&lt;/em&gt; denotes the canonical form of words
in a corpus. For example, &lt;em&gt;run&lt;/em&gt;, &lt;em&gt;runs&lt;/em&gt;, &lt;em&gt;ran&lt;/em&gt;, and &lt;em&gt;running&lt;/em&gt; belong
to the same lemma, viz. &lt;em&gt;run&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I stole this example from the &lt;a href="https://en.wikipedia.org/wiki/Lemma_(morphology)"&gt;&amp;ldquo;Wikipedia page on &lt;em&gt;lemma&lt;/em&gt;&amp;rdquo;&lt;/a&gt;; please refer to it for more details.&lt;/p&gt;
&lt;p&gt;The reason for counting &lt;em&gt;lemmas&lt;/em&gt; is that they give us a rough estimate
of the complexity of a text. If a text contains many unique lemmas, it
is likely to be more complex than a text with fewer unique lemmas.&lt;/p&gt;
&lt;p&gt;I am aware that this is not the linguistically correct way of complexity
analysis, but it gives us a qualitative overview of a text without
delving deeper into its vocabulary.&lt;/p&gt;
&lt;p&gt;Consequently, I wrote &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches/blob/master/analyse_speeches.py"&gt;another script&lt;/a&gt; to analyse the speeches and store the statistics mentioned above in files. It is time for a quick analysis!&lt;/p&gt;
&lt;h1 id="results"&gt;Results&lt;/h1&gt;
&lt;p&gt;Let’s first take a look at the average sentence length of all
speeches. You can hover over each data point to see the name of the
president giving the speech.&lt;/p&gt;

  &lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_avg_sentence_len.svg"&gt;&lt;img alt="A plot of the average sentence length, in words, of all presidential inauguration speeches" src="https://bastian.rieck.me/images/inauguration_speeches_avg_sentence_len.svg" /&gt;&lt;/a&gt;
  &lt;/figure&gt;


&lt;p&gt;We can see that—alas— the average length of a sentence is declining. This is not necessarily a bad thing, as shorter sentences are often thought to be understood better by readers and listeners. Given that metric, there are a few interesting outliers, such as &lt;a href="https://en.wikipedia.org/wiki/John_Adams"&gt;John Adams&lt;/a&gt;, whose speech contains a real beast of a sentence:&lt;/p&gt;
&lt;small&gt;
&lt;blockquote&gt;
&lt;p&gt;On this subject it might become me better to be silent or to speak with diffidence; but as something may be expected, the occasion, I hope, will be admitted as an apology if I venture to say that if a preference, upon principle, of a free republican government, formed upon long and serious reflection, after a diligent and impartial inquiry after truth; if an attachment to the Constitution of the United States, and a conscientious determination to support it until it shall be altered by the judgments and wishes of the people, expressed in the mode prescribed in it; if a respectful attention to the constitutions of the individual States and a constant caution and delicacy toward the State governments; if an equal and impartial regard to the rights, interest, honor, and happiness of all the States in the Union, without preference or regard to a northern or southern, an eastern or western, position, their various political opinions on unessential points or their personal attachments; if a love of virtuous men of all parties and denominations; if a love of science and letters and a wish to patronize every rational effort to encourage schools, colleges, universities, academies, and every institution for propagating knowledge, virtue, and religion among all classes of the people, not only for their benign influence on the happiness of life in all its stages and classes, and of society in all its forms, but as the only means of preserving our Constitution from its natural enemies, the spirit of sophistry, the spirit of party, the spirit of intrigue, the profligacy of corruption, and the pestilence of foreign influence, which is the angel of destruction to elective governments; if a love of equal laws, of justice, and humanity in the interior administration; if an inclination to improve agriculture, commerce, and manufacturers for necessity, convenience, and defense; if a spirit of equity and humanity toward the aboriginal nations of America, and a disposition to meliorate their condition by inclining them to be more friendly to us, and our citizens to be more friendly to them; if an inflexible determination to maintain peace and inviolable faith with all nations, and that system of neutrality and impartiality among the belligerent powers of Europe which has been adopted by this Government and so solemnly sanctioned by both Houses of Congress and applauded by the legislatures of the States and the public opinion, until it shall be otherwise ordained by Congress; if a personal esteem for the French nation, formed in a residence of seven years chiefly among them, and a sincere desire to preserve the friendship which has been so much for the honor and interest of both nations; if, while the conscious honor and integrity of the people of America and the internal sentiment of their own power and energies must be preserved, an earnest endeavor to investigate every just cause and remove every colorable pretense of complaint; if an intention to pursue by amicable negotiation a reparation for the injuries that have been committed on the commerce of our fellow-citizens by whatever nation, and if success can not be obtained, to lay the facts before the Legislature, that they may consider what further measures the honor and interest of the Government and its constituents demand; if a resolution to do justice as far as may depend upon me, at all times and to all nations, and maintain peace, friendship, and benevolence with all the world; if an unshaken confidence in the honor, spirit, and resources of the American people, on which I have so often hazarded my all and never been deceived; if elevated ideas of the high destinies of this country and of my own duties toward it, founded on a knowledge of the moral principles and intellectual improvements of the people deeply engraven on my mind in early life, and not obscured but exalted by experience and age; and, with humble reverence, I feel it to be my duty to add, if a veneration for the religion of a people who profess and call themselves Christians, and a fixed resolution to consider a decent respect for Christianity among the best recommendations for the public service, can enable me in any degree to comply with your wishes, it shall be my strenuous endeavor that this sagacious injunction of the two Houses shall not be without effect.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/small&gt;
&lt;p&gt;Compare this to the second inauguration speech of &lt;a href="https://en.wikipedia.org/wiki/George_Washington"&gt;George Washington&lt;/a&gt;, which is the briefest one, while still using longer sentences than &lt;em&gt;any&lt;/em&gt; of the presidents starting their term in the 20th or the 21st century.&lt;/p&gt;
&lt;p&gt;What about the active vocabulary of the presidents? To this end, let us
take a look at the number of unique lemmas in a speech. Note that these
are &lt;em&gt;raw counts&lt;/em&gt;, so they will also give us an indication of how long a
speech is. Again, hover over a data point to display the name.&lt;/p&gt;

  &lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/inauguration_speeches_num_unique_lemmas.svg"&gt;&lt;img alt="Unique lemmas of all presidential inauguration speeches" src="https://bastian.rieck.me/images/inauguration_speeches_num_unique_lemmas.svg" /&gt;&lt;/a&gt;
  &lt;/figure&gt;


&lt;p&gt;Here, there is not so much of a clear trend but rather some interesting
outliers. According to this metric, most presidents in the 20th century
and onwards use about the same number of unique lemmas in a speech. This
means that the speeches have roughly the same length and also the same
complexity, provided you buy my argument that the number of unique
lemmas is something interesting to consider. We can see that Donald J.
Trump is not really an outlier in this regard; both Gerald Ford—a
republican—in 1974 and Jimmy Carter—a democrat—in 1977
gave speeches are are rated approximately the same.&lt;/p&gt;
&lt;p&gt;Interestingly, some other patterns arise. First, we see that the second
inauguration speech of George Washington is really short and sweet.
There are less than 200 unique lemmas. Second, the inauguration speech
of William Henry Harrison is obviously extremely long and convoluted,
more so than any other speech (so far; who knows what the future
holds?). We can also see that the &lt;em&gt;third&lt;/em&gt; inauguration speech of
Franklin D. Roosevelt in 1945 really is on point. His message is short
and simple. Afterwards, things start to get more complicated again.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;What can we make of this? First, it is interesting to see that these
simple qualitative analysis steps only give us a very narrow picture of
what is happening in a speech. At least the oratory culture of the
United States seems to be doing well. Most presidents use about the same
complexity for their speeches. The number of unique lemmas decreased for
modern times, though. These may be an artefact of the stemming method,
though. As language changes over time, a simple stemmer that is trained
for modern speeches will have its troubles when analysing older speeches.&lt;/p&gt;
&lt;p&gt;I hope that this provided some insights. You are welcome to play with the data and do your own analysis. Please take a look at &lt;a href="https://github.com/Pseudomanifold/us-inauguration-speeches"&gt;the GitHub repository&lt;/a&gt; for more information.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 20 Aug 2017 16:57:29 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/inauguration_speeches_brief/</guid></item><item><title>About</title><link>https://geo.rocks/about/</link><description>GIS, Data Science &amp;amp; ML © 2020 Dominik Weckmüller
About me My name is Dominik Weckmüller and my mission is to democratize knowledge.
I&amp;rsquo;m a full-stack software engineer, researcher and geospatial consultant specialized in geoinformatics, particularly GIS, geomarketing and remote sensing with application to social geography. I develop web applications with a focus on geospatial big data science, NLP and deep learning. I worked as a freelancer for:
private companies universities (University of Virginia School of Architecture; Politecnico di Milano Department of Management, Economics and Industrial Engineering) public bodies (City of Bonn; Joint Research Centre, European Commission).</description><author>Geography &amp;amp; Coding</author><pubDate>Sun, 20 Aug 2017 16:38:52 GMT</pubDate><guid isPermaLink="true">https://geo.rocks/about/</guid></item><item><title>Cross-platform web UI for C and Go</title><link>https://zserge.com/posts/webview/</link><description>Cross-platform GUI has always been a painful part of software development.
Today the biggest horror for an old-school C developer is to look at the list of Electron apps on their website. Simple, often trivial utilities, each taking over a hundred of megabytes of disk space and consuming hundreds of RAM once launched.
I&amp;rsquo;m not going to start a rant here, people of HackerNews have said enough on this topic. Electron wins because it is easy to use and everyone knows how to write HTML/CSS (unlike, say, QML or XAML).</description><author>zserge's blog</author><pubDate>Sun, 20 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://zserge.com/posts/webview/</guid></item><item><title>Stackless vs. Stackful Coroutines</title><link>https://blog.varunramesh.net/posts/stackless-vs-stackful-coroutines/</link><description>Coroutines can either be stackless or stackful. The terminology is somewhat confusing.</description><author>Varun Ramesh's Blog</author><pubDate>Sat, 19 Aug 2017 09:25:00 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/stackless-vs-stackful-coroutines/</guid></item><item><title>Projectile shell dir company completion</title><link>https://xenodium.com/projectile-shell-dir-company-completion</link><description>&lt;p&gt;&lt;a href="https://github.com/bbatsov/projectile"&gt;Projectile&lt;/a&gt; and &lt;a href="https://company-mode.github.io"&gt;company&lt;/a&gt; are just amazing Emacs packages. Projectile gives random access to files, while company completes well… anything. For shells, Emacs has a handful of options.&lt;/p&gt;
&lt;p&gt;Standing on the shoulders of package giants (&lt;a href="https://github.com/magnars/dash.el"&gt;dash&lt;/a&gt; and &lt;a href="https://github.com/rejeep/f.el"&gt;f&lt;/a&gt; included) and some elisp, we can bring random access to project directories from the shell.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/projectile-shell-dir-company-completion/company-projectile-cd.png" /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(require 'cl-lib)
(require 'company)
(require 'dash)
(require 'f)
(require 'projectile)

(defvar-local company-projectile-cd-prefix &amp;quot;cd &amp;quot;)

(defun company-projectile-cd (command &amp;amp;optional arg &amp;amp;rest ignored)
  &amp;quot;Company shell completion for any projectile path.&amp;quot;
  (interactive (list 'interactive))
  (case command
    (interactive (company-begin-backend 'company-projectile-cd))
    (prefix
     (company-grab-symbol-cons company-projectile-cd-prefix
                               (length company-projectile-cd-prefix)))
    (candidates
     (company-projectile-cd--candidates
      (company-grab-symbol-cons company-projectile-cd-prefix
                                (length company-projectile-cd-prefix))))
    (post-completion
     (company-projectile-cd--expand-inserted-path arg))))

(defun company-projectile-cd--candidates (input)
  &amp;quot;Return candidates for given INPUT.&amp;quot;
  (company-projectile-cd--reset-root)
  (when (consp input)
    (let ((search-term (substring-no-properties
                        (car input) 0 (length (car input))))
          (prefix-found (cdr input)))
      (when prefix-found
        (if (projectile-project-p)
            (company-projectile-cd--projectile search-term)
          (company-projectile-cd--find-fallback search-term))))))

(defun company-projectile-cd--projectile (search-term)
  (-filter (lambda (path)
             (string-match-p (regexp-quote
                              search-term)
                             path))
           (-snoc
            (projectile-current-project-dirs)
            ;; Throw project root in there also.
            (projectile-project-root))))

(defun company-projectile-cd--find-fallback (search-term)
  (ignore-errors
    (-map (lambda (path)
            (string-remove-prefix &amp;quot;./&amp;quot; path))
          (apply #'process-lines
                 (list &amp;quot;find&amp;quot; &amp;quot;.&amp;quot; &amp;quot;-type&amp;quot; &amp;quot;d&amp;quot;  &amp;quot;-maxdepth&amp;quot; &amp;quot;2&amp;quot; &amp;quot;-iname&amp;quot;
                       (format &amp;quot;\*%s\*&amp;quot; search-term))))))

(defun company-projectile-cd--expand-inserted-path (path)
  &amp;quot;Replace relative PATH insertion with its absolute equivalent if needed.&amp;quot;
  (unless (f-exists-p path)
    (delete-region (point) (- (point) (length path)))
    (insert (concat (projectile-project-root) path))))

(defun company-projectile-cd--reset-root ()
  &amp;quot;Reset project root. Useful when cd'ing in and out of projects.&amp;quot;
  (projectile-reset-cached-project-root)
  (when (projectile-project-p)
    (projectile-project-root)))
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 19 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/projectile-shell-dir-company-completion</guid></item><item><title>Pirate Cup</title><link>https://mbutler.org/pirate-cup/</link><description>Pirate Cup is a game based almost exactly on the 1988 FASA classic, Circus Imperium. It was built with Phaser and used free art assets from Kenney. Once again, I find it next to impossible to polish a game and finish it up enough to actually release it. I enjoy the challenge of implementing rules [&amp;#8230;]</description><author>mbutler</author><pubDate>Fri, 18 Aug 2017 23:31:36 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/pirate-cup/</guid></item><item><title>Half-Baked: Index Investing and Divesting</title><link>https://faingezicht.com/articles/2017/08/18/indexing/</link><description>A while back, I started thinking about putting some savings in a broad-based index fund, and I compared various brokerage providers. I was surprised to learn about one of Wealthfront's features, which other players did not offer: &lt;a href="https://research.wealthfront.com/whitepapers/tax-optimized-direct-indexing/"&gt;direct indexing&lt;/a&gt;.

Direct indexing replaces a traditional passive fund with the equivalent combination of individual securities that would make up said fund. Instead of holding one share of an asset that tracks the S&amp;amp;P 500, you hold the fractional equivalent of the 500 stocks that that one share would represent[^0]. This allows for more flexible tax loss harvesting strategies, and (at least in theory) leads to better performance. The wrinkle with direct indexing is that many people can't buy and sell stocks of certain companies freely, either because of insider trading regulation, or because of the tax implications of wash sales. To remedy this, Wealthfront allows you to build up an exclusion list, a blacklist of companies that you're not willing to hold, and which they automatically replace in your portfolio with highly correlated, but different assets to still have you hold a fund equivalent.

A few months later, in a conversation with Hannah regarding index funds, she mentioned that she wouldn't like to use a total market fund, as she would like to make sure her money didn't go to private prison operators, and other companies whose values she didn't agree with. Her argument, simply put, was that if you believe that companies should be socially responsible, or environmentally friendly, then why invest in a company that does not follow what you value? When you invest in a company, you are voting with your dollars; you are saying "I am willing to let company A take my cash today so that it can put it to work and give me some return tomorrow," literally enabling their business. This is where it gets interesting. Direct indexing lets you invest in broad passive funds while divesting[^1] from companies whose principles you don't agree with!

Ultimately, I decided not to invest with Wealthfront (in part because to be able to use direct indexing, you need to invest at least 100K, but mostly because of fees), and decided to go with Vanguard instead. Today I got an email from them, asking me to vote by proxy on a proposal being considered by Vanguard's board:

&gt; A shareholder proposal to "institute transparent procedures to avoid holding investments in companies that, in management’s judgment, substantially contribute to genocide or crimes against humanity, the most egregious violations of human rights. Such procedures may include time-limited engagement with problem companies if management believes that their behavior can be changed."

I voted yes, and I guess that's as good as it gets. I don't expect Vanguard to implement direct indexing and blacklisting any time soon. There might be a market opportunity here, though.

&lt;small&gt;_The "Half-Baked" series is my effort to write more, and put my thoughts out there on the internet, a brain dump, unedited. Just a few minutes of writing. If you find typos, or grammatical errors, let me know. They will be corrected as I notice them, but otherwise the content will remain as published._&lt;/small&gt;

[^0]: This is not totally accurate, as the stocks that you can directly hold depend on how large your position is with Wealthfront, and the capitalization of the companies themselves, but that is not important for the point I am trying to make.
[^1]: In theory you could have bought the index and shorted the equivalent amount in those stocks, but that's not feasible even with a ton of effeort, due to limitations in the stock market.</description><author>Avy Faingezicht</author><pubDate>Fri, 18 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/08/18/indexing/</guid></item><item><title>One thousand captcha photos organized with a neural network</title><link>https://www.ryancompton.net/2017/08/18/one-thousand-captcha-photos-organized-with-a-neural-network.html</link><description>Coauthored with Habib Talavati. Originally published on the Clarifai blog at https://blog.clarifai.com/one-thousand-captcha-photos-organized-with-a-neural-network-2/ The below image shows 1024 of the captcha photos used in “I’m not a human: Breaking the Google reCAPTCHA” by Sivakorn, Polakis, and Keromytis arranged on a 32x32 grid in such a way that visually-similar photos appear in close proximity to each other on the grid.</description><author>Ryan Compton</author><pubDate>Fri, 18 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.ryancompton.net/2017/08/18/one-thousand-captcha-photos-organized-with-a-neural-network.html</guid></item><item><title>Timeseries charts with Chart.js</title><link>https://jfoucher.com/2017/08/timeseries-charts-with-chart.js.html</link><description>&lt;p&gt;Somehow I always end up having to do timeseries charts. Chart.js is my tool of choice for that task, but I never seem to remember what options to pass and what format the data should have. Yesterday I must have spent 2 hours looking at the docs and trying various things, mostly because it didn’t occur to me to check the last project where I used them, &lt;a href="https://budgt.eu"&gt;Budgt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So anyway, note to self : this is how you do timeseries graphs in chart.js&lt;/p&gt;

&lt;div class="language-js 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;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chartCanvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Labels should be Date objects&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2017&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;08&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2017&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2017&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="na"&gt;datasets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Page Views&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;340&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fe8b36&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fe8b36&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lineTension&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="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="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;responsive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;scales&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;xAxes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;scaleLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;labelString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Date&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="p"&gt;}],&lt;/span&gt;
            &lt;span class="na"&gt;yAxes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="na"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;beginAtZero&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;scaleLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;labelString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Page Views&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="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&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="nx"&gt;chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&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;And here’s what it looks like:&lt;/p&gt;

&lt;canvas height="200" id="chartCanvas" width="400"&gt;&lt;/canvas&gt;




&lt;p&gt;That’s it. Hopefully I’ll remember I posted this here next time I need timeseries charts in chart.js&lt;/p&gt;</description><author>Geeky Nuggets</author><pubDate>Fri, 18 Aug 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://jfoucher.com/2017/08/timeseries-charts-with-chart.js.html</guid></item><item><title>An Idea Whose Time Has Come</title><link>https://blog.eutopian.io/an-idea-whose-time-has-come/</link><description>950 words, 4 1/2 minutes. Hugo by Étienne Carjat, 1876
&amp;ldquo;Nothing is as powerful as an idea whose time has come.&amp;quot; - Victor Hugo.
This is the second of two posts on strategic software. The first explained what it is, what it does, and where to find it. Now I&amp;rsquo;ll tell you why it&amp;rsquo;s an idea whose time has come. I&amp;rsquo;ll tell you why it will be more powerful in some respects than traditional politics and how it will come to shape the world.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 17 Aug 2017 13:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/an-idea-whose-time-has-come/</guid></item><item><title>Debian OpenSSL 1.1.0f-4 and macOS 10.11 (El Capitan)</title><link>https://porkrind.org/missives/debian-openssl-1-1-0f-4-and-macos-10-11/</link><description>Some people were reporting that an IMAP server wasn&amp;#8217;t working on their Mac. It was working from linux machines, and from Thunderbird on all OSes. From Macs I was getting this testing from the command line: $ openssl s_client -connect &amp;#60;my-imap-server&amp;#62;:993 CONNECTED(00000003) 39458:error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.6/src/ssl/s23_clnt.c:593: This led me to a recent libssl package &amp;#8230; &lt;a class="more-link" href="https://porkrind.org/missives/debian-openssl-1-1-0f-4-and-macos-10-11/"&gt;Continue reading &lt;span class="screen-reader-text"&gt;Debian OpenSSL 1.1.0f-4 and macOS 10.11 (El Capitan)&lt;/span&gt;&lt;/a&gt;</description><author>Missives</author><pubDate>Thu, 17 Aug 2017 09:15:28 GMT</pubDate><guid isPermaLink="true">https://porkrind.org/missives/debian-openssl-1-1-0f-4-and-macos-10-11/</guid></item><item><title>Introduction to Higher Order Components</title><link>https://dylanpaulus.com/posts/2017/higher-order-components/</link><description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Think of Higher Order Components (HOC) like Pacman. As Pacman consumes his smaller looking dot counterparts, Pacman gains superpower abilities. Like ghost eating! HOC's work similarly... minus ghosts.&lt;br /&gt;
A HOC consumes a base component, applies some new ability or super power, then spits out a new modified base component. To help show the power of HOC's, lets create one that does a simple check. If a component doesn't have children, show an empty component. When children are present, we'll display them.&lt;/p&gt;
&lt;h3&gt;withEmptyState()&lt;/h3&gt;
&lt;p&gt;First, lets define our base component.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function Hello(props) {
  return &amp;lt;div&amp;gt;Hello, {props.children}!&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before jumping straight into the HOC, what are we trying to achieve? We want to pass our &lt;code&gt;&amp;lt;Hello /&amp;gt;&lt;/code&gt; component into some function, lets call it withEmptyState(), which creates and returns a new component. This new component will either: show &lt;code&gt;&amp;lt;Hello /&amp;gt;&lt;/code&gt; if the new component has children, or will return null.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function withEmptyState(component) {
  return function (props) {
    // Start new stateless functional component
    if (props.children) {
      return component(props);
    }

    return null;
  };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty simple, but extremely powerful! All this function does is take a component, then returns a new stateless functional component. Inside, we check the props. Does this component have children? If yes, return our originally passed in component using our new component's props (We'll see how this ties in soon). If no children exist, don't render anything.&lt;/p&gt;
&lt;p&gt;But how would I use withEmptyState?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const HOC = withEmptyState(Hello);

class MyContainer extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        HOC 1: &amp;lt;HOC /&amp;gt;
        &amp;lt;hr /&amp;gt;
        HOC 2: &amp;lt;HOC&amp;gt;WORLD!&amp;lt;/HOC&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our first instance of &lt;code&gt;&amp;lt;HOC /&amp;gt;&lt;/code&gt; wouldn't render anything, as we haven't gave it children.&lt;/p&gt;
&lt;p&gt;The second &lt;code&gt;&amp;lt;HOC&amp;gt;WORLD!&amp;lt;/HOC&amp;gt;&lt;/code&gt; would render our &lt;code&gt;&amp;lt;Hello&amp;gt;&lt;/code&gt; component; we would see "Hello, WORLD!".&lt;/p&gt;
&lt;aside&gt;
&lt;img alt="Image showing off Higher Order Component results" /&gt;
&lt;/aside&gt;
&lt;h3&gt;The End&lt;/h3&gt;
&lt;p&gt;Higher Order Components allow us to separate common functionality into their own functions, so we don't have to add duplication between components. They also allow us to decouple functionality!&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Thu, 17 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2017/higher-order-components/</guid></item><item><title>Behind the Scenes at a VC Fund, Part 1: Deals, Deals, Deals</title><link>https://www.codingvc.com/p/behind-the-scenes-at-a-vc-fund-part-1-deals-deals-deals</link><description>My fund, Susa Ventures, just added Natalie Dillon to our team. She&amp;#8217;s our first-ever investment team hire and we&amp;#8217;re very excited to work with her. While speaking with dozens of wonderful candidates for the role, I was reminded of how opaque venture capital is as a profession. Many of the candidates asked what a typical day and a typical month are like for a VC. Is it schmoozing at parties for 40 hours a week? Taking back-to-back investment calls while lounging on some tropical beach? Making million-dollar decisions using coin flips? Reading technical research papers? (Answers: no, no, no, and hardly ever.) Now that I&amp;#8217;ve been doing this job for a while, I thought it might be useful to document what working in venture capital is like for anyone who may be curious. This 3-part series is a summary of my experience being one of three partners at</description><author>Coding VC</author><pubDate>Wed, 16 Aug 2017 08:10:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/behind-the-scenes-at-a-vc-fund-part-1-deals-deals-deals</guid></item><item><title>Random Meetup Attendee Bookmarklet</title><link>https://thomashunter.name/posts/2017-08-16-random-meetup-attendee-bookmarklet</link><author>Thomas Hunter II</author><pubDate>Wed, 16 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-08-16-random-meetup-attendee-bookmarklet</guid></item><item><title>The Age Of Strategic Software</title><link>https://blog.eutopian.io/the-age-of-strategic-software/</link><description>1300 words, 5 minutes.
Belloc by E. O. Hoppé, 1915.
&amp;ldquo;Whatever happens, we have got the Maxim gun, they have not.&amp;quot; - Hilaire Belloc.
Once upon a time software was just for counting beans. It counted more beans faster and cheaper than anything else. Then computers became personal, then portable, then pocketable. All sorts of different kinds of software were created to serve the people and help them do their jobs better.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 15 Aug 2017 13:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/the-age-of-strategic-software/</guid></item><item><title>Outside Lands, again (again)</title><link>https://faingezicht.com/photos/2017/08/15/outside-lands-v3/</link><description>Outside Lands has become one of those San Francisco events that I look forward to all year for the opportunity to take portraits. Thousands of happy people pour into Golden Gate park for a weekend of music and fun. It is kind of crazy that this is my fourth time there.

Somehow, I took 1300 photos over the weekend, so curating and editing them was an impossible task. If you know I took your photo, and you can't see it here, &lt;a href="/contact"&gt;reach out&lt;/a&gt; and I'll send you a copy.

You might have seen my &lt;a href="/photos/2015/08/09/outside-lands?src=OL17"&gt;2015&lt;/a&gt; and &lt;a href="/photos/2016/08/15/outside-lands-v2?src=OL17"&gt;2016&lt;/a&gt; sets already, but if not, I definitely recommend it after you're done with these!</description><author>Avy Faingezicht</author><pubDate>Tue, 15 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/08/15/outside-lands-v3/</guid></item><item><title>The making of a floating-label input with React Native's Animated API</title><link>https://goshacmd.com/floating-label-input-rn-animated/</link><author>Gosha Spark</author><pubDate>Tue, 15 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/floating-label-input-rn-animated/</guid></item><item><title>Hornstrandir</title><link>https://hth.is/2017/08/14/hornstrandir/</link><description>Link to album
Last august, my girlfriend and I, along with friends, went on a trip to a place far north in Iceland that relatively few Icelanders have seen, Hornstrandir.
The reason for why so few have gone there (relative to the rest of the island) is in probably part due to the location. As Iceland&amp;rsquo;s northern most peninsula, Hornstrandir is not easy to get to. First you have to get your self to Ísafjörður (or neighbouring towns) which is either a 6 hour drive or an expensive 1 hour flight, away from the capital Reykjavík.</description><author>Hrafn Thorvaldsson</author><pubDate>Mon, 14 Aug 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://hth.is/2017/08/14/hornstrandir/</guid></item><item><title>[Computing] Legal Analysis of the “Admiral” Anti-Adblocker DMCA Incident</title><link>https://www.devever.net/~hl/dmca-adblock</link><description>&lt;p&gt;A company called Admiral makes ad-blocker-blocker technology.&lt;/p&gt;</description><author>devever.net/~hl</author><pubDate>Sat, 12 Aug 2017 07:22:00 GMT</pubDate><guid isPermaLink="true">https://www.devever.net/~hl/dmca-adblock</guid></item><item><title>Guardians of the Galaxy Vol. 2</title><link>https://olshansky.info/movie/guardians_of_the_galaxy_vol._2/</link><description>Olshansky's review of Guardians of the Galaxy Vol. 2</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 12 Aug 2017 03:07:35 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/guardians_of_the_galaxy_vol._2/</guid></item><item><title>Made with love</title><link>https://ph-uhl.com/0002-made-with-heart/</link><description>&lt;p&gt;Did you ever see a website or a webapp where it said &amp;quot;created with ♡ by Jon Doe&amp;quot; in the footer? Hardly never. When I first saw it I thought, it's kind of cute. Guess what, numerous people on the internet thought so, too. Now it is hard to find anything on the web without the pesky ♡....</description><author>Philipp Uhl</author><pubDate>Sat, 12 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ph-uhl.com/0002-made-with-heart/</guid></item><item><title>2017-08-12</title><link>https://ho.dges.online/pictures/2017-08-12/</link><description/><author>ho.dges.online</author><pubDate>Sat, 12 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-08-12/</guid></item><item><title>Schlachter family website (1999)</title><link>https://schlachter.ca/familyweb/</link><description>Many stories from Mexico in this family website recovered from an old hard-drive.</description><author>David Schlachter</author><pubDate>Fri, 11 Aug 2017 20:00:00 GMT</pubDate><guid isPermaLink="true">https://schlachter.ca/familyweb/</guid></item><item><title>You Donate $400/Year Thanks To The Best Business Trick Ever</title><link>https://svedic.org/economy/indirect-razors-and-blades-business-model</link><description>I’m going to tell you a story about one ingenious business model that the majority of people are not aware of. It costs average US household around $400 per year. To understand the model, you’ll need to understand three economic &amp;#8230; &lt;a href="https://svedic.org/economy/indirect-razors-and-blades-business-model"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Fri, 11 Aug 2017 17:09:16 GMT</pubDate><guid isPermaLink="true">https://svedic.org/economy/indirect-razors-and-blades-business-model</guid></item><item><title>2017-08-11</title><link>https://ho.dges.online/pictures/2017-08-11/</link><description/><author>ho.dges.online</author><pubDate>Fri, 11 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-08-11/</guid></item><item><title>Links - August 10, 2017</title><link>https://faingezicht.com/links/2017/08/10/links/</link><description/><author>Avy Faingezicht</author><pubDate>Thu, 10 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/08/10/links/</guid></item><item><title>Color Theme Generator</title><link>https://ph-uhl.com/0001-color-scheme-creator/</link><description>This site uses color theory to create different colors from one base color.</description><author>Philipp Uhl</author><pubDate>Thu, 10 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ph-uhl.com/0001-color-scheme-creator/</guid></item><item><title>Communication between iframes with React and postMessage for an html template editor</title><link>https://jfoucher.com/2017/08/interframe-communication-with-postmessage.html</link><description>&lt;p&gt;I’m working on a project where I need some sort of simple landing page editor, where “blocks” are defined at the template level and they can be rearranged, text changed or added, and not much more. Most of the software I could find was either way too complex for my needs, gave the user the freedom to &lt;em&gt;completely&lt;/em&gt; destroy the template, or were otherwise pretty useless.&lt;/p&gt;

&lt;p class="image"&gt;&lt;img alt="Editor in action" src="/uploads/2017/08/leanr.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;If it was frustrating for me I imagine how it would feel for my users who need to do this quickly and efficiently. What I needed would’t have drag and drop, nor 300 sliders for everything, neither would it give the user the ability to completely modify the template. (Users can provide custom HTML for their pages if they so choose). Anyway, all I &lt;em&gt;need&lt;/em&gt; was the ability to place some template blocks on a page, move them up and down, remove them, and change the text bits.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“How hard can it be ?”&lt;/em&gt; &lt;br /&gt;&lt;small&gt;- me, at 3 AM on thursday night.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How hard indeed ? Well, as it turns out, &lt;em&gt;quite&lt;/em&gt;. But it’s my fault. Scope creep. I decided it would also be possible to change the images. And also upload them. And maybe add custom buttons. And edit the background images. And the background colors. Anyway, here we are now, and this is how I’ve (almost, anyday now) done it :&lt;/p&gt;

&lt;p&gt;I used an iframe to hold the displayed template, as that allows complete style (and everything else) isolation, and gives a good preview of the final result. &lt;em&gt;However&lt;/em&gt;, javascript between the iframe and the “controlling” page is not that easy. Because of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"&gt;same origin policy&lt;/a&gt; we can’t just tell the iframe to do this or that, or read it’s elements to see the html that’s in them.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Inter-frame communication is like inter-process communication”&lt;/em&gt; &lt;br /&gt;&lt;small&gt;- My buddy who does C (or C++ maybe?)&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oh I forgot to say, I want to store somewhat structured data about the edits, not just the raw HTML, to enable easier further edits if necessary. &lt;a href="https://github.com/bustle/mobiledoc-kit"&gt;mobiledoc&lt;/a&gt; seemed promising. I spent about an hour investigating it (my internet was slow that day, I swear!) before I realised it’s basically markdown. I thought adapting it to my use case, but it felt futile (as in: too much work). So what was I on about ? ah yes, iframes ! Mmmm who doesn’t love a  good iframe? You don’t? Good, ‘cause me neither. Anyway, inter-frame communication is like inter-process communication (or so says my buddy that does printer drivers for HP – Yeah, I’ll curse him on your behalf if you have an HP printer): you have to pass messages around, in our case with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;window.postMessage()&lt;/code&gt;&lt;/a&gt;. It works, it’s great!&lt;/p&gt;

&lt;p&gt;Anyway, here’s how it works: I like to think of it as communication between say a frontend and an API, mostly because of the asynchronous nature of the communication. So basically, the parent page get ready to receive messages from the iframe by listening to the “message” event, like so:&lt;/p&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleFrameTasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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;I’m using react for the frontend, so this went in the &lt;code class="language-plaintext highlighter-rouge"&gt;componentDidMount()&lt;/code&gt; method, but you could place it anywhere, really, as long as it runs when you want to start editing on the iframe side.&lt;/p&gt;

&lt;p&gt;And then on the iframe side I have something like this:&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-js"&gt;    &lt;span class="c1"&gt;// Send message to react
&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deleteBlock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;blockId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;blockId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In fact at the start I was &lt;code class="language-plaintext highlighter-rouge"&gt;JSON.stringify()&lt;/code&gt;ing the data I sent, as I remember it being necessary a few years ago, but that’s not required anymore.&lt;/p&gt;

&lt;p&gt;Then on the parent React side, the &lt;code class="language-plaintext highlighter-rouge"&gt;handleFrameTasks&lt;/code&gt; dispatches the actions required depending on what the iframe requested. For example in the case above it will delete the page block with id &lt;code class="language-plaintext highlighter-rouge"&gt;blockId&lt;/code&gt; from it’s page data structure.&lt;/p&gt;

&lt;p&gt;Did I mention that the iframe content is generated dynamically and injected in the iframe src with a data blob URL? Well then, maybe I’ll post about that the next time.&lt;/p&gt;

&lt;p&gt;Until then, keep coding !&lt;/p&gt;

&lt;p&gt;PS Oh about that &lt;a href="/2017/03/one-project-per-month-first-budget-tracking.html"&gt;One project per month challenge&lt;/a&gt;? This one is bigger than I expected, so it will (has already been) longer than a month. It will be great, I hope. Everything you need for an early stage startup. &lt;a href="/contact.html"&gt;Contact me&lt;/a&gt; if you’d like some more info.&lt;/p&gt;</description><author>Geeky Nuggets</author><pubDate>Thu, 10 Aug 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://jfoucher.com/2017/08/interframe-communication-with-postmessage.html</guid></item><item><title>Minecraft, Factorio, Game thing</title><link>http://www.nuke24.net/plog/24.html</link><description>Thoughts on why neither Minecraft nor Factorio are good enough</description><author>TOGoS's Project Log</author><pubDate>Wed, 09 Aug 2017 20:34:11 GMT</pubDate><guid isPermaLink="true">http://www.nuke24.net/plog/24.html</guid></item><item><title>Upgrading Microserver G8 CPU</title><link>https://caiustheory.com/upgrading-microserver-g8-cpu/</link><description>&lt;p&gt;My home server is a &lt;a href="https://www.hpe.com/uk/en/product-catalog/servers/proliant-servers/pip.hpe-proliant-microserver-gen8.5379860.html"&gt;HP Proliant Microserver Gen 8&lt;/a&gt;, which is modestly powerful and runs everything I need at home in a fairly compact footprint without being too noisy or power hungry.&lt;/p&gt;
&lt;p&gt;Both the G8 and the previous revision, the G7, are moderately expandable in terms of memory &amp;amp; storage devices. (Not least of which is an internal USB port, which is useful plugging the SmartOS boot device into, no chance of it being knocked out!) I&amp;rsquo;ve upgraded the memory and HDDs in the time I&amp;rsquo;ve had the machine. (&lt;a href="/finding-cheap-microserver-g8-memory/"&gt;Here&amp;rsquo;s how I upgraded the memory on the cheap&lt;/a&gt;!)&lt;/p&gt;
&lt;p&gt;The Gen 8 specifically is a little more upgradable however, as it comes with a 1155 CPU socket. Mine contained a &lt;a href="https://ark.intel.com/products/71074/Intel-Celeron-Processor-G1610T-2M-Cache-2_30-GHz"&gt;Celeron G1610T CPU&lt;/a&gt; from new, which whilst quicker than the AMD one in the G7, was only two cores / two threads and not massively fast in the grand scheme of things.&lt;/p&gt;
&lt;p&gt;Given I run a few different things on the home server, it acts as a NAS for a handful of laptops, &lt;a href="https://www.plex.tv/"&gt;plex server&lt;/a&gt;, &lt;a href="https://www.crashplan.com/"&gt;crashplan&lt;/a&gt; backup server, gathers various stats from network devices &amp;amp; runs the &lt;a href="https://unifi-hd.ubnt.com"&gt;unifi controller&lt;/a&gt;. Mostly it&amp;rsquo;s fine, but transcoding in Plex specifically burns the CPU and on the odd occasion I&amp;rsquo;ve noticed it being slower than realtime and having to wait for the server to catch up.&lt;/p&gt;
&lt;p&gt;So what to do? As you&amp;rsquo;ve no doubt guessed from the title of the post, I upgraded the CPU in it. I did some research and found &lt;a href="https://b3n.org/installed-xeon-e3-1230v2-in-gen8-hp-microserver/"&gt;someone else who documented the upgrading process&lt;/a&gt;, as well as the &lt;a href="http://n40l.wikia.com/wiki/Cpu_gen8"&gt;N40L wiki listing potential upgrade candidates&lt;/a&gt;. I then pulled together my own table of processors, specs &amp;amp; price on fleabay to work out which I want.&lt;/p&gt;
&lt;p&gt;My criteria were more than 2 cores/threads, ECC ram &lt;strong&gt;has&lt;/strong&gt; to be supported and ideally not much higher TDP than the stock CPU. &lt;a href="https://support.plex.tv/hc/en-us/articles/201774043"&gt;Plex guidelines for CPU power&lt;/a&gt; state that as a (very) rough guideline, you need a 2000 PassMark score per 1080p transcode. Given I would like other things running alongside Plex, allowing 2-3x that figure sounds ideal.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CPU&lt;/th&gt;
&lt;th&gt;Cores&lt;/th&gt;
&lt;th&gt;Threads&lt;/th&gt;
&lt;th&gt;TDP (W)&lt;/th&gt;
&lt;th&gt;Passmark&lt;/th&gt;
&lt;th&gt;Price (£)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;G1610T&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;2322&lt;/td&gt;
&lt;td&gt;12.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E3-1220L v2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;3701&lt;/td&gt;
&lt;td&gt;120.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E3-1220L&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;3563&lt;/td&gt;
&lt;td&gt;60.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E3-1260L&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;6534&lt;/td&gt;
&lt;td&gt;80.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E3-1265L&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;6054&lt;/td&gt;
&lt;td&gt;64.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;E3-1265L v2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;7733&lt;/td&gt;
&lt;td&gt;133.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Stock CPU is first in the list for comparison. Bold one is the chosen upgrade.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After some deliberation, I decided to pick up the E3-1265L v2 from Ebay. It has a slightly higher TDP, but not so much that I&amp;rsquo;m worried about the temperature in the server. Most importantly it supports ECC ram &amp;amp; quadruples the physical cores, whilst providing a whopping eight threads for processing power. More than enough for a couple of concurrent Plex transcodes with cycles left over for other things at the same time.&lt;/p&gt;
&lt;p&gt;I ordered it from a Hong Kong seller, and it arrived in the UK after 10 days or so as expected. It came with thermal paste, which I applied in a cross formation before refitting everything. The G8 is really easy to pull apart, HP really thought about that!&lt;/p&gt;
&lt;p&gt;First boot with the processor went very smoothly, SmartOS recognises it quite happily.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; [root@oscar ~]# sysinfo | grep -i cpu
&amp;quot;CPU Type&amp;quot;: &amp;quot;Intel(R) Xeon(R) CPU E3-1265L V2 @ 2.50GHz&amp;quot;,
&amp;quot;CPU Virtualization&amp;quot;: &amp;quot;vmx&amp;quot;,
&amp;quot;CPU Physical Cores&amp;quot;: 1,
&amp;quot;CPU Total Cores&amp;quot;: 8,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;rsquo;m also happy with the temperatures, even after streaming a couple of videos via plex for an hour or so, whilst backing up a laptop via crashplan, as well as the usual stuff that&amp;rsquo;s always running on the machine, everything was still well within normal ranges.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sensor&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Units&lt;/th&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inlet Ambient&lt;/td&gt;
&lt;td&gt;22.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;40.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P1 DIMM 1-2&lt;/td&gt;
&lt;td&gt;40.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chipset&lt;/td&gt;
&lt;td&gt;56.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chipset Zone&lt;/td&gt;
&lt;td&gt;44.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VR P1 Zone&lt;/td&gt;
&lt;td&gt;61.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iLO Zone&lt;/td&gt;
&lt;td&gt;49.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCI 1 Zone&lt;/td&gt;
&lt;td&gt;40.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sys Exhaust&lt;/td&gt;
&lt;td&gt;48.000&lt;/td&gt;
&lt;td&gt;degrees C&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fan 1&lt;/td&gt;
&lt;td&gt;12.544&lt;/td&gt;
&lt;td&gt;percent&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All in all, great success!&lt;/p&gt;
&lt;p&gt; 
 &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Updated 2018-12-30: &lt;a href="https://twitter.com/tomwardill/"&gt;@tomwardill&lt;/a&gt; &lt;a href="https://twitter.com/tomwardill/status/999002779887824896"&gt;notes&lt;/a&gt; the E3-1230L V3 doesn&amp;rsquo;t fit: &amp;ldquo;The E3-1230L V3 that you list doesn&amp;rsquo;t fit, it&amp;rsquo;s a 1150 socket, not a 1155&amp;rdquo;. The table of candidates has been altered to remove it.&lt;/em&gt;&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Wed, 09 Aug 2017 03:30:23 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/upgrading-microserver-g8-cpu/</guid></item><item><title>Creating icns icons</title><link>https://xenodium.com/creating-icns-icons</link><description>&lt;p&gt;Stack overflow yields &lt;a href="https://stackoverflow.com/questions/12437433/where-can-i-find-icon-composer-on-mac"&gt;Where can i find Icon Composer on Mac?&lt;/a&gt; when I did a quick search to convert a png to icns. For future reference:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;#!/bin/bash -e

set -e
set -o pipefail

if [ &amp;quot;$#&amp;quot; -ne 1 ]; then
 echo &amp;quot;\nusage: to_icns.sh path/to/image.png\n&amp;quot;
 exit 1
fi

readonly IMAGE_FPATH=$1
readonly BASENAME=$(basename ${IMAGE_FPATH%.*})

mkdir ${BASENAME}.iconset

sips -z 16 16   $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_16x16.png&amp;quot;
sips -z 32 32   $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_16x16@2x.png&amp;quot;
sips -z 32 32   $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_32x32.png&amp;quot;
sips -z 64 64   $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_32x32@2x.png&amp;quot;
sips -z 128 128 $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_128x128.png&amp;quot;
sips -z 256 256 $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_128x128@2x.png&amp;quot;
sips -z 256 256 $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_256x256.png&amp;quot;
sips -z 512 512 $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_256x256@2x.png&amp;quot;
sips -z 512 512 $IMAGE_FPATH --out &amp;quot;${BASENAME}.iconset/icon_512x512.png&amp;quot;

cp $IMAGE_FPATH &amp;quot;${BASENAME}.iconset/icon_512x512@2x.png&amp;quot;

iconutil -c icns ${BASENAME}.iconset

rm -R ${BASENAME}.iconset

echo Wrote ${BASENAME}.icns
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 09 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/creating-icns-icons</guid></item><item><title>Half-Baked: Streaming and Public Commons</title><link>https://faingezicht.com/articles/2017/08/09/streaming/</link><description>Last time I went to the library to pick up a book, I noticed a man next to me getting a stack of DVDs. Given the context, my assumption was that this guy probably doesn't pay for a streaming service, and that he probably couldn't afford it, either. People like him, rely on the library to get entertainment and education. This encounter made me think about how technology affects libraries and other public commons.

Physical dead-tree books are not going away anytime soon, as the consumption experience of digital vs. physical is really different, but music and movies are experienced the same way regardless of the format. What happens when we stop making physical DVDs?

In a future where these assets are not physical, but bits on a server to be streamed on-demand, how does the public library work? Libraries exist because we agree to fund the purchase of physical assets that the library can then distribute. The infrastructure required to support this is relatively simple - librarians, land, shelves, a ledger. On the other hand, Netflix, Amazon, HBO, and others have collectively invested millions, if not billions, of dollars in building complex computing infrastructure to stream content to our homes reliably and without lag. How does the local library compete with that?

These streaming services rely on economies of scale and centralization in ways that the government administered library probably can't come close to.

&lt;small&gt;_The "Half-Baked" series is my effort to write more, and put my thoughts out there on the internet, a brain dump, unedited. Just a few minutes of writing. If you find typos, or grammatical errors, let me know. They will be corrected as I notice them, but otherwise the content will remain as published._&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Wed, 09 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/08/09/streaming/</guid></item><item><title>localStorage and sessionStorage in Safari's private mode</title><link>https://muffinman.io/blog/localstorage-and-sessionstorage-in-safaris-private-mode/</link><description>&lt;article class="article"&gt;&lt;p&gt;If you didn&amp;#x27;t know, in Safari&amp;#x27;s private mode both &lt;code&gt;localStorage&lt;/code&gt; and &lt;code&gt;sessionStorage&lt;/code&gt; are not working.
To be exact, Safari sets storage&amp;#x27;s limit to 0, so you can&amp;#x27;t write anything to it.
I keep forgetting this, until QA people report it at some point.&lt;/p&gt;
&lt;p&gt;So I quickly wrote a small facade for it, which fails silently in this case.
That means it still doesn&amp;#x27;t work but it won&amp;#x27;t throw an error and break your application.&lt;/p&gt;
&lt;p&gt;This is the version for &lt;code&gt;localStorage&lt;/code&gt;, just replace it with &lt;code&gt;sessionStorage&lt;/code&gt; if you need it.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token constant"&gt;LS_TEST_KEY&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;ls-test&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;let&lt;/span&gt; isLocalStorageSupported &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;typeof&lt;/span&gt; &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;object&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Try to&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword control-flow"&gt;try&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setItem&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token constant"&gt;LS_TEST_KEY&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;test&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;removeItem&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token constant"&gt;LS_TEST_KEY&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;catch&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;e&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  isLocalStorageSupported &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;false&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// If we get error that we exceeded storage&amp;#x27;s quota&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// but storage is still empty we are in private mode&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;e&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;code&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;DOMException&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token constant"&gt;QUOTA_EXCEEDED_ERR&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;length&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Private mode&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;else&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;throw&lt;/span&gt; e&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;LocalStorage&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function-variable function"&gt;getItem&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;key&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;isLocalStorageSupported&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getItem&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;key&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token keyword null nil"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function-variable function"&gt;setItem&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;key&lt;span class="token punctuation"&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;isLocalStorageSupported&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setItem&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;key&lt;span class="token punctuation"&gt;,&lt;/span&gt; value&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function-variable function"&gt;removeItem&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;key&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;isLocalStorageSupported&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token dom variable"&gt;localStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;removeItem&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;key&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;export&lt;/span&gt; &lt;span class="token keyword module"&gt;default&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;LocalStorage&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 09 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/localstorage-and-sessionstorage-in-safaris-private-mode/</guid></item><item><title>Is JSX still relevant? Are there other options?</title><link>https://goshacmd.com/jsx-relevancy-options/</link><author>Gosha Spark</author><pubDate>Wed, 09 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/jsx-relevancy-options/</guid></item><item><title>Windows and macOS could move to Linux</title><link>https://jasoneckert.github.io/myblog/windows-and-macos-could-move-to-linux/</link><description>&lt;p&gt;&lt;img alt="move to Linux" src="linuxy.png#center" title="move to Linux" /&gt;&lt;/p&gt;
&lt;p&gt;For those in the tech world, the title of this post may seem both radical and pretentious.&lt;/p&gt;
&lt;p&gt;However, in the following four parts of this blog post, I hope to shed light on why this is a real possibility in the not-so-distant future and why.&lt;/p&gt;
&lt;h1 id="part-1-os-overview"&gt;PART 1: OS overview&lt;/h1&gt;
&lt;p&gt;First of all, an operating system (OS) is essentially the core software that allows your computer to run - it provides a core component (called a kernel) that understands how to use the hardware in your computer, a user interface (e.g. your Desktop), as well as a rich set of software libraries and frameworks that allow apps to run.  These software libraries and frameworks are specific to your OS and are often called a platform.  For example, you can develop an app for the Windows platform, or you can develop and app for the macOS or Linux platforms.  When it comes to mobile devices, iOS is just a mobile version of macOS, and Android is just Linux with an Android framework on top - as a result, we can really say that the three main OS platforms available today are Windows, macOS and Linux.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Wed, 09 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/windows-and-macos-could-move-to-linux/</guid></item><item><title>Better Odds For VCs &amp;amp; Founders</title><link>https://blog.eutopian.io/better-odds-for-vcs-founders/</link><description>1500 words, 7 minutes. Fishing Through Ice, Bain News Service. c.1910.
This post is written from the perspective of a VC screening for success factors. In it, I drill deeper into successful operational characteristics. If you&amp;rsquo;re an entrepreneur or founder, you should give consideration to adopting some of the systems I talk about here. I&amp;rsquo;ll even suggest prioritising them over features and fixes to your product because getting imperfect product adopted by many is a better predictor of success than putting perfection in the hands of a few.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 08 Aug 2017 21:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/better-odds-for-vcs-founders/</guid></item><item><title>A Retrospective on Seven Months at Turing</title><link>https://josh.works/turing-retrospective</link><description>&lt;h1 id="collection-of-thoughts-on-turing"&gt;Collection of thoughts on Turing&lt;/h1&gt;

&lt;p&gt;It’s the last week of &lt;a href="https://www.turing.io/"&gt;Turing&lt;/a&gt;. I went through the &lt;a href="https://www.turing.io/programs/back-end-engineering"&gt;backend software engineering program&lt;/a&gt;, and it’s been a journey.&lt;/p&gt;

&lt;p&gt;In no particular order, I’m throwing down thoughts in three general categories:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;What went well&lt;/li&gt;
  &lt;li&gt;What didn’t go well&lt;/li&gt;
  &lt;li&gt;What I might have done differently, were I to do it again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I believe there is a narrow window for me to capture this information well. As soon as I get a job, I’ll probably forget everything that didn’t go well, and if I were to &lt;em&gt;never&lt;/em&gt; get a job, I’d forget anything that went well.&lt;/p&gt;

&lt;h2 id="went-well"&gt;Went well&lt;/h2&gt;

&lt;h3 id="learning"&gt;Learning&lt;/h3&gt;

&lt;p&gt;I’ve learned a ton, and my pace of learning has steadily climbed through Turing, as I build a more and more robust mental for existing information. It’s easier to add new information when the framework for the old stuff is strong.&lt;/p&gt;

&lt;p&gt;I use Anki (a flashcard app) every day, so even on days when I don’t write any code, I’m still getting reps in of practice, and strengthening mental pathways. I’ve used Anki every day since Turing started, and have almost 1000 cards in my programming deck.&lt;/p&gt;

&lt;p&gt;&lt;img alt="review stats" src="/images/Statistics.jpg" /&gt;&lt;/p&gt;

&lt;!--more--&gt;
&lt;h3 id="getting-in-simple-exposure-to-programming"&gt;Getting in simple exposure to programming&lt;/h3&gt;

&lt;p&gt;Quality beats quantity, but at the beginning, I’m simply resigning myself to pursuing quantity.&lt;/p&gt;

&lt;p&gt;I’ve &lt;a href="https://github.com/josh-works"&gt;committed a lot of code&lt;/a&gt;. It’s not &lt;em&gt;good&lt;/em&gt; code, but it’s code, so I’m making progress and learning.&lt;/p&gt;

&lt;p&gt;&lt;img alt="I've committed a lot of code" src="/images/github_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I filled up 1.5 large notebooks with notes and code, and many whiteboards.&lt;/p&gt;

&lt;h3 id="cohort"&gt;Cohort&lt;/h3&gt;

&lt;p&gt;I bonded with the folks I went through Turing with. I think we’ll be friends for a long time, and will try to meet up every now and again. (I hear there’s a trip to a beach in the works for a year from now.)&lt;/p&gt;

&lt;h3 id="outside-of-turing"&gt;Outside of Turing&lt;/h3&gt;

&lt;p&gt;While Turing dominated my time these last seven months, I enjoyed still spending lots of time with Kristi, and I managed to sneak in a surprisingly large amount of rock climbing.&lt;/p&gt;

&lt;p&gt;I’ve been improving in my climbing, but that’s a topic for a different time.&lt;/p&gt;

&lt;h2 id="didnt-go-well"&gt;Didn’t go well&lt;/h2&gt;

&lt;p&gt;I’m technically not graduated yet - I’ve started this a few days before the end of Turing.&lt;/p&gt;

&lt;p&gt;I feel like the quality of my work on the last two big projects was low. I still have a lot to learn about JavaScript and DOM manipulation, and I’ve not yet gotten enough repetition in with those basics to have simple tasks be effortless and quick to achieve.&lt;/p&gt;

&lt;p&gt;So, that’s been a bit stressful. I have generally high standards for my work, and when I can’t meet it, I become convinced that I’m failing everyone else’s standards as well.&lt;/p&gt;

&lt;p&gt;Why did these last two projects go poorly?&lt;/p&gt;

&lt;h3 id="tactical-reasons-they-went-poorly"&gt;Tactical reasons they went poorly&lt;/h3&gt;

&lt;p&gt;I expand on this concept below, but I have a “slow but thorough” learning style. I struggled to spend the time I needed getting in repetition and depth of learning while managing the high rate of work required at Turing.&lt;/p&gt;

&lt;p&gt;If I didn’t have the time to dig deep into something, I’d skip it, and aim to complete the projects.&lt;/p&gt;

&lt;p&gt;If I were going to re-do my module three prework, I’d work through this tutorial three times in a row:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/build-a-restful-json-api-with-rails-5-part-one"&gt;Build a RESTful JSON API With Rails 5 - Part One (DigitalOcean Tutorial)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d find some node/express/deep dives into JavaScript before module four started. I felt a bit behind there as well.&lt;/p&gt;

&lt;h3 id="strategic-reasons-they-went-poorly"&gt;Strategic reasons they went poorly&lt;/h3&gt;

&lt;p&gt;I learn things slowly.&lt;/p&gt;

&lt;p&gt;Some folks at Turing have expressed the incorrection assumption that I learn things quickly, and I try to correct their wrong thinking. I always aim to get early exposure to a topic, and to play with it before I have to use it in any sort of production environment.&lt;/p&gt;

&lt;p&gt;I did a fair amount of work before Turing to gain exposure to the topics we covered in the first half of the program, and consequently had a good frame of reference for the things we learned.&lt;/p&gt;

&lt;p&gt;The topics in the 2nd half of the program I’d gained no prior exposure to, and felt ill-prepared by the recommended pre-work that we did over the intermission weeks.&lt;/p&gt;

&lt;p&gt;For the duration of both of the second mods, I felt behind, simply enough.&lt;/p&gt;

&lt;p&gt;The good news here, though, is given the world of difference that I experienced based soley on prior exposure to a topic… with repeated exposure, I can feel comfortable with just about anything.&lt;/p&gt;

&lt;p&gt;This is encouraging, because I have many years to gain comfort with a range of technologies.&lt;/p&gt;

&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I’m thrilled I did Turing.&lt;/strong&gt; I’m not good at big “summarize this huge thing” write-ups, and much prefer to do small posts on bite-sized topics. So, much more to come on that, down the road.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Would I recommend Turing to someone else?&lt;/strong&gt; It depends. There are some very important non-Turing-related details that lined up nicely for me. If someone else is in the same position and has the same inclination, I’d say go for it. This was well within my range of comfortable risk, because of the following:&lt;/p&gt;

&lt;h6 id="i-had-my-wifes-enthusiastic-support"&gt;I had my wife’s enthusiastic support&lt;/h6&gt;

&lt;p&gt;I cannot overstate how empowering this is. Kristi has been making all of our money this year, on top of managing most of the details of cooking, food prep, etc. Her efforts freed me up to just think about programming, which is a significant advantage. On top of that, she of course provided great emotional support&lt;/p&gt;

&lt;h6 id="id-been-planning-on-something-like-turing-for-over-a-year-before-starting-and-wed-been-saving-money-appropriately-both-for-tuition-and-for-living-expenses-while-in-school"&gt;I’d been planning on something like Turing for over a year before starting, and we’d been saving money appropriately, both for Tuition, and for living expenses while in school&lt;/h6&gt;

&lt;p&gt;Kristi ended up changing jobs shortly after Turing started, and it came with a significant pay increase, so that dramatically changed (for the better) our financial situation while I was in school. Also, turns out you can defer most of your tuition for Turing until after it ends. Those two things left us with more margin in our budget than I’d expected.&lt;/p&gt;

&lt;h6 id="this-wasnt-the-first-time-i-tried-to-learn-software-development"&gt;This wasn’t the first time I tried to learn software development&lt;/h6&gt;

&lt;p&gt;I’ve done the self-study thing for a while before Turing started. That made the first half of the program much smoother sailing for me than they might have been otherwise.&lt;/p&gt;

&lt;h6 id="im-not-a-total-stranger-to-the-world-of-software-development"&gt;I’m not a total stranger to the world of software development&lt;/h6&gt;

&lt;p&gt;I’ve worked for two different software companies before doing Turing. I have a bit of the lay of the land, as it were, of how a “standard” software company fits together. I also spent time doing support and sales (and a bunch of other stuff) for technical software products, so I’m comfortable with the common pain points of software development, and I can speak to the value I’ll bring to a development team. This diminishes any pressure I feel around getting my first development job.&lt;/p&gt;

&lt;p&gt;The sales experience in particular was helpful - I feel no discomfort cold-emailing people and setting up virtual or in-person informational interviews. Since informational interviews are the &lt;em&gt;best&lt;/em&gt; predictor of getting jobs, this feels like a significant advantage.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;These four pieces alleviate lots of potential pressure, and make this a much less risky decision than it might be for someone who doesn’t have this same context and environment.&lt;/p&gt;

&lt;p&gt;That said, if someone is &lt;em&gt;curious&lt;/em&gt; about software development, I’d 100% recommend they &lt;a href="http://trycoding.turing.io/"&gt;kick the tires&lt;/a&gt; with Turing and some online tutorials. Or shoot me an email. We can talk about it. I think it’s a great decision, provided someone knows what they’re getting into, and have set up systems and support for themselves as they move through the program.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Tue, 08 Aug 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/turing-retrospective</guid></item><item><title>Traction</title><link>https://www.wints.org/notes/2017.08.08/</link><description>&lt;p&gt;I just started a newsletter about Keto with my wife and friend. I&amp;rsquo;ve been doing keto for a few months now with great results. And the keto movement is beginning to enter the mainstream.
In all the things I&amp;rsquo;ve put online, or businesses I&amp;rsquo;ve tried to start, this is the first one that I&amp;rsquo;ve experienced any traction.&lt;/p&gt;
&lt;p&gt;I think this is what it feels like to hit a pain point.
Growth hasn&amp;rsquo;t been spectacular, but there&amp;rsquo;s a definite gap and its tangible. First full week - 170 subscribers.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Tue, 08 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.08.08/</guid></item><item><title>2017-08-08</title><link>https://ho.dges.online/pictures/2017-08-08/</link><description/><author>ho.dges.online</author><pubDate>Tue, 08 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-08-08/</guid></item><item><title>Salesloft Team Cadences</title><link>https://solomon.io/team-cadences/</link><description>An average SalesLoft customer has about 10 sales reps using the software. At that size, customers are extremely happy.</description><author>Sam Solomon</author><pubDate>Mon, 07 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/team-cadences/</guid></item><item><title>Proximity Structures: Playing around with PixiJS</title><link>https://www.hallada.net/2017/08/07/proximity-structures.html</link><description>&lt;p&gt;I’ve been messing around with a library called &lt;a href="http://www.pixijs.com/"&gt;PixiJS&lt;/a&gt;
which allows you to create WebGL animations which will fall back to HTML5 canvas
if WebGL is not available in the browser. I mostly like it because the API is
similar to HTML5 canvas which &lt;a href="https://github.com/thallada/thallada.github.io/blob/master/js/magic.js"&gt;I was already familiar
with&lt;/a&gt;. I
can’t say that I like the PixiJS API and documentation that much, though. For
this project, I mostly just used a small portion of it to create &lt;a href="http://www.goodboydigital.com/pixi-webgl-primitives/"&gt;WebGL (GPU
accelerated) primitive
shapes&lt;/a&gt; (lines and
circles).
&lt;!--excerpt--&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Play with it here&lt;/strong&gt;: &lt;a href="http://proximity.hallada.net"&gt;http://proximity.hallada.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read/clone the code here&lt;/strong&gt;: &lt;a href="https://github.com/thallada/proximity-structures"&gt;https://github.com/thallada/proximity-structures&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://proximity.hallada.net"&gt;&lt;img alt="The animation in
action" src="/img/blog/proximity-structures.gif" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea was inspired by
&lt;a href="https://thumb9.shutterstock.com/display_pic_with_logo/3217643/418838422/stock-vector-abstract-technology-futuristic-network-418838422.jpg"&gt;all&lt;/a&gt;
&lt;a href="https://ak5.picdn.net/shutterstock/videos/27007555/thumb/10.jpg"&gt;those&lt;/a&gt;
&lt;a href="https://ak9.picdn.net/shutterstock/videos/10477484/thumb/1.jpg"&gt;countless&lt;/a&gt;
&lt;a href="https://ak3.picdn.net/shutterstock/videos/25825727/thumb/1.jpg"&gt;node&lt;/a&gt;
&lt;a href="https://t4.ftcdn.net/jpg/00/93/24/21/500_F_93242102_mqtDljufY7CNY0wMxunSbyDi23yNs1DU.jpg"&gt;network&lt;/a&gt;
&lt;a href="https://ak6.picdn.net/shutterstock/videos/12997085/thumb/1.jpg"&gt;graphics&lt;/a&gt; that
I see all the time as stock graphics on generic tech articles.&lt;/p&gt;

&lt;p&gt;This was really fun to program. I didn’t care much about perfect code, I just
kept hacking one thing onto another while watching the instantaneous feedback of
the points and lines responding to my changes until I had something worth
sharing.&lt;/p&gt;

&lt;h3 id="details"&gt;Details&lt;/h3&gt;

&lt;p&gt;The majority of the animation you see is based on
&lt;a href="https://en.wikipedia.org/wiki/Inbetweening"&gt;tweening&lt;/a&gt;. Each point has an origin
and destination stored in memory. Every clock tick (orchestrated by the almighty
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame"&gt;requestAnimationFrame&lt;/a&gt;),
the main loop calculates where each point should be in the path between its
origin and destination based on how long until it completes its “cycle”.  There
is a global &lt;code class="language-plaintext highlighter-rouge"&gt;cycleDuration&lt;/code&gt;, defaulted to 60. Every frame increments the cycle
counter by 1 until it reaches 60, at which point it folds over back to 0. Every
point is assigned a number between 1 and 60. This is its start cycle. When the
global cycle counter equals a point’s start cycle number, the point has reached
its destination and a new target destination is randomly chosen.&lt;/p&gt;

&lt;p&gt;Each point is also randomly assigned a color. When a point is within
&lt;code class="language-plaintext highlighter-rouge"&gt;connectionDistance&lt;/code&gt; of another point in the canvas, a line is drawn between the
two points, their colors are averaged, and the points’ colors become the average
color weighted by the distance between the points. You can see clusters of
points converging on a color in the animation.&lt;/p&gt;

&lt;p&gt;Click interaction is implemented by modifying point target destinations within a
radius around the click. Initially, a mouse hover will push points away.
Clicking and holding will draw points in, progressively growing the effect
radius in the process to capture more and more points.&lt;/p&gt;

&lt;p&gt;I thought it was really neat that without integrating any physics engine
whatsoever, I ended up with something that looked sort of physics based thanks
to the tweening functions. Changing the tweening functions that the points use
seems to change the physical properties and interactions of the points. The
elastic tweening function makes the connections between the points snap like
rubber bands. And, while I am not drawing any explicit polygons, just points and
lines based on proximity, it sometimes looks like the points are coalescing into
some three-dimensional structure.&lt;/p&gt;

&lt;p&gt;I’ll probably make another procedural animation like this in the future since it
was so fun. Next time, I’ll probably start from the get-go in ES2015 (or ES7,
or ES8??) and proper data structures.&lt;/p&gt;</description><author>Tyler Hallada - Blog</author><pubDate>Mon, 07 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hallada.net/2017/08/07/proximity-structures.html</guid></item><item><title>On Estimates, Time, and Evidence</title><link>https://ntietz.com/blog/on-estimates-time-and-evidence/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;Here's an exchange that's pretty common:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"How long will that take?"
"A few days."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I run into this all the time with clients - they have real business needs to know how long something will take and what the risks are with any given project. So, we are asked to give estimates of how long tasks will take. Whether in time (2 days) or points (3 points) later used to measure team velocity, these are ultimately an implicit agreement of roughly how long a task will take.&lt;/p&gt;
&lt;p&gt;Much has been written about software estimation techniques. It is alarming how few citations are in these articles, however, given that the claims they make are verifiable -- "X technique is more accurate than Y technique". For a field that claims to be quantitative and data-driven, we use alarmingly little data in our decisions of which tools and techniques to use (ironically, this claim is not one I have data to back up).&lt;/p&gt;
&lt;p&gt;While reading &lt;a href="http://theseniorsoftwareengineer.com/"&gt;"The Senior Software Engineer"&lt;/a&gt;, I came across a claim within it: when you are estimating a task, you will be more accurate if you estimate 1 day's worth of work than 1 week's worth of work, and more accurate if you estimate 1 week's worth of work than 1 month's worth of work. On the face of it, this seems like a very useful result if it is true - unfortunately, no citation was given. So, let's dig in.&lt;/p&gt;
&lt;p&gt;Here is the claim: given two tasks T1 and T2, an estimate will be more accurate if it is for a shorter span of time. There are two subparts to this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What does it mean for an estimate to be accurate?&lt;/li&gt;
&lt;li&gt;Which way of doing estimates is the most accurate?&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="what-is-accuracy"&gt;What is accuracy?&lt;/h1&gt;
&lt;p&gt;Let's assume we have a task T and for that task, we have the estimated time, TE, and the actual time taken, TA. Two possible measures of error come to mind: raw time difference, and percent difference.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Raw time difference:&lt;/em&gt; Error = |TA - TE|&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Percent difference:&lt;/em&gt; Error = |TA - TE| / TE&lt;/p&gt;
&lt;p&gt;In the real world, raw time difference is going to be the most noticeable error, so it may influence how we perceive the accuracy of estimation techniques. On the other hand, percent difference is a more fair comparison, since it allows us to compare wildly different timescales: a raw difference of &lt;em&gt;one day&lt;/em&gt; is clearly very significant if the initial estimate was &lt;em&gt;one hour&lt;/em&gt;, whereas it is relatively inconsequential if the initial estimate was &lt;em&gt;one year&lt;/em&gt;. For the purposes of this article, I will use percent difference when I refer to error, although it is helpful to keep in mind the raw time difference measure as it influences how we perceive accuracy and thus how we perceive different estimation techniques.&lt;/p&gt;
&lt;h1 id="how-we-perceive-time-matters"&gt;How We Perceive Time Matters&lt;/h1&gt;
&lt;p&gt;There are three possible worlds, and our goal is to determine which is the actual world and which are the counterfactual worlds. These world are ones in which:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;estimates are likely to be more accurate if they are for a &lt;em&gt;shorter&lt;/em&gt; time&lt;/li&gt;
&lt;li&gt;estimates are likely to be more accurate if they are for a &lt;em&gt;longer&lt;/em&gt; time&lt;/li&gt;
&lt;li&gt;length of tasks has no impact on the accuracy of estimates&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Many of my coworkers have espoused a belief in world 1, as did "The Senior Software Engineer", so I suspect that that's the industry consensus.&lt;/p&gt;
&lt;p&gt;Let's run through some scenarios to see what these worlds would look like, if they were the actual world. For all the worlds, we will assume that the shorter task, T1, is estimated at 1 week and the longer task, T2, is estimated at 1 month.&lt;/p&gt;
&lt;p&gt;In World 1, the shorter estimate is more likely to be accurate. For the sake of arbitrary numbers, let's say that T1 ends up having 10% error and T2 ends up having 30% error. In this situation, T1's raw time difference would be 0.5 days, and T2's would be 6 days (assuming 20 working days / month, and 5 working days / week). Ouch, that's a lot of slip!&lt;/p&gt;
&lt;p&gt;In World 2, the longer estimate is more likely to be accurate, so we'll say that T1 ends up having 30% error and T2 ends up having 10% error. T1's raw time difference would thus be 1.5 days, and T2's raw time difference would be 2 days. That's still a lot of slip, but the gap has narrowed significantly.&lt;/p&gt;
&lt;p&gt;In World 3, the estimates are equally likely to be accurate, so we'll go in the middle and use 20% error for each. In this world, T1's raw time difference would be 1 day, and T2's raw time difference would be 4 days.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;World&lt;/th&gt;&lt;th&gt;Error (1 week)&lt;/th&gt;&lt;th&gt;Slip (1 week)&lt;/th&gt;&lt;th&gt;Error (1 month)&lt;/th&gt;&lt;th&gt;Slip (1 month)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;10%&lt;/td&gt;&lt;td&gt;0.5 days&lt;/td&gt;&lt;td&gt;30%&lt;/td&gt;&lt;td&gt;6 days&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;30%&lt;/td&gt;&lt;td&gt;1.5 days&lt;/td&gt;&lt;td&gt;10%&lt;/td&gt;&lt;td&gt;2 days&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;20%&lt;/td&gt;&lt;td&gt;1 day&lt;/td&gt;&lt;td&gt;20%&lt;/td&gt;&lt;td&gt;4 days&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Table 1: error and slip (raw time difference) in all three possible worlds.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Note that in all three possible worlds, the raw time difference in a 1 month estimate exceeds the raw time difference of a 1 week estimate, and in worlds 1 and 3, the differences are significant to the point where other confounding factors will probably play a larger role in the total amount of slip than just which of these worlds you are in.&lt;/p&gt;
&lt;p&gt;The point of this exercise is not to show you that we are living in world 1 or world 2 or world 3. The point is to show you that in all possible worlds, it is likely that the slip from a 1 week estimate will be smaller than the slip from a 1 month estimate and that this has &lt;em&gt;absolutely nothing&lt;/em&gt; to do with whether or not shorter estimates are more &lt;em&gt;accurate&lt;/em&gt; than longer estimates.&lt;/p&gt;
&lt;p&gt;This colors our overall perception of whether or not shorter estimates are more accurate than others. Managers and engineers alike will remember a slip of 4 days or 6 days as "about a week", and they'll remember a slip of 0.5 days or 1 day as "a little behind schedule", so at the end of the day world 1 and world 3 both seem like they will favor the mental model that shorter estimates are more accurate, even though that is not true in world 3! The fact that these two very different worlds are difficult to tell apart from "on the ground" should alarm us.&lt;/p&gt;
&lt;h1 id="let-s-use-evidence"&gt;Let's Use Evidence&lt;/h1&gt;
&lt;p&gt;Because our perception can be heavily biased by a lot of factors - as shown above, but also by what we want to be true - we should lean on evidence and scientific studies to determine what is actually true.&lt;/p&gt;
&lt;p&gt;It turns out that even this simple question (are shorter or longer estimates more accurate?) does not readily turn up in the academic literature. This is likely due to my inexperience with searching academic literature (I completed a grand total of one semester of a doctoral program). That inexperience is likely shared among my fellow engineers, and my peers may also not have readily available access to academic literature (fortunately, my undergrad university lets us keep library access for a long time after graduation). The combination of lack of exposure and lack of access to journals makes it fairly unsurprising that our books and blog posts do not reference the literature. It does not make it any less disappointing.&lt;/p&gt;
&lt;p&gt;In general, &lt;a href="http://simula.no/publications/review-studies-expert-estimation-software"&gt;studies show&lt;/a&gt; that we are overly optimistic in our time estimation, such that in complicated tasks, we will be more likely to hit a schedule overrun than in less complicated tasks (and longer tasks are probably more complicated than shorter tasks). Here's a quote from the survey paper:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In sum, the results suggest that bottom-up-based estimates only lead to improved estimation accuracy if the uncertainty of the whole task is high, i.e., the task is too complex to estimate as a whole, and, the decomposition structure activates relevant knowledge only. The validity of these two conditions is, typically, not possible know in advance and applying both top-down and bottom-up estimation processes, therefore, reduces the risk of highly inaccurate estimates.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Decomposing tasks into smaller units of time is helpful when the uncertainty of the task's duration is high, and looking at the task holistically is helpful when the uncertainty of the task's duration is low, and we can't know which it is until we get through the task, so let's do both!&lt;/p&gt;
&lt;p&gt;This matches my intuition. Some large tasks that are straightforward are easy to estimate accurately even though they take a long time: for example, I could tell you with great accuracy how long it would take me to drive my car from my home in Columbus to my inlaws' place in Philadelphia, even though I don't know exactly where we will stop in the middle or for exactly how long. Some small tasks are not straightforward to estimate accurately: it may take three seconds to get my cat into her carrier, but if she's in a feisty mood, it may take as long as ten minutes, or longer.&lt;/p&gt;
&lt;p&gt;I still haven't found an evidence-based answer to the question of whether or not, in general, shorter tasks are more accurately estimated than longer tasks. There are a lot of confounding factors, like how you do estimates in general (which will likely change when you go to estimate a larger project!). I'm not even sure that it's an important question to answer, because the actual accuracy of the estimate is probably not the largest driving factor in deciding how you approach doing estimates.&lt;/p&gt;
&lt;p&gt;What &lt;em&gt;is&lt;/em&gt; important is making sure that we have data to back up our claims when we assert that certain methodologies are better than others. These are testable claims - let's test them.&lt;/p&gt;
&lt;p&gt;Here are some testable claims that I would like to see answers to (note: I haven't actually searched for answers to these; but I &lt;em&gt;have&lt;/em&gt; seen many people, including myself, assert these are true or false without any evidence, just anecdotes):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functional programming makes it easier to write parallel programs&lt;/li&gt;
&lt;li&gt;Functional programming results in less buggy code&lt;/li&gt;
&lt;li&gt;Agile development increases development speed&lt;/li&gt;
&lt;li&gt;Shorter estimates are more accurate than longer estimates&lt;/li&gt;
&lt;li&gt;Open offices are better for productivity/collaboration than individual offices or team offices&lt;/li&gt;
&lt;li&gt;Type-checked languages have fewer production bugs than dynamically typed languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are just a few of the claims that people make, without evidence, which are testable.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Mon, 07 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/on-estimates-time-and-evidence/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Implementing a simple sudo</title><link>https://andrestc.com/post/implementing-sudo/</link><description>&lt;p&gt;One of the exercises of &amp;ldquo;The Linux Programming Interface&amp;rdquo; chapter 38 is about implementing program,
called &lt;code&gt;douser&lt;/code&gt;, that should have the same functionality as the &lt;code&gt;sudo&lt;/code&gt; progam. This means that if you run
&lt;code&gt;$ douser whoami&lt;/code&gt;, this should asks for the &lt;code&gt;root&lt;/code&gt; user password and, if the password matches, should run
the command &lt;code&gt;whoami&lt;/code&gt;, which would print &lt;code&gt;root&lt;/code&gt;. If the &lt;code&gt;-u &amp;lt;user&amp;gt;&lt;/code&gt; flag is used, &lt;code&gt;douser&lt;/code&gt; should ask for
the &lt;code&gt;user&lt;/code&gt; password and execute &lt;code&gt;whoami&lt;/code&gt; on behaf of that user, printing its name.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Sun, 06 Aug 2017 16:17:20 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/implementing-sudo/</guid></item><item><title>Forcing aptX on MacOS bluetooth audio</title><link>https://xenodium.com/forcing-aptx-on-macos-bluetooth-audio</link><description>&lt;p&gt;Bought a pair of QuietComfort 35. Audio quality on MacOS was lagging compared to iOS. Googling led to different posts suggesting the use of Bluetooth Explorer to force aptX usage. Did the trick for me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bluetooth Explorer&lt;/strong&gt; can be downloaded from &lt;a href="https://developer.apple.com/download/more"&gt;https://developer.apple.com/download/more&lt;/a&gt;. Search for Hardware IO tools:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/forcing-aptx-on-macos-bluetooth-audio/download-bluetooth-explorer.png" /&gt;&lt;/p&gt;
&lt;p&gt;Open &lt;strong&gt;Hardware_IO_Tools_for_Xcode_7.3.dmg&lt;/strong&gt; and launch &lt;strong&gt;Bluetooth Explorer&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/forcing-aptx-on-macos-bluetooth-audio/tools-image.png" /&gt;&lt;/p&gt;
&lt;p&gt;Select &lt;strong&gt;Audio Options&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/forcing-aptx-on-macos-bluetooth-audio/audio-options.png" /&gt;&lt;/p&gt;
&lt;p&gt;Check &lt;strong&gt;Force use of aptX&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/forcing-aptx-on-macos-bluetooth-audio/force-aptx.png" /&gt;&lt;/p&gt;
&lt;p&gt;Don't forget to disconnect and reconnect your Bluetooth device.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 06 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/forcing-aptx-on-macos-bluetooth-audio</guid></item><item><title>Shiny (R) Web App Performance - Profiling</title><link>https://lukesingham.com/shiny-r-performance-profiling/</link><description>&lt;p&gt;Introduced at the 2016 R conference, the &lt;code&gt;profvis&lt;/code&gt; package offers a visual way of inspecting the call stack and highlights the most memory and computationally intensive parts of your code.&lt;/p&gt;
&lt;h2 id="run-profvis"&gt;Run Profvis &lt;a class="direct-link" href="https://lukesingham.com/shiny-r-performance-profiling/#run-profvis"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Load library&lt;/span&gt;&lt;br /&gt;library&lt;span class="token punctuation"&gt;(&lt;/span&gt;profvis&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Run profiler on shiny app with optional arg to save output&lt;/span&gt;&lt;br /&gt;profvis&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; runApp&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;'Projects/path_of_app'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class="token punctuation"&gt;,&lt;/span&gt; prof_output &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'/path_to_save_output'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point your app will launch, to get the shiny app code to execute, interact with the parts of the application that you are interested in. Once you have completed the interactions, close the page and press the 'stop' button at the top of the console in RStudio. Profvis will recognise you have stopped running the shiny app, display the profvis interface and &lt;em&gt;optionally&lt;/em&gt; save the file. The file name is randomly generated and should look something like this &lt;code&gt;file108f93bff877b.Rprof&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Each block in the flame graph represents a call to a function, or possibly multiple calls to the same function. The width of the block is proportional to the amount of time spent in that function. When a function calls another function, another block is added on top of it in the flame graph.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Source: &lt;a href="https://profvis.r-lib.org/"&gt;Profvis Overview&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="reload-a-saved-profvis"&gt;Reload a Saved Profvis &lt;a class="direct-link" href="https://lukesingham.com/shiny-r-performance-profiling/#reload-a-saved-profvis"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To reload the saved profvis profile:&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Load saved profvis&lt;/span&gt;&lt;br /&gt;profvis&lt;span class="token punctuation"&gt;(&lt;/span&gt;prof_input &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'/path_to_save_output/file108f93bff877b.Rprof'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="save-as-a-webpage"&gt;Save as a Webpage &lt;a class="direct-link" href="https://lukesingham.com/shiny-r-performance-profiling/#save-as-a-webpage"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can also save as a webpage using the following code:&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Assign to variable&lt;/span&gt;&lt;br /&gt;p &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; profvis&lt;span class="token punctuation"&gt;(&lt;/span&gt;prof_input &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'/path_to_save_output/file108f93bff877b.Rprof'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Save as a webpage&lt;/span&gt;&lt;br /&gt;htmlwidgets&lt;span class="token operator"&gt;::&lt;/span&gt;saveWidget&lt;span class="token punctuation"&gt;(&lt;/span&gt;p&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;"/path_to_save_output/profile.html"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="resources"&gt;Resources &lt;a class="direct-link" href="https://lukesingham.com/shiny-r-performance-profiling/#resources"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.rstudio.com/resources/videos/profiling-and-performance/"&gt;Video of Winston Chang presenting ProfViz&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://blog.rstudio.com/2016/05/23/profiling-with-rstudio-and-profvis/"&gt;Profiling code integrated into RStudio IDE, great for non-shiny code&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Sun, 06 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/shiny-r-performance-profiling/</guid></item><item><title>The Mathematics of 2048: Minimum Moves to Win with Markov Chains</title><link>http://jdlm.info/articles/2017/08/05/markov-chain-2048.html</link><description>&lt;p&gt;&lt;strong&gt;Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2017-09-25&lt;/strong&gt; There was some lively &lt;a href="https://news.ycombinator.com/item?id=15327837"&gt;discussion about this series on Hacker News&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is the first in a series. Next: &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html"&gt;Counting States with Combinatorics&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot of 2048" src="/assets/2048/2048.png" style="width: 40%; float: right; margin-left: 10pt; border: 6pt solid #eee;" /&gt;&lt;/p&gt;

&lt;p&gt;As part of a recent revamp, &lt;a href="http://gabrielecirulli.github.io/2048"&gt;2048&lt;/a&gt;’s “You win!” screen started reporting the number of moves it took to win, which made me wonder: how many moves should it take to win?&lt;/p&gt;

&lt;p&gt;In this post, we’ll answer that question by modeling the game of 2048 as a Markov chain and analyzing it to show that, no matter how well the player plays, &lt;strong&gt;the number of moves required to win the game is at least 938.8 on average&lt;/strong&gt;. This gives us a benchmark — if you can win in around this number of moves, you’re doing pretty well.&lt;/p&gt;

&lt;p&gt;The number of moves needed to win depends on random chance, because the game adds &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles at random. The analysis will also show that the distribution for the minimum number of moves to win has a standard deviation of 8.3 moves, and that its overall shape is well-approximated by a mixture of binomial distributions.&lt;/p&gt;

&lt;p&gt;To obtain these results, we’ll use a simplified version of 2048: instead of placing the tiles on a board, we’ll… throw them into a bag. That is, we’ll ignore the geometric constraints imposed by the board on which tiles can be merged together. This simplification makes our job much easier, because the player no longer has to make any decisions &lt;sup id="fnref:mdp"&gt;&lt;a class="footnote" href="#fn:mdp" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;, and because we don’t have to keep track of where the tiles are on the board.&lt;/p&gt;

&lt;p&gt;The price we pay for relaxing the geometric constraints is that we can only compute a lower bound on the expected number of moves to win; it might be that the geometric constraints make it impossible to attain that bound. However, by playing many games of 2048 (for science!), I’ll also show that we can often get close to this lower bound in practice.&lt;/p&gt;

&lt;p&gt;If you’re not familiar with 2048 or with Markov chains, that’s OK — I’ll introduce the necessary ideas as we go. The (research quality) code behind this article is &lt;a href="https://github.com/jdleesmiller/twenty48"&gt;open source&lt;/a&gt;, in case you’d like to see the code to generate &lt;a href="https://github.com/jdleesmiller/twenty48/blob/27c30f5e42861c87a2162efed38003a9db9e8b29/bin/markov_chain"&gt;the chain&lt;/a&gt; and &lt;a href="https://github.com/jdleesmiller/twenty48/blob/27c30f5e42861c87a2162efed38003a9db9e8b29/data/markov_chain/plot.R"&gt;the plots&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="2048-as-a-markov-chain"&gt;2048 as a Markov Chain&lt;/h2&gt;

&lt;p&gt;To represent our simplified ‘2048 in a bag’ game as a Markov chain, we need to define the &lt;em&gt;states&lt;/em&gt; and the &lt;em&gt;transition probabilities&lt;/em&gt; of the chain. Each state is like a snapshot of the game at a moment in time, and the transition probabilities specify, for each state, which state is likely to come next.&lt;/p&gt;

&lt;p&gt;Here we will define each state to encode which tiles are currently in the bag. We don’t care about the order of the tiles, so we can think of it as a multiset of tiles. Initially, there are no tiles, so our initial state is simply the empty set. In diagram form, which we’ll add to below, this initial state looks like:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="The initial state for the Markov chain" src="/assets/2048/markov_chain_initial_state.svg" /&gt;
&lt;/p&gt;

&lt;h3 id="setting-up-the-board"&gt;Setting up the Board&lt;/h3&gt;

&lt;p align="center"&gt;
&lt;img alt="Montage of a sample of eight setup states." src="/assets/2048/initial_states.png" style="height: 200px;" /&gt;&lt;br /&gt;
A sample of a dozen new game boards.
&lt;/p&gt;

&lt;p&gt;When we start a new game of 2048, the game places two random tiles on the board (see examples above). To represent this in the Markov chain, we need to work out the transition probabilities from the initial state to each of the possible successor states.&lt;/p&gt;

&lt;p&gt;Fortunately, we can look at &lt;a href="https://github.com/gabrielecirulli/2048"&gt;the game’s source code&lt;/a&gt; to find out how the game does this. Whenever the game places a random tile on the board, it always follows the same process: &lt;em&gt;pick an available cell uniformly at random, then add a new tile either with value &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt;, with probability 0.9, or value &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;, with probability 0.1&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For 2048 in a bag, we don’t care about finding an available cell, because we haven’t put any capacity constraint on the bag; we just care about adding either a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile with the given probabilities. This leads to three possible successor states for the initial state:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;\(\{2, 2\}\) when both of the new tiles are &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt;s. This happens with probability \(0.9 \times 0.9 = 0.81\).&lt;/li&gt;
  &lt;li&gt;\(\{4, 4\}\) when both of the new tiles are &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;s. This happens with probability \(0.1 \times 0.1 = 0.01\) — that is, you are pretty lucky if you start with two &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;s.&lt;/li&gt;
  &lt;li&gt;\(\{2, 4\}\) when the new tiles are &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; and then &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;, which happens with probability \(0.9 \times 0.1 = 0.09\), or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; and then &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt;, which happens with probability \(0.1 \times 0.9 = 0.09\). We don’t care about order, so both cases lead to the same state, with total probability \(0.09 + 0.09 = 0.18\).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can add these successor states and their transition probabilities to the Markov chain diagram as follows, where the transition probabilities are written on the edge labels, and the new nodes and edges are shown in blue:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Directed graph showing the initial state and its immediate successors: {2, 2}, {2, 4}, {4, 4}" src="/assets/2048/markov_chain_0.svg" /&gt;
&lt;/p&gt;

&lt;h3 id="playing-the-game"&gt;Playing the Game&lt;/h3&gt;

&lt;p&gt;With the first pair of tiles now placed, we’re ready to start playing the game. In the real game, this means that the player gets to swipe left, right, up or down to try to bring pairs of like tiles together. In the bag game, however, there is nothing to stop us from merging all pairs of like tiles, so that’s what we’ll do.&lt;/p&gt;

&lt;p&gt;In particular, the rule for merging tiles in the bag game is: &lt;em&gt;find all of the pairs of tiles in the bag that have the same value and remove them; then replace each pair of tiles with a single tile with twice the value&lt;/em&gt; &lt;sup id="fnref:merge"&gt;&lt;a class="footnote" href="#fn:merge" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Once pairs of like tiles have been merged, the game adds a single new tile at random using the same process as above — that is, a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile with probability 0.9, or a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile with probability 0.1 — to arrive at the successor state.&lt;/p&gt;

&lt;p&gt;For example, to find the possible successors of the state \(\{2, 2\}\), we first merge the two &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles into a single &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile, and then the game will add either a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile or a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile. The possible successors are therefore \(\{2, 4\}\) and \(\{4, 4\}\), which, as it happens, we have already encountered. The diagram including these two transitions from \(\{2, 2\}\), which have probability 0.9 and 0.1 respectively, is then:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Directed graph showing the additional transitions from the {2, 2} state" src="/assets/2048/markov_chain_1.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;If we follow the same process for the successors of \(\{2, 4\}\), we see that no merging is possible yet, because there is no pair of like tiles, and the successor state will either be \(\{2, 2, 4\}\) or \(\{2, 4, 4\}\), depending on whether the new tile is a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;. The updated diagram is then:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Directed graph showing the additional transitions from the {2, 4} state" src="/assets/2048/markov_chain_2.svg" /&gt;
&lt;/p&gt;

&lt;h3 id="layers-and-skipping"&gt;Layers and ‘Skipping’&lt;/h3&gt;

&lt;p&gt;We can continue adding transitions in this way. However, as we add more states and transitions, the diagrams can become quite complicated &lt;sup id="fnref:dot"&gt;&lt;a class="footnote" href="#fn:dot" rel="footnote"&gt;3&lt;/a&gt;&lt;/sup&gt;. We can make the diagrams a bit more orderly by using the following observation: &lt;strong&gt;the sum of the tiles in the bag increases by either 2 or 4 with each transition&lt;/strong&gt;. This is because merging pairs of like tiles does not change the sum of the tiles in the bag (or on the board — this property also holds in the real game), and the game always adds either a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile or a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;If we group states together into ‘layers’ by their sum, the first few layers look like this:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Directed graph showing states up to sum 12" src="/assets/2048/markov_chain_3.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;For later layers, I’ve also omitted the labels for transitions with probability 0.9 (solid lines, unless otherwise labelled) and 0.1 (dashed lines), to reduce clutter.&lt;/p&gt;

&lt;p&gt;Grouping the states into layers by sum makes another pattern clear: each transition (other than those from the initial state) is either to the next layer, with probability 0.9, or the layer after, with probability 0.1. (This is particularly clear if you look at the layers with sums 8, 10 and 12 in the diagram above.) That is, most of the time the game gives us a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt;, and we’ll transition to the next layer, but sometimes we get lucky, and the game gives us a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;, which means we get to skip a layer, getting us slightly closer to our goal of reaching the 2048 tile.&lt;/p&gt;

&lt;h3 id="the-end-game"&gt;The End Game&lt;/h3&gt;

&lt;p&gt;We could continue this process forever, but since we are only interested in reaching the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile, we’ll stop it at that point by making any state with a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile an &lt;em&gt;absorbing&lt;/em&gt; state. An absorbing state has a single transition, which is to itself with probability 1 — that is, once you reach an absorbing state, you can never leave.&lt;/p&gt;

&lt;p&gt;In this case all of the absorbing states are ‘win states’ — you have a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile and have therefore won the game. There is no way to ‘lose’ the bag game, because unlike in the real game, we cannot get into a situation where the board (or bag) is full.&lt;/p&gt;

&lt;p&gt;The first state that contains a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile is in the layer with sum 2066. It’s notable that you can’t get a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile on its own on the board — it takes a few moves to merge the &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt; tiles, the &lt;code class="language-plaintext highlighter-rouge"&gt;512&lt;/code&gt; tiles, and so on, during which you accumulate more &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles. This is why the sum of the tiles for the first state with a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile is higher than 2048.&lt;/p&gt;

&lt;p&gt;Here’s what the graph looks like around this first winning state (&lt;a href="/assets/2048/markov_chain_end.svg"&gt;see more&lt;/a&gt;), with the absorbing states colored red:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/markov_chain_end.svg"&gt;&lt;img alt="Screenshot of the end of the Markov chain" src="/assets/2048/markov_chain_end_screenshot.png" style="margin: 10px;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;If we continue to add transitions until there are no non-absorbing states left, we eventually end up with 3487 states, of which 26 are absorbing; this completes the definition of the Markov chain. The diagram for the full chain is quite large, but if your device can handle a 5MB SVG file, &lt;a href="/assets/2048/markov_chain_big.svg"&gt;here is a diagram of the full chain&lt;/a&gt; (you may need to scroll down a bit to see the start). When very zoomed out, it looks like this:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/markov_chain_big.svg"&gt;&lt;img alt="Zoomed out view of the whole chain" src="/assets/2048/markov_chain_big_thumbnail.png" style="border: 0;" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h3 id="sampling-from-the-chain"&gt;Sampling from the Chain&lt;/h3&gt;

&lt;p&gt;Now that we have put in the effort to model 2048 (in a bag) as a Markov chain, the simplest way to find out how many moves it takes before we are absorbed is to run simulations. In each simulation, we generate a single trajectory through the chain by starting at the initial state, then choosing a successor state at random in proportion to the transition probabilities, then repeating from that state. After one million simulation runs, the following distribution emerges for the number of moves to win:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Distribution of the number of moves to win, with the mean of 938.8 highlighted" src="/assets/2048/markov_chain_moves_histogram.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;The mean, which is marked by the vertical blue line, comes out at &lt;strong&gt;938.8 moves&lt;/strong&gt;, excluding the first transition from the initial state, with a standard deviation of &lt;strong&gt;8.3 moves&lt;/strong&gt;. So, that’s our answer for the minimum expected number of moves to win the game!&lt;/p&gt;

&lt;p&gt;The theory of Markov chains also lets us calculate some of these properties directly using clever mathematics. In &lt;a href="#appendix-a-analysis-of-the-markov-chain"&gt;Appendix A&lt;/a&gt;, I’ll show how to calculate the mean and standard deviation for the number of moves without relying on simulation. Then, in &lt;a href="#appendix-b-the-shape-of-the-distribution"&gt;Appendix B&lt;/a&gt;, I’ll use some of properties of the chain to offer at least a partial explanation of the shape of the distribution.&lt;/p&gt;

&lt;h2 id="putting-theory-to-the-test"&gt;Putting Theory to the Test&lt;/h2&gt;

&lt;p&gt;Finally, to test these results in real life, I played a lot of 2048 (for science!) and, for the 28 games I won, recorded the number of moves it took and also the sum of the tiles on the board when I reached the 2048 tile &lt;sup id="fnref:changes"&gt;&lt;a class="footnote" href="#fn:changes" rel="footnote"&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Montage of 28 winning games of 2048" src="/assets/2048/wins.png" /&gt;
&lt;/p&gt;

&lt;p&gt;Transcribing these numbers into a spreadsheet and plotting them leads to the following scatter plot:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Moves to Win and Tiles on Board for the 28 games I won" src="/assets/2048/markov_chain_human.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;I’ve marked the minimum expected number of moves, plus or minus one standard deviation, in blue, and the tile sum 2066, which we found to be the lowest sum of tiles for which it was possible to have a 2048 tile, in red.&lt;/p&gt;

&lt;p&gt;The sum of the tiles on the board is important, because when it’s large, that typically means that I made a mistake that left a large tile stranded somewhere I could not merge it with any other tile. It then took many more moves to build up that tile again in a place where it could be merged (or to set up the board to try to get into the right place to merge) with another large tile.&lt;/p&gt;

&lt;p&gt;If I were very good at playing 2048, we’d predict my results would cluster in the bottom left corner of the graph, and that most of them would lie between the dashed blue lines. In fact, we see that, while I sometimes get close to this ideal, I am not very consistent — there are plenty of points in the top right, with lots of extra moves and extra tiles.&lt;/p&gt;

&lt;p&gt;This plot also highlights the fact that this analysis gives us only the minimum &lt;em&gt;expected&lt;/em&gt; number of moves. There were a few games where I got lucky and won in less than 938.8 moves, including one win with 927 moves and a tile sum of 2076. (It is the second from the left in the bottom row of the montage above.) This is essentially because I got a lot of &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles in that game, just by chance, and also because I didn’t make any major blunders that required extra moves.&lt;/p&gt;

&lt;p&gt;In principle, there is non-zero probability that we could win the game in only 519 moves. We can find this by walking through the chain, always taking the transition for the &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt;, and counting the number of transitions required to reach a 2048 tile. However, the probability of this occurring is \(0.1^{521}\), or \(10^{-521}\); there are only about \(10^{80}\) atoms in the observable universe, so you shouldn’t hold your breath waiting for such a game to happen to you. Similarly, if we are very unlucky and always get &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles, we should still be able to win in only 1032 moves. Such a game is much more likely, with a probability of \(0.9^{1034}\), which is about \(10^{-48}\), but you probably shouldn’t hold your breath waiting for that game either. The average of 938.8 moves is much closer to 1032 than 519, because &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles are much more likely than &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this post we have seen how to construct a Markov chain that models how a game of 2048 evolves if it is always possible to merge like tiles. By doing so, we’ve been able to apply techniques from the theory of absorbing Markov chains to calculate interesting properties of the game, and in particular that it takes at least 938.8 moves to win, on average.&lt;/p&gt;

&lt;p&gt;The main simplification that enabled this approach was to ignore the structure of the board, effectively assuming that we threw tiles into a bag, rather than placing them onto the board. In &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html"&gt;my next post&lt;/a&gt;, I plan to look at what happens when we do consider the structure of the board. We’ll see that the number of states we need to consider becomes many orders of magnitude larger (though perhaps not as large as one might think), and also that we will need to leave the world of Markov chains and enter the world of Markov Decision Processes, which allow us to bring the player back into the equation, and in principle may allow us to ‘solve’ the game completely — to find a provably optimal way of playing.&lt;/p&gt;

&lt;h2 id="appendix-a-analysis-of-the-markov-chain"&gt;Appendix A: Analysis of the Markov Chain&lt;/h2&gt;

&lt;p&gt;Once that we’ve defined our Markov chain, we can bring some powerful mathematical machinery to bear to calculate its properties without simulation. Many of these calculations are possible only because our Markov chain is a special type of Markov chain called an &lt;a href="https://en.wikipedia.org/wiki/Absorbing_Markov_chain"&gt;absorbing Markov chain&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The criteria for being an absorbing Markov chain are that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;There must be at least one absorbing state. As we’ve seen above, there are 26 absorbing states, one for each winning state with a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For any state, it is possible to reach an absorbing state in a finite number of transitions. One way to see that this holds for our chain is to observe that there are no loops other than for the absorbing states — except for the absorbing states, the chain is a directed acyclic graph.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="the-transition-matrix"&gt;The Transition Matrix&lt;/h3&gt;

&lt;p&gt;Now that we have established that we have an absorbing Markov chain, the next step is to write out its &lt;em&gt;transition matrix&lt;/em&gt; in &lt;em&gt;canonical form&lt;/em&gt;. A transition matrix is a matrix that organizes the transition probabilities, which we defined for our chain above, such that the \((i, j)\) entry is the probability of transitioning from state \(i\) to state \(j\).&lt;/p&gt;

&lt;p&gt;For the transition matrix, \(\mathbf{P}\), of an absorbing chain with \(r\) absorbing states and \(t\) &lt;em&gt;transient&lt;/em&gt; (which means non-absorbing) states, to be in canonical form, it must be possible to break it up into four smaller matrices, \(\mathbf{Q}\), \(\mathbf{R}\), \(\mathbf{0}\) and \(\mathbf{I}_r\), such that:
\[
\mathbf{P} = \left(
\begin{array}{cc}
 \mathbf{Q} &amp;amp; \mathbf{R} \\\&lt;br /&gt;
 \mathbf{0} &amp;amp; \mathbf{I}_r
\end{array}
\right)
\]
where \(\mathbf{Q}\) is a \(t \times t\) matrix that describes the probability of transitioning from one transient state to another transient state, \(\mathbf{R}\) is a \(t \times r\) matrix that describes the probability of transitioning from a transient state to an absorbing state, \(\mathbf{0}\) denotes an \(r \times t\) matrix of zeros, and \(\mathbf{I}_r\) is the transition matrix for the absorbing states, which is an \(r \times r\) identity matrix.&lt;/p&gt;

&lt;p&gt;To get a transition matrix in canonical form for our chain, we need to decide on an ordering of the states. It suffices to order states (1) by whether they are absorbing, with absorbing states last, then (2) by the sum of their tiles, in ascending order, and finally (3) in lexical order, to break ties. If we do this, we obtain the following matrix:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="The full transition matrix for the absorbing Markov chain" src="/assets/2048/markov_chain_canonical.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;It’s quite large, namely \(3487 \times 3487\), so when zoomed out it just looks pretty much diagonal, but if we zoom in on the lower right hand corner, we can see that it does have some structure, and in particular it has the canonical form that we’re after:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="The lower right hand corner of the transition matrix for the absorbing Markov chain, which shows more structure" src="/assets/2048/markov_chain_canonical_lower_right.svg" /&gt;
&lt;/p&gt;

&lt;h3 id="the-fundamental-matrix"&gt;The Fundamental Matrix&lt;/h3&gt;

&lt;p&gt;With the transition matrix in canonical form, the next step is to use it to find what is called the &lt;em&gt;fundamental matrix&lt;/em&gt; for the chain, which will let us calculate the expected number of transitions before absorption, which is (finally!) the answer to our original question.&lt;/p&gt;

&lt;p&gt;The fundamental matrix, \(\mathbf{N}\), is defined in terms of \(\mathbf{Q}\) by the identity
\[
\mathbf{N} = \sum_{k=0}^{\infty} \mathbf{Q}^k
\]
where \(\mathbf{Q}^k\) denotes the \(k\)th matrix power of \(\mathbf{Q}\).&lt;/p&gt;

&lt;p&gt;The \((i, j)\) entry of \(\mathbf{N}\) has a particular interpretation: it is the expected number of times that we would enter state \(j\) if we followed the chain starting from state \(i\). To see this, we can we observe that, just as the \((i, j)\) entry of \(\mathbf{Q}\) is the probability of transitioning from state \(i\) to state \(j\) in a single transition, the \((i, j)\) entry of \(\mathbf{Q}^k\) is the probability of entering state \(j\) exactly \(k\) transitions after entering state \(i\). If, for a given pair of states \(i\) and \(j\), we add up said probabilities for all \(k \geq 0\), the summation includes every time at which we could possibly enter state \(j\) after state \(i\), weighted by the corresponding probability, which is what gives us the desired expectation.&lt;/p&gt;

&lt;p&gt;Fortunately, the fundamental matrix can also be calculated directly, without the awkward infinite summation, as the inverse of the matrix \(\mathbf{I}_t - \mathbf{Q}\), where \(\mathbf{I}_t\) is the \(t \times t\) identity matrix; that is, \(\mathbf{N} = (\mathbf{I}_t - \mathbf{Q})^{-1}\). (The proof of this identity is left as an exercise for the reader!)&lt;/p&gt;

&lt;h3 id="expected-moves-to-win"&gt;Expected Moves to Win&lt;/h3&gt;

&lt;p&gt;Once we have the fundamental matrix, we can find the expected number of transitions from any state \(i\) to an absorbing state by summing up all of the entries in row \(i\) — in other words, the number of transitions before we reach an absorbing state is the total number of transitions that we spend in all of the transient states along the way.&lt;/p&gt;

&lt;p&gt;We can obtain these row sums for all states at once by calculating the matrix-vector product \(\mathbf{N} \mathbf{1}\), where \(\mathbf{1}\) denotes a column vector of \(t\) ones. Since \(\mathbf{N} = (\mathbf{I}_t - \mathbf{Q})^{-1}\), we can do this efficiently by solving the linear system of equations
\[
(\mathbf{I}_t - \mathbf{Q})\mathbf{t} = \mathbf{1}
\]
for \(\mathbf{t}\). The entry in \(\mathbf{t}\) that corresponds to the initial state (the empty set, \(\{\}\)) is the number of transitions. In this case, the number that comes out is 939.8. To finish up, we just need to subtract \(1\), because the transition from the initial state doesn’t count as a move. This gives our final answer as &lt;strong&gt;938.8 moves&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can also obtain the &lt;a href="https://en.wikipedia.org/wiki/Absorbing_Markov_chain#Variance_on_number_of_steps"&gt;variance&lt;/a&gt; for the minimum number of moves as
\(
2(\mathbf{N} - \mathbf{I}_t) \mathbf{t} - \mathbf{t} \circ \mathbf{t}
\),
where \(\circ\) denotes the &lt;a href="https://en.wikipedia.org/wiki/Hadamard_product_(matrices)"&gt;Hadamard (elementwise) product&lt;/a&gt;. For the initial state, the variance comes out as 69.5, which gives a standard deviation of &lt;strong&gt;8.3 moves&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id="appendix-b-the-shape-of-the-distribution"&gt;Appendix B: The Shape of the Distribution&lt;/h2&gt;

&lt;p&gt;Perhaps remarkably, we were able to calculate both the mean and the variance of the moves-to-win distribution using the fundamental matrix from the Markov chain. It would however be nice to have some insight into why the distribution is the shape that it is. The approach I’ll suggest here is only approximate, but it does match the empirical results from the simulation of the chain quite closely, and it provides some useful insights.&lt;/p&gt;

&lt;p&gt;We’ll begin by revisiting an observation that we made above: the sum of the tiles on the board increases by either 2 or 4 with each transition (other than the first transition from the initial state). If we were interested in hitting a specific sum for the tiles on the board, rather than hitting a &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile, then it’s relatively straightforward to calculate the required number of transitions using the binomial distribution, as we’ll see below.&lt;/p&gt;

&lt;p&gt;So, the next question is, which sum should we aim to hit? From the Markov chain analysis above, we determined that there are 26 absorbing (winning) states, and we’ve also seen that they are in different ‘sum layers’, so there isn’t a single target sum — there are several target sums. What we need to know is the probability of being absorbed in each state, which is called an &lt;em&gt;absorbing probability&lt;/em&gt;. We can then add up the absorbing probabilities for each of the absorbing states in a particular sum layer to find a probability of winning with a given target sum.&lt;/p&gt;

&lt;h3 id="absorbing-probabilities"&gt;Absorbing Probabilities&lt;/h3&gt;

&lt;p&gt;Fortunately, the absorbing probabilities can also be found from the fundamental matrix. In particular, we can obtain them by solving the linear equations
\[
(\mathbf{I}_t - \mathbf{Q}) \mathbf{B} = \mathbf{R}
\]
for the \(t \times r\) matrix \(\mathbf{B}\), whose \((i, j)\) entry is the probability of being absorbed in state \(j\) when starting from state \(i\). As before, we are interested in the absorbing probabilities when we start from the initial state. Plotting out the absorbing probabilities, there are 15 absorbing states for which the probabilities are large enough to plot (at least \(10^{-3}\)):&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Absorbing probabilities for the Markov chain" src="/assets/2048/markov_chain_absorbing_probabilities.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;In particular, most games end in either the \(\{2,2,8,8,2048\}\) state, which has sum 2068, or the \(\{2,4,16,2048\}\) state, which has sum 2070. Summing up all of the absorbing states by layer sum gives the complete layer sum probabilities:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Total absorbing probabilities by sum of tiles" src="/assets/2048/markov_chain_sum_probabilities.svg" /&gt;
&lt;/p&gt;

&lt;h3 id="binomial-probabilities"&gt;Binomial Probabilities&lt;/h3&gt;

&lt;p&gt;Now that we have some sums to aim for, and we know how often we are aiming for each one, the next question is, how many moves does it take to hit a particular sum? As noted above, we can think of this in terms of the &lt;a href="https://en.wikipedia.org/wiki/Binomial_distribution"&gt;Binomial distribution&lt;/a&gt;, which lets us calculate the probability of a given number of “successes” out of a given number of “trials”.&lt;/p&gt;

&lt;p&gt;In this case, we’ll consider a “trial” to be a move, and a “success” to be a move in which the game gives us a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile; as we’ve seen above, this happens with probability 0.1. A “failure” here is a move in which the game gives us a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile, which happens with probability 0.9.&lt;/p&gt;

&lt;p&gt;With this interpretation of successes, in order to hit a given sum \(S\) in \(M\) moves, we need \(\frac{S}{2} - M\) successes out of \(M\) moves. This is because each move counts at least \(2\) toward the sum, which contributes a total of \(2M\), and each success counts an additional \(2\) toward the sum, for a total contribution of \(2 \left(\frac{S}{2} - M\right) = S - 2M\); adding these contributions together leaves the desired sum, \(S\).&lt;/p&gt;

&lt;p&gt;The joint probability of obtaining a sum \(S\) in a number of moves \(M\) is then Binomial, and in particular
\[
\mathrm{Pr}(M=m, S=s) = B\left(\frac{s}{2} - m; m, 0.1\right)
\]
where \(B(k; n, p)\) is the probability mass function for the binomial distribution, which gives the probability of exactly \(k\) successes in \(n\) trials, where the probability of success is \(p\), namely
\[
B(k; n, p) = {n\choose k}p^k(1-p)^{n-k}
\]
where \(n \choose k\) denotes a &lt;a href="https://en.wikipedia.org/wiki/Binomial_coefficient"&gt;binomial coefficient&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now if we know the target sum \(S\) that we are aiming for, we can compute the conditional distribution of the number of moves given that sum, which is what we are interested in, from the joint distribution. That is, we can find \(\mathrm{Pr}(M | S)\) as
\[
\mathrm{Pr}(M | S) = \frac{\mathrm{Pr}(M, S)}{\mathrm{Pr}(S)}.
\]
where \(\mathrm{Pr}(S)\) is obtained from the joint distribution by summing out \(M\) for each possible sum \(S\). It’s worth noting that \(\mathrm{P}(S)\) is less than one for each possible sum, because there’s always a chance that the game ‘skips’ the sum by placing a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;With these conditional distributions for each target sum in hand, we can then add them up, weighted by the total absorbing probability for the target sum, to obtain the overall distribution. This gives a fairly good match to the distribution from the simulation:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Simulated and binomial mixture model distributions for minimum moves to win" src="/assets/2048/markov_chain_weighted_mixture.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;Here the simulated distribution is shown with the grey bars, and the colored areas show each of the conditional distributions, which are stacked. Each conditional distribution is scaled according to the total absorbing probability for its sum, and also shifted a few moves, with larger sums requiring more moves on average.&lt;/p&gt;

&lt;p&gt;One interpretation of this result is that, if playing optimally, the number of moves to win is essentially determined by how quickly the player can get to a sum large enough to have a 2048 tile, which is in turn governed by the number of &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles, which follows a binomial distribution.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://twitter.com/h0peth0mas"&gt;Hope Thomas&lt;/a&gt; and &lt;a href="https://natestemen.github.io/"&gt;Nate Stemen&lt;/a&gt; for reviewing drafts of this article.&lt;/p&gt;

&lt;p&gt;If you’ve read this far, perhaps you should &lt;a href="https://twitter.com/jdleesmiller"&gt;follow me on twitter&lt;/a&gt;, or even apply to work at &lt;a href="https://www.overleaf.com/jobs"&gt;Overleaf&lt;/a&gt;. &lt;code class="language-plaintext highlighter-rouge"&gt;:)&lt;/code&gt;&lt;/p&gt;

&lt;h2 id="footnotes"&gt;Footnotes&lt;/h2&gt;





&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:mdp"&gt;
      &lt;p&gt;If we do allow the player to make decisions, we have a &lt;a href="https://en.wikipedia.org/wiki/Markov_decision_process"&gt;Markov Decision Process&lt;/a&gt;, rather than a Markov chain. That will be the subject of a later blog post. &lt;a class="reversefootnote" href="#fnref:mdp"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:merge"&gt;
      &lt;p&gt;Merging pairs of like tiles in this way captures an important nuance of the merging logic in the real game: if you have, for example, four &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles in a row, and you swipe to merge them, the result is two &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles, not a single &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile. That is, you can’t merge newly merged tiles on a single swipe. &lt;a class="reversefootnote" href="#fnref:merge"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:dot"&gt;
      &lt;p&gt;The diagrams here come from the excellent &lt;code class="language-plaintext highlighter-rouge"&gt;dot&lt;/code&gt; tool in &lt;a href="http://www.graphviz.org/"&gt;graphviz&lt;/a&gt;. If we don’t give &lt;code class="language-plaintext highlighter-rouge"&gt;dot&lt;/code&gt; a hint by grouping the states together into layers by sum, laying out the full graph can take quite a while. &lt;a class="reversefootnote" href="#fnref:dot"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:changes"&gt;
      &lt;p&gt;The appearance of the game’s “You win!” screen changed several times over the months in which I collected this data. For the record, playing 2048 was not the only thing I did during these months. &lt;a class="reversefootnote" href="#fnref:changes"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>jdlm.info</author><pubDate>Sat, 05 Aug 2017 12:00:00 GMT</pubDate><guid isPermaLink="true">http://jdlm.info/articles/2017/08/05/markov-chain-2048.html</guid></item><item><title>Server and client for SnailLife Go</title><link>https://liza.io/server-and-client-for-snaillife-go/</link><description>&lt;p&gt;Over the last couple of days I restructured SnailLife Go into a server and client. I&amp;rsquo;m still in the &amp;ldquo;rough draft&amp;rdquo; stage, but the top level project structure now looks like this:&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 05 Aug 2017 08:05:10 GMT</pubDate><guid isPermaLink="true">https://liza.io/server-and-client-for-snaillife-go/</guid></item><item><title>All Python Assert Methods In One List</title><link>https://www.mattcrampton.com/blog/a_list_of_all_python_assert_methods/</link><description>Every Python Assert Method in One List I am constantly looking up assert methods on the Python 2 Unit Test Documentation and it's driving me crazy because that page is super long and hard to mentally parse. The lists of assert methods available are broken up in different sections on the page and I'm done searching around it. Writing unit tests in Python obviously requires heavy use of assert methods, but for some reason they're buried in the Python documentation. So here's a compiled list of all of them for my reference, but maybe this is useful for someone else out there too... Python Assert Methods Method Checks Version assertEqual a == b &amp;nbsp; assertNotEqual a != b &amp;nbsp; assertTrue bool(x) is True &amp;nbsp; assertFalse bool(x) is False &amp;nbsp; assertIs a is b 2.7 assertIsNot a is not b 2.7 assertIsNone x is None 2.7 assertIsNotNone x is not None 2.7 assertIn a in b 2.7 assertNotIn a not in b 2.7 assertIsInstance is instance(a,b) 2.7 assertNotIsInstance not is instance(a,b) 2.7 asse...</description><author>MattCrampton.com</author><pubDate>Fri, 04 Aug 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/a_list_of_all_python_assert_methods/</guid></item><item><title>Links - August 04, 2017</title><link>https://faingezicht.com/links/2017/08/04/links/</link><description/><author>Avy Faingezicht</author><pubDate>Fri, 04 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/08/04/links/</guid></item><item><title>SIGGRAPH 2017 Course Notes- Recent Advances in Disney's Hyperion Renderer</title><link>https://blog.yiningkarlli.com/2017/08/recent-advances-in-hyperion.html</link><description>&lt;p&gt;This year at SIGGRAPH 2017, Luca Fascione and Johannes Hanika from Weta Digital organized a Path Tracing in Production course.
The course was split into two halves: a first half about production renderers, and a second half about using production renderers to make movies.
Brent Burley presented our recent work on Disney’s Hyperion Renderer as part of the first half of the course.
To support Brent’s section of the course, the entire Hyperion team worked together to put together some course notes describing recent work in Hyperion done for &lt;em&gt;Zootopia&lt;/em&gt;, &lt;em&gt;Moana&lt;/em&gt;, and upcoming films.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/course_notes_zootopia.png"&gt;&lt;img alt="Image from course notes Figure 8: a production frame from &amp;lt;em&amp;gt;Zootopia&amp;lt;/em&amp;gt;, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/course_notes_zootopia.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the abstract for the course notes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Path tracing at Walt Disney Animation Studios began with the Hyperion renderer, first used in production on Big Hero 6. Hyperion is a custom, modern path tracer using a unique architecture designed to efficiently handle complexity, while also providing artistic controllability and efficiency.
The concept of physically based shading at Disney Animation predates the Hyperion renderer. Our history with physically based shading significantly influenced the development of Hyperion, and since then, the development of Hyperion has in turn influenced our philosophy towards physically based shading.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The course notes and related materials can be found at:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://jo.dreggn.org/path-tracing-in-production/2017/index.html"&gt;Official Course Resources Page (Full course notes and supplemental materials)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.yiningkarlli.com/projects/ptcourse2017.html"&gt;Project Page (Author’s Version)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://dl.acm.org/citation.cfm?doid=3084873.3084904"&gt;Official Print Version (ACM Library)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The course wasn’t recorded due to proprietary content from various studios, but the overall course notes for the entire course cover everything that was presented.
The major theme of our part of the course notes (and Brent’s presentation) is replacing multiple scattering approximations with accurate brute-force path-traced solutions.
Interestingly, the main motivator for this move is primarily a desire for better, more predictable and intuitive controls for artists, as opposed to simply just wanting better visual quality.
In the course notes, we specifically discuss fur/hair, path-traced subsurface scattering, and volume rendering.&lt;/p&gt;

&lt;p&gt;The Hyperion team also had two other presentations at SIGGRAPH 2017:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ralf Habel presented several sections of the “&lt;a href="https://graphics.pixar.com/library/ProductionVolumeRendering/"&gt;Production Volume Rendering&lt;/a&gt;”” course, which was jointly put together by Julian Fong and Magnus Wrenninge from Pixar Animation Studios, Christophe Kulla from Sony Imageworks, and Ralf Habel from Walt Disney Animation Studios.&lt;/li&gt;
  &lt;li&gt;Peter Kutz presented our “&lt;a href="https://blog.yiningkarlli.com/2017/07/spectral-and-decomposition-tracking.html"&gt;Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes&lt;/a&gt;” technical paper in the “Rendering Volumes” papers session.&lt;/li&gt;
&lt;/ul&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Fri, 04 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2017/08/recent-advances-in-hyperion.html</guid></item><item><title>Adding copyright notices to papers</title><link>https://bastian.rieck.me/blog/2017/adding_copyright_notices/</link><description>&lt;p&gt;Much has been written about the sorry state of academic publishing.
Luckily for me, the visualization community works with a number of
publishers that are very sane, welcoming, and considerate with respect
to personal copies of papers. All of them permit the free use of
pre-prints on a personal website as long as it contains a text similar
to the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Author&amp;rsquo;s Copy. Find the definitive version at example.com/doi/12345&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After doing this manually for a couple of papers, I finally decided to
solve it directly in LaTeX. This is what I came up with: first, you need
to add &lt;code&gt;\usepackage[absolute]{textpos}&lt;/code&gt; to the preamble of your
document. Next, add the following lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\setlength{\TPHorizModule}{\paperwidth}
\setlength{\TPVertModule} {\paperheight}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;They ensure that the subsequent calls for placing text work with respect
to the current paper size. In order to place a copyright notice at the
top of your paper, you only have to do the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\begin{textblock*}{20cm}(0.5cm,0.5cm)
  Author's copy. To appear in IEEE Transactions on Visualization and Computer Graphics.
\end{textblock*}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Place this somewhere in your document, for example directly after
&lt;code&gt;\begin{document}&lt;/code&gt; and you should be good to go.&lt;/p&gt;
&lt;p&gt;Happy publishing!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Thu, 03 Aug 2017 19:39:50 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/adding_copyright_notices/</guid></item><item><title>Yosemite</title><link>https://faingezicht.com/photos/2017/08/03/yosemite/</link><description>After many months of planning our trip to Yosemite, it finally happened. Taylor and Zoë flew in for the weekend, and on Friday evening after work we took off. We picked up Amol in the East Bay, and kept going towards the Sierra. None of us had been there before, except for Hannah.</description><author>Avy Faingezicht</author><pubDate>Thu, 03 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/08/03/yosemite/</guid></item><item><title>How to assess your level of preparation for the tech interviews</title><link>https://shankhs.com/how-to-assess-your-level-of-preparation-for-the-tech-interviews/</link><description>PREPARATION. PREPARATION. PREPARATION. Preparation is the key to be successful in any interview and land that job or internship that you always wanted. When you decide you need a job, the first thing you do is evaluate your preparation level. Self-assessment can be tricky. Sometimes we are over confident, and sometimes we are under confident. &amp;#8230; &lt;a class="more-link" href="https://shankhs.com/how-to-assess-your-level-of-preparation-for-the-tech-interviews/"&gt;Continue reading &lt;span class="screen-reader-text"&gt;How to assess your level of preparation for the tech interviews&lt;/span&gt; &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>shankhs</author><pubDate>Tue, 01 Aug 2017 18:51:34 GMT</pubDate><guid isPermaLink="true">https://shankhs.com/how-to-assess-your-level-of-preparation-for-the-tech-interviews/</guid></item><item><title>Migration to Ghost v1.0</title><link>https://rjp.is/blogging/posts/migration-to-ghost-v1-0/</link><description>In which we start to get annoyed by Ghost.</description><author>infrequent oscillations</author><pubDate>Tue, 01 Aug 2017 12:38:22 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/migration-to-ghost-v1-0/</guid></item><item><title>More Fatter + Sidewalk Chalk</title><link>https://faingezicht.com/photos/2017/08/01/fatterchalk/</link><description/><author>Avy Faingezicht</author><pubDate>Tue, 01 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/08/01/fatterchalk/</guid></item><item><title>2017-08-01</title><link>https://ho.dges.online/pictures/2017-08-01/</link><description/><author>ho.dges.online</author><pubDate>Tue, 01 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-08-01/</guid></item><item><title>TNValidate is now open source</title><link>https://nestenius.se/net/tnvalidate-is-now-open-source/</link><description>Our internal validation library TNValidate is now available as a project on GitHub. We released this as open source because we wanted to let others take</description><author>Tore Nestenius</author><pubDate>Tue, 01 Aug 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nestenius.se/net/tnvalidate-is-now-open-source/</guid></item><item><title>Windows "vintage" default desktop colours</title><link>http://blog.pythonaro.com/2017/07/windows-vintage-default-desktop-colours.html</link><description>Note to self: these are the default desktop background colours for old Windows versions.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="background-color: teal;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;b&gt;008080&lt;/b&gt; (RGB 000-128-128) - Windows 95/98&lt;/li&gt;
&lt;li&gt;&lt;span style="background-color: #3a6ea5;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;b&gt;3A6EA5&lt;/b&gt; (RGB 058-110-165) - Windows 2000&lt;/li&gt;
&lt;/ul&gt;
(I know you love them, even if setting a wallpaper was the first thing you did after logging on a new PC. It's called nostalgia.)</description><author>Subclassed</author><pubDate>Mon, 31 Jul 2017 22:03:56 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2017/07/windows-vintage-default-desktop-colours.html</guid></item><item><title>Handler 机制深入理解（Handler、Looper、MessageQueue）</title><link>https://0xzhangke.github.io/computer/2017/07/31/android_handler.html</link><description>&lt;h2 id="handler"&gt;Handler&lt;/h2&gt;
&lt;p&gt;Handler 主要用于在不同的线程中相互通信，使用场景最多的应该就是在子线程中更新 UI。
与 Handler 相关的类：
&lt;strong&gt;Handler&lt;/strong&gt;：处理与发送消息（Message）
&lt;strong&gt;Message&lt;/strong&gt;：消息的包装类
&lt;strong&gt;Looper&lt;/strong&gt;：整个 Handler 通信的核心，接受 Handler 发送的 Message，循环遍历 MessageQueue 中的 Message，并发送至 Handler 处理
&lt;strong&gt;MessageQueue&lt;/strong&gt;：保存 Message
&lt;strong&gt;LocalThread&lt;/strong&gt;：存储 Looper 与 Looper所在线程的信息&lt;/p&gt;

&lt;p&gt;关系流程图：&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/assets/img/post/handler/1.webp" /&gt;&lt;/p&gt;

&lt;p&gt;上图简单概括为：&lt;strong&gt;Handler 将 Message post 或者 send 到 MessageQueue 中，Looper 不断循环从 MessageQueue 中取出 Message 交由 Handler 来处理。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="handler-消息处理"&gt;Handler 消息处理&lt;/h3&gt;
&lt;p&gt;Handler 处理消息的方法为 dispatchMessage：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;/**
 * Handle system messages here.
 */
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;①判断 Message.callback 是否为空，不为空则交给 callback 处理；
②判断 Handler.callback 是否为空，不为空则调用mCallback.handleMessage(msg) 处理；
③如果前面都为空，则调用 Handler.handleMessage(msg) 方法处理。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;所以我们可以通过重写 dispatchMessage方法来改变这种默认的消息分发顺序。&lt;/p&gt;

&lt;p&gt;一般来说，我们都是按照如下的方式使用 Message&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Message message = mHandler.obtainMessage();
message.what = 0;
message.obj = "123";
mHandler.sendMessage(message);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;我们很少在 Message 中使用 callback，那么 这个 callback究竟又是什么？&lt;/p&gt;
&lt;h3 id="handler-消息发送"&gt;Handler 消息发送&lt;/h3&gt;

&lt;h4 id="post-方式"&gt;post 方式&lt;/h4&gt;

&lt;p&gt;刚刚说到，Handler 发送 Message 有两类方法：post 和 send 。其中最常用的就是 send 方法了，下面来看一个使用 post 的例子：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mHandler.post(new Runnable() {
    @Override
    public void run() {
        //do something
    }
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;打开 post(Runnable) 方法：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;public final boolean post(Runnable r){
    return  sendMessageDelayed(getPostMessage(r), 0);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中把  Runnable 参数通过 getPostMessage() 方法包装成了 Message 消息，然后继续使用 send 方式发送到 MessageQueue 中去。
那么继续打开 getPostMessage 方法：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;到这里就很明白了，先获取一个 Message 对象，然后把 Runnable 赋值给 m.callback，继而使用 send 方式发送。也就是说，post 方法本质上也是 send 方法，只不过对 Runnable 做了一层包装。
&lt;em&gt;PS：我们平时自定义 View 时，如果想要在主线程做某些操作一般会使用 post(Runnable r) 方法，其实这个方法也是调用了 Handler 的 post 方法，将该 Runnable send 到主线程的 MessageQueue 中。&lt;/em&gt;&lt;/p&gt;
&lt;h4 id="send-方式"&gt;send 方式&lt;/h4&gt;
&lt;p&gt;通过各种调用之后，最终会调用 sendMessageAtTime 发送消息&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;先获取到 MessageQueue ，然后判断是否为空，不为空则调用 enqueueMessage 方法&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里其实&lt;strong&gt;最终就调用了 MessageQueue 的 enqueueMessage 方法了，这个方法就是使 Message 对象入列。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="messagequeue"&gt;MessageQueue&lt;/h2&gt;
&lt;p&gt;MessageQueue 就是一个队列，具有一个队列的一般特征：
①元素入队：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;boolean enqueueMessage(Message msg, long when)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;②元素出队：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Message next()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;③删除元素：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;void removeMessages(Handler h, int what, Object object)
void removeMessages(Handler h, Runnable r, Object object)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="looper"&gt;Looper&lt;/h2&gt;
&lt;p&gt;在整个 Handler 通信机制中，Looper 才是重头戏，Looper 就好比计算机的 CPU，控制整个通信系统的正常运转。
通过上面的介绍我们知道，Handler 负责发送与处理消息，MessageQueue 负责存储消息，Message 是消息的载体，那么他们之间到底是怎样的结合起来的？当然靠的是 Looper，Looper 通过循环遍历 MessageQueue ，当有消息时就发送到 Handler 中处理。&lt;/p&gt;

&lt;p&gt;道理很简单，但实际可能要稍微复杂点，首先这里需要明确几个概念：
&lt;strong&gt;① 每个 Thread 对应一个 Looper
② 每个 Looper 对应一个 MessageQueue
③ 每个 MessageQueue 对应多个 Message
④ 每个 Message 最多只能指定一个 Handler 处理&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;当我们在普通线程中使用 Handler 时，一般方式如下：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;class LooperThread extends Thread{
    public Handler handler;
    @Override
    public void run() {
        super.run();
        Looper.prepare();//准备工作
        handler = new Handler(){
            @Override
            public void dispatchMessage(Message msg) {
                super.dispatchMessage(msg);
                //处理消息
            }
        };
        Looper.loop();//进入主循环
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;到了这里我们大概会有一个疑问，无论是 Handler 的创建还是 Handler.sendMessage() 都没有和 Looper 产生联系，那么当我们使用 Handler 发送消息时，是如何确保这个消息与 Looper 关联起来的呢？&lt;/p&gt;

&lt;p&gt;看上面的代码，首先通过 Looper 的静态方法 Looper.prepare(); 开始准备工作，这个方法的核心代码如下：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;先不管 sThreadLocal 是个什么东西，首先判断 sThreadLocal.get() 是否为空，如果为空则抛出一个运行时异常：Only one Looper may be created per thread ，这个异常很常见，当你在一个线程中多次调用 Looper.prepare(); 时就会抛出这个异常，这里保证每个线程只有一个 Looper 对象。如果 sThreadLocal.get() 返回空，则调用 sThreadLocal.set(new Looper(quitAllowed)) 方法，将 Looper 对象放入 sThreadLocal 中，挺简单的几行代码，逻辑也很清晰，那在看看 sThreadLocal 到底是个什么东西。&lt;/p&gt;

&lt;p&gt;其在 Looper 中的定义为：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;static final ThreadLocal&amp;lt;Looper&amp;gt; sThreadLocal = new ThreadLocal&amp;lt;Looper&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其实到这里我们大概能判断出来 ThreadLocal 是一个用来存储 Looper 的东西。
我们只需要关心上面用到的 sThreadLocal.get 和 sThreadLocal.set 方法，先看 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;/**
 * Returns the value in the current thread's copy of this
 * thread-local variable.  If the variable has no value for the
 * current thread, it is first initialized to the value returned
 * by an invocation of the {@link #initialValue} method.
 *
 * @return the current thread's value of this thread-local
 */
public T get() {
    Thread t = Thread.currentThread();//先获取当前线程的对象
    ThreadLocalMap map = getMap(t);
    if (map != null) {
//把当前线程的对象当做 key，获取 Looper，判断当前线程的 Looper 是否已经存在
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    return setInitialValue();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个方法主要就是获取当前线程的 Looper 对象，再来看 set 方法：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;大意就是把当前线程的信息 Looper 保存到 ThreadLocal 中。&lt;/p&gt;

&lt;p&gt;到了这我们大概就能明白了，&lt;strong&gt;Looper.prepare 就是在当前线程中创建一个 Looper 对象，并且保证只有一个 Looper 存在。&lt;/strong&gt;
可以看到，sThreadLocal 与 Looper.prepare 都是静态方法，Looper 对象也是保存在静态变量中，那么也就是说，当我们的 App 启动时，sThreadLocal 变量就已经存在并且保存了主线程的 Looper，当后面我们在子线程中使用 Handler 时，就会继续把该线程的 Looper对象保存到 sThreadLocal 中。&lt;/p&gt;

&lt;p&gt;罗里吧嗦扯了半天，那么回过头来看看刚刚的那个问题，Handler  如何与 Looper 关联起来？
我们来看看 Handler 的默认构造方法，最终调用的构造器代码如下：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;public Handler(Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class&amp;lt;? extends Handler&amp;gt; klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &amp;amp;&amp;amp;
                (klass.getModifiers() &amp;amp; Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
        }
    }
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;主要在于 11 行和 16 行，调用 Looper.myLooper() 方法将 Looper 对象赋值给当前 Handler 中的 mLooper，在调用 mLooper.mQueue 将 Looper 中的 MessageQueue 赋值给 mQueue。&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;到了这里整个 Handler 通信的机制就已经很明确了，再来个大概的总结：
&lt;strong&gt;① 使用 Looper.prepare(); 做初始化操作，该方法会在当前线程中创建一个唯一的 Looper 对象；
② 创建 Handler 对象，Handler 在创建时就会与当前线程中的 Looper 对象与 MessageQueue 对象绑定；
③ Looper.loop() 启动循环。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="activitythread-中的-handler"&gt;ActivityThread 中的 Handler&lt;/h2&gt;
&lt;p&gt;ActivityThread 与普通线程使用 Looper.prepare(); 不同，这里使用 Looper.prepareMainLooper(); 来初始化：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个函数除了会调用 prepare 之外，主要的功能就是将当前线程（也就是主线程）的 Looper 赋值给 sMainLooper 变量，这样就可以使用 Looper.getMainLooper() 获取主线程的 Looper。
另外 Handler 的创建跟普通线程也有一定的区别：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;if (sMainThreadHandler == null) {
    sMainThreadHandler = thread.getHandler();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在 ActivityThread 的 mian 函数中，会先实例化一个 ActivityThread 对象，然后通过这个对象的 getHandler 方法获取 Handler。&lt;/p&gt;

&lt;p&gt;这个 Handler 用于处理主线程中的各种消息，其中已经定义了很多处理消息的操作，例如启动 Activity 、内存管理等操作，只要发送通过这个 Handler 发送相关的 Message 即可，而 ActivityThread 之所以要讲这个 Handler 赋值给其中的静态变量  sMainThreadHandler 也是因为要通过这个 Handler来发送相关的消息。&lt;/p&gt;

&lt;p&gt;初始化结束后就开始进入消息循环（ Looper.loop ）的阶段，这个方法就是用于不停地接受 Handler 发送过来的各种消息，并交给 Handler 来处理：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;
    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        // This must be in a local variable, in case a UI event sets the logger
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println("&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        final long traceTag = me.mTraceTag;
        if (traceTag != 0 &amp;amp;&amp;amp; Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
        try {
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        if (logging != null) {
            logging.println("&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; Finished to " + msg.target + " " + msg.callback);
        }
        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }
        msg.recycleUnchecked();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里就是开始一个死循环，看其中的 36 行，接受到消息后交给 Handler 的 dispatchMessage 方法来处理。&lt;/p&gt;

&lt;p&gt;END&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;p&gt;[1]林学森. 深入理解Android内核设计思想[M]. 北京, 2014.&lt;/p&gt;</description><author>张可的博客</author><pubDate>Mon, 31 Jul 2017 17:54:03 GMT</pubDate><guid isPermaLink="true">https://0xzhangke.github.io/computer/2017/07/31/android_handler.html</guid></item><item><title>I’m having some trouble with the truffle console.</title><link>https://olshansky.info/posts/2017-07-31-im-having-some-trouble-with-the-truffle-console/</link><description>When I type “Vo” and click tab, it autocompletes to Voting as expecting.</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 31 Jul 2017 13:17:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-07-31-im-having-some-trouble-with-the-truffle-console/</guid></item><item><title>Talks</title><link>https://andrestc.com/talks/</link><description>&lt;p&gt;This list contains some of the major conference talks that I did in the past years.&lt;/p&gt;
&lt;h2 id="2018"&gt;&lt;strong&gt;2018&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Linux Delay Accounting&lt;/strong&gt; at Gophercon (Lightning Talk) &lt;a href="https://speakerdeck.com/andrestc/linux-delay-accounting"&gt;[Slides]&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=_aCw-uZ4KXA"&gt;[Video]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Understanding Go Memory Allocation&lt;/strong&gt; at Gophercon UK &lt;a href="https://speakerdeck.com/andrestc/understanding-go-memory-allocation-gophercon-uk"&gt;[Slides]&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=3CR4UNMK_Is"&gt;[Video]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Entendendo Alocação de memória no Go&lt;/strong&gt; at The Developers Conferece SP (PT-BR) &lt;a href="https://speakerdeck.com/andrestc/entendendo-alocacao-de-memoria-no-go"&gt;[Slides]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Developers Conference&lt;/li&gt;
&lt;li&gt;Gophercon Brazil &lt;a href="https://www.youtube.com/watch?v=Qc-tgDkU7VI"&gt;[Video]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Containers na Globo.com - Passado, Presente e Futuro&lt;/strong&gt; (PT-BR) &lt;a href="//www.slideshare.net/andrestc/containers-na-globocom-passado-presente-e-futuro"&gt;[Slides]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;QCon São Paulo &lt;a href="https://www.youtube.com/watch?v=K1qV_BcD5oU&amp;amp;list=PLoxsuhBe-jd8LgY7Y6G2UZl0d0c5ikfGt&amp;amp;index=69"&gt;[Video]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cloud Computing Rio de Janeiro Meetup&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2017"&gt;&lt;strong&gt;2017&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go Execution Tracer&lt;/strong&gt; at Gophercon Brasil &lt;a href="//www.slideshare.net/andrestc/go-execution-tracer"&gt;[Slides]&lt;/a&gt;&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Mon, 31 Jul 2017 03:21:12 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/talks/</guid></item><item><title>Zipping around the Solar System</title><link>https://walkabout165.blogspot.com/2017/07/freely-zipping-around-solar-system.html</link><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinXXw5zl7L9Esj3pOM6mCq6JH8z1ymgxTy3Zn3t-v_hobzMqHIF7L1dtZIR2FYryMmRbbhIjlA9WmLDOv7gisb5mLvmr-g6n_CiBJsppBHAWBKrmXcpK8jYitwyjAvzBvU9gHEWnjzgpYu/s1600/delta_v_map_of_solar_system.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinXXw5zl7L9Esj3pOM6mCq6JH8z1ymgxTy3Zn3t-v_hobzMqHIF7L1dtZIR2FYryMmRbbhIjlA9WmLDOv7gisb5mLvmr-g6n_CiBJsppBHAWBKrmXcpK8jYitwyjAvzBvU9gHEWnjzgpYu/s320/delta_v_map_of_solar_system.png" width="263" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
So I was researching on another technical musing, related to navigation in the solar system. &amp;nbsp;And I really enjoyed this map I came across by Reddit user &lt;i&gt;ucarion&lt;/i&gt;&amp;nbsp;which shows the delta-v's required to get to different orbits of interest in the solar system. &amp;nbsp;And its format is very intuitive, being the same as the globally popular subway map style. &lt;br /&gt;
&lt;br /&gt;
What I've been thinking about is a way for a vehicle to be piloted around the solar system with impunity. &amp;nbsp;i.e. not having to be restricted to the hohmann transfers and planetary momentum captures &amp;nbsp;commonly used by NASA to get to Mars and other planetary bodies. &lt;br /&gt;
&lt;br /&gt;
Right now, the limiting factor as I see it is the fact that we are very propellant-poor in our current means of pushing ourselves around the solar system. &amp;nbsp;By contrast, energy (for adding kinetic energy to propellant) is less of a concern, as it can be generated from a variety of sources. &lt;br /&gt;
&lt;br /&gt;
My motivation to get this solved? &amp;nbsp;Exploration, but I recognize that our economy won't expend real currency at the problem unless there's the potential for financial return. &amp;nbsp;So to that I suggest asteroid capture e.g. like Planetary Resources advocates for. &lt;br /&gt;
&lt;br /&gt;
What do we do with a big asteroid? &amp;nbsp;No doubt you can think of your own application from them. &amp;nbsp;From my perspective, precious metals aside, lets say people living on Earth want to start spreading out across it - e.g. for lower rent or more agricultural area. &amp;nbsp;Then you can envision massive tropical colonies in the Pacific Ocean's international waters as advocated for by seasteading companies! &amp;nbsp;Where is the material going to come from to build floating landforms that covers millions of square kilometers? &amp;nbsp;Most countries aren't going to let you displace from land from theirs, and environmental advocates are going to make it politically difficult for you to dredge up enough material from the sea floor. &amp;nbsp;How about material harvested from asteroids instead? &lt;br /&gt;
&lt;br /&gt;
But back to the propellant problem. &amp;nbsp;Where are we going to get all the propellant we need to navigate with impunity around the asteroid belt and bring massive material mined from the asteroids back over and down into Earth's low-earth-orbit (LEO) for eventual transport down to the Earth's surface? &lt;br /&gt;
&lt;br /&gt;
I bring you:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEKP_DoUPFCSUs1f26tibfzLGiVrAXvJBD_GwPMylZcSIOUCq6vGIZTLBnHXdU61BUg06QHkipgdtM0Nm75x48TqNgXSBrEgzqdftV0dPpNjpwUksgvZRtrqN4yewJDRTfwSypNTTjFKB-/s1600/Jupiter.jpg" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEKP_DoUPFCSUs1f26tibfzLGiVrAXvJBD_GwPMylZcSIOUCq6vGIZTLBnHXdU61BUg06QHkipgdtM0Nm75x48TqNgXSBrEgzqdftV0dPpNjpwUksgvZRtrqN4yewJDRTfwSypNTTjFKB-/s320/Jupiter.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;span style="font-size: large;"&gt;Jupiter!&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Yes, the Jovian monstrosity can be monstrously helpful in our quest to zip around the solar system for economic and exploration gain! &amp;nbsp;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
How? &amp;nbsp;Simple! &amp;nbsp;Jupiter's atmosphere is packed with gaseous hydrogen. &amp;nbsp;We just need to capture *lots* of it on an ongoing basis to fuel our spacefaring adventures! &amp;nbsp;So how do we get it?&amp;nbsp;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
First, we need to get away from the incumbent paradigm of chemical rocketry. &amp;nbsp;It's too expensive to bring fuel and oxidizer to orbit. Enter nuclear technology. &amp;nbsp;Normally I'm bearish on nuclear for terrestrial activity for its hazard potential, but in space, its a wonderful thing. &amp;nbsp;According to wikipedia (yes I'm citing wikipedia, deal with it) fission-heated hydrogen gas rockets can achieve twice the exhaust velocity (twice the specific impulse for rocket aficionados) than hydrogen in a chemical rocket. &amp;nbsp;That's basically more bang for our propellant buck. &amp;nbsp;But even more importantly, we don't have to bring any oxidizer on a fission rocket, we only need fissile rods for replacing every once in a while, (and they are much easier transport for their small size than chemical fuel). &amp;nbsp;We are just heating the propellant gas to high pressure and then releasing it through a rocket nozzle. &amp;nbsp;So, we don't need to find and harvest oxidizer somewhere or send up expensively from Earth.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
To first order, I advocate for having many such automated fission-powered rockets making round-trips to Jupiter, equipped with a very wide scoop to harvest Jovian hydrogen as propellant for itself and for other vessels it will transfer to. &amp;nbsp;The scooper craft doesn't need to descend far down into Jupiter stratosphere at all - because the craft is traveling so fast and Jupiter is so vast. &amp;nbsp;The craft will naturally slow as it gathers gas, but it can still even wildly overshoot Jupiter afterward, because it can use the propellant it just gathered to change to the opposite direction, only to gather more propellant for its return leg for delivering onward.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Then we'll want to set up propellant "coaling stations" at key Lagrange points like Jupiter's L1 as well as in sun-centric orbits that allow for easy interception - effectively a supply chain in space. &amp;nbsp;Our asteroid-mining craft can then transact at these coaling stations to collect propellant and travel where they may. &amp;nbsp;No more propellant-hoarding, no more strict Hohmann transfers. Just get to where you need to go and come back whenever you're ready.&amp;nbsp;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Going back to the Solar System Subway Map image at top, there are three primary phases of travel from one planet to another that apply here. &amp;nbsp;Surface-to-LEO, &amp;nbsp;LEO-to-Earth-intercept, and Earth-intercept-to-Jupiter-intercept. &amp;nbsp;The nuclear (fission) powered gas scoopers lend themselves to Jupiter-intercepting transfers. &amp;nbsp;Origin: perhaps Earth intercept only initially, but before long one of the coaling stations.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Then what about the other two transit phases? &amp;nbsp;Maybe I'll save the detail for another technical musing since I have to go, but I advocate for maglev / hyperloop-esque mass drivers to get from the Earth's surface to LEO (massively reduced cost to orbit - no expended propellant required!) and yes, chemical rockets to go from LEO to intercept. &amp;nbsp;Why chemical rockets and not fissile ones? &amp;nbsp;Because I don't think people on Earth will stand for having a nuclear reactor in LEO that could come down in the event of an accident and create a Fukushima-like incident. &amp;nbsp;So there still is a place for the chemical rocket industry (chemical rocket industry lobbyists rejoice!), but luckily now over the long term this industry only has to bring its own oxidizer from Earth, since the hydrogen is already going to be there courtesy of Jupiter. :)&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;</description><author>The Walkabout Blog</author><pubDate>Sun, 30 Jul 2017 21:07:59 GMT</pubDate><guid isPermaLink="true">https://walkabout165.blogspot.com/2017/07/freely-zipping-around-solar-system.html</guid></item><item><title>Using Aleph to calculate the homology of 2-manifolds</title><link>https://bastian.rieck.me/blog/2017/aleph_homology_2_manifolds/</link><description>&lt;p&gt;In a &lt;a href="https://bastian.rieck.me/blog/2017/homology_statistics_2_manifolds/"&gt;previous article&lt;/a&gt;,
I discussed the distribution of Betti numbers of triangulations of
2-manifolds. This article now discusses the code. Coincidentally, it
also demonstrates how to use &lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, my (forthcoming) library for exploring persistent homology and its uses.&lt;/p&gt;
&lt;p&gt;Aleph is header-only, so it can be readily deployed in your own
projects. In the following, I am assuming that you have installed Aleph,
following the &lt;a href="https://pseudomanifold.github.io/Aleph/building"&gt;official instructions&lt;/a&gt;.
There are several &lt;a href="https://pseudomanifold.github.io/Aleph/tutorials"&gt;tutorials&lt;/a&gt; available that cover different parts of the persistent homology calculation process. For our purpose, viz. the calculation of homology of triangulated spaces, no large machinery is needed. We start with some includes and &lt;code&gt;using&lt;/code&gt; directives:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;aleph/topology/io/LexicographicTriangulation.hh&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;aleph/persistentHomology/Calculation.hh&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;aleph/topology/Simplex.hh&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;aleph/topology/SimplicialComplex.hh&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;VertexType&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;Simplex&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aleph&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;topology&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Simplex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VertexType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;SimplicialComplex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aleph&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;topology&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SimplicialComplex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Simplex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nothing fancy happened so far. We set up a &lt;em&gt;simplex&lt;/em&gt; class, which is the
basic data type in most applications, as well as a &lt;em&gt;simplicial complex&lt;/em&gt;,
which is the basic storage class for multiple simplices. The only
interesting thing is our choice of &lt;code&gt;DataType&lt;/code&gt; and &lt;code&gt;VertexType&lt;/code&gt;. Since
our simplices need not store any additional data except for their
vertices, we select &lt;code&gt;bool&lt;/code&gt; as a data type in order to make the class
smaller. This could potentially be achieved with &lt;a href="https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Empty_Base_Optimization"&gt;EBCO&lt;/a&gt;
as well, but I did not yet have time to test it adequately. In addition
to the data type, we use &lt;code&gt;unsigned short&lt;/code&gt; as the vertex type—the
triangulations that we want to analyse only feature 9 or 10 vertices, so
&lt;code&gt;unsigned short&lt;/code&gt; is the best solution for storing vertex identifiers.&lt;/p&gt;
&lt;p&gt;Next, we need some I/O code to read a lexicographic triangulation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="k"&gt;return&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argv&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SimplicialComplex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplicialComplexes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;aleph&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;topology&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LexicographicTriangulationReader&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;simplicialComplexes&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nl"&gt;K&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;simplicialComplexes&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createMissingFaces&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, we used the &lt;code&gt;LexicographicTriangulationReader&lt;/code&gt;, a reader class that supports reading files in the &lt;a href="http://page.math.tu-berlin.de/~lutz/stellar/mixed.html"&gt;format&lt;/a&gt; defined by &lt;a href="http://page.math.tu-berlin.de/~lutz"&gt;Frank H. Lutz&lt;/a&gt;. However, this format only provides the top-level simplices of a triangulation. Hence, for a 2-manifold, only the 2-simplices are specified. For calculating homology groups, however, &lt;em&gt;all&lt;/em&gt; simplices are required. Luckily, the &lt;code&gt;SimplicialComplex&lt;/code&gt; class offers a method for just this purpose. By calling &lt;code&gt;createMissingFaces()&lt;/code&gt;, all missing faces of the simplicial complex are calculated and added to the simplicial complex. Afterwards, we use &lt;code&gt;sort()&lt;/code&gt; to sort simplices in lexicographical order. This order is required to ensure that the homology groups can be calculated correctly—the calculation routines assume that the complex is being &lt;a href="https://en.wikipedia.org/wiki/Filtration_(mathematics)"&gt;&amp;quot;&lt;em&gt;filtrated&lt;/em&gt;&amp;quot;&lt;/a&gt;, so faces need to precede co-faces.&lt;/p&gt;
&lt;p&gt;Having created and stored a list of simplicial complexes, we may now finally calculate their homology groups by adding the following code &lt;em&gt;after&lt;/em&gt; the last &lt;code&gt;for&lt;/code&gt;-loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nl"&gt;K&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;simplicialComplexes&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;dualize&lt;/span&gt;                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;includeAllUnpairedCreators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;diagrams&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 class="n"&gt;aleph&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;calculatePersistenceDiagrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                          &lt;span class="n"&gt;dualize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                          &lt;span class="n"&gt;includeAllUnpairedCreators&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code calls &lt;code&gt;calculatePersistenceDiagrams()&lt;/code&gt;, which is usually
employed to calculate, well, a set of persistence diagrams. The two
flags &lt;code&gt;dualize&lt;/code&gt; and &lt;code&gt;includeAllUnpairedCreators&lt;/code&gt; also deserve some
explanation. The first flag only instructs the convenience function as
to whether the boundary matrix that is required for (persistent)
homology calculations should be dualized or not. Dualization was
&lt;a href="https://people.mpi-inf.mpg.de/~mkerber/bkrw-pphat.pdf"&gt;shown&lt;/a&gt; to result
in faster computations, so of course we want to use it as well. The
second parameter depends on our particular application scenario.
Normally, the persistent homology calculation ignores &lt;em&gt;all&lt;/em&gt; creator
simplices in the top dimension. The reason for this is simple: if we
expand a neighbourhood graph to a Vietoris–Rips complex, the
top-level simplices are an artefact of the expansion process. Most of
these simplices cannot be paired with higher-dimensional simplices,
hence they will appear to create a large number of high-dimensional
holes. The persistent homology calculation convenience function hence
ignores those simplices for the creation of persistence diagrams by
default. For &lt;em&gt;our&lt;/em&gt; application, however, keeping those simplices is
actually the desired behaviour—the top-level simplices are
well-defined and an integral part of the triangulation.&lt;/p&gt;
&lt;p&gt;As a last step, we want to print the signature of Betti numbers for the
given simplicial complex. This is easily achieved by adding a nested
loop at the end of the &lt;code&gt;for&lt;/code&gt;-loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nl"&gt;diagram&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;diagrams&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;diagram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dimension&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"b_"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;" = "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;diagram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;betti&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will give us all non-zero Betti numbers of the given triangulation.
The output format is obviously not optimal—in a research setting,
I like to use &lt;a href="http://www.json.org"&gt;JSON&lt;/a&gt; for creating human-readable
and machine-readable results. If you are interested in how this may look, please take a look at a &lt;a href="https://github.com/Pseudomanifold/Aleph/blob/master/src/tools/wicked_triangulations.cc"&gt;more involved tool for dealing with triangulations&lt;/a&gt;. Be aware, however, that this tool is still a work in progress.&lt;/p&gt;
&lt;p&gt;This concludes our little foray into Aleph. I hope that I piqued your interest! By the way, I am always looking for contributors…&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 30 Jul 2017 19:03:11 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/aleph_homology_2_manifolds/</guid></item><item><title>PyOhio</title><link>https://ntietz.com/blog/pyohio-2017/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;This was my first time going to PyOhio, and it was a blast. There will be some videos being posted soon, so I will opt to link to those as they come in, but first, here are some of the highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ed Finkler of &lt;a href="https://osmihelp.org/"&gt;OSMI&lt;/a&gt; gave a great talk on mental illness in tech, resources that are available, what OSMI does, etc. This topic &lt;em&gt;needs&lt;/em&gt; to be discussed more (and I will have a very personal post about it myself coming soon). If you have the means, please consider donating to them.&lt;/li&gt;
&lt;li&gt;I learned about how to use a Raspberry Pi, Redis, and some engineering Rube Goldberg goodness to measure how much coffee is left in the pot from &lt;a href="https://www.linkedin.com/in/yanigisawa/"&gt;James Alexander&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;There were some amazing lightning talks on Saturday evening, made even more amazing by the fact that the projector didn't work for half of them and &lt;em&gt;they went on anyway&lt;/em&gt; (more on this later).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/sublimemarch"&gt;Stephanie Slattery&lt;/a&gt; gave an &lt;em&gt;incredible&lt;/em&gt; talk on accessibility and really inspired me to ensure that everything I do is as accessible as it can be. It's good for both ethical and financial reasons -- how often is it that incentives align that well? Let's seize the opportunity and make the world better by making our tech improve the lives for all our users, instead of excluding a fifth of them.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/andrewwwolfe"&gt;Andrew Wolfe&lt;/a&gt; gave a great and humorous talk where he detailed how he built out the software for BrokerSavant, the challenges faced in scaling a machine learning pipeline (and some solutions!), and ironically technical difficulties started on a slide about unexpected technical difficulties.&lt;/li&gt;
&lt;li&gt;Our general counsel at &lt;a href="https://dacatime.com"&gt;DACA Time&lt;/a&gt; attended a few talks and got visibly animated and excited about coding, which just, in so many ways, fills me with joy. Law and code aren't &lt;em&gt;that&lt;/em&gt; different and are probably equally opaque to most people. Why not use one to solve the other?&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kcunning"&gt;Katie Cunningham&lt;/a&gt; discussed the ways in which technical interviews are often done &lt;em&gt;very poorly&lt;/em&gt; and some of the ways you can fix it (often by just not doing things; for example, just don't whiteboard, it doesn't actually give you the info you think it gives you).&lt;/li&gt;
&lt;li&gt;Thanks to my &lt;a href="https://en.wikipedia.org/wiki/Escitalopram"&gt;medication&lt;/a&gt;, for the first time in my life, I was able to go up to two different speakers and initiate conversations with them. I was also able to initiate conversations with multiple audience members when I identified shared connections between us. This seems like a normal thing to be able to do, but for most of my life, I thought it was normal to just have crippling fear of talking to people, so I never initiated conversations with anyone else. (Again, consider donating to &lt;a href="https://osmihelp.org"&gt;OSMI&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;I had to miss a really good talk on mentoring because I had not eaten all day and did not want to pass out during my lightning talk later. The good news is that it was recorded, so I will still get to see it later!&lt;/li&gt;
&lt;li&gt;Lightning talks happened! As mentioned earlier, there were technical difficulties before but they were resolved. So I figured that I would be golden for my own, right? I was wrong. My laptop (running Ubuntu, so, you know) did not play nice with the projector, even with an audience member's adapter. What did I do? The only natural thing: describe and act out the GIFs I wanted to use. It was okay!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I had a great time overall, and I can't wait to post links to some of the videos of these great talks. (And hopefully there will be an embarrassing video in which I act out some cute GIFs.)&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Sun, 30 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/pyohio-2017/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Homology statistics for 2-manifolds</title><link>https://bastian.rieck.me/blog/2017/homology_statistics_2_manifolds/</link><description>&lt;p&gt;For a new (forthcoming) research project, I have to brush up my
knowledge about homology groups and triangulations. This constitutes
an excellent opportunity to extend &lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;,
my (also forthcoming) library for exploring persistent homology
and its uses.&lt;/p&gt;
&lt;p&gt;As a quick example, I decided to calculate some statistics about the
homology of 2-manifolds. Thanks to the work of &lt;a href="http://page.math.tu-berlin.de/~lutz/stellar/mixed.html"&gt;Frank H.  Lutz&lt;/a&gt;,
a list of triangulations with up to 9 vertices, as well as a list of
triangulations with 10 vertices, exist. After adding support for the
appropriate data format in Aleph, I was able to easily read a family
of triangulations and subsequently process them. Even though Aleph’s
main purpose is the calculation of &lt;em&gt;persistent&lt;/em&gt; homology, ordinary homology
calculations work just as well—ordinary homology being a special
case of persistent homology.&lt;/p&gt;
&lt;p&gt;As a starting point for further mathematical ruminations, let us take
a look at the distribution of &lt;a href="https://en.wikipedia.org/wiki/Betti_number"&gt;&amp;ldquo;Betti numbers&amp;rdquo;&lt;/a&gt; of 2-manifolds. More precisely, we analyse the distribution
of the first Betti number of the manifold—according to
&lt;a href="https://en.wikipedia.org/wiki/Poincar%C3%A9_duality"&gt;Poincaré duality&lt;/a&gt;, the zeroth and second Betti number have
to equal, and we know the zeroth Betti number to be 1 for a manifold.&lt;/p&gt;
&lt;p&gt;Without further ado, here is a tabulation of first Betti numbers for
triangulations with up to 9 vertices:&lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Value&lt;/th&gt;
    &lt;th&gt;Number of occurrences&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;73&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;154&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;313&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;133&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;37&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;The results are interesting: most triangulations appear to have the
homology of a torus, i.e. a first Betti number of 2, followed by the
homology of the real projective plane with a first Betti number of 1.
Betti numbers larger than 3 are extremely rare. Intuitively, this makes
sense—the triangulation only consists of at most 9 vertices, so
there are natural limits on how high the Betti number can become.&lt;/p&gt;
&lt;p&gt;For triangulations with 10 vertices, another distribution arises:&lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Value&lt;/th&gt;
    &lt;th&gt;Number of occurrences&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;233&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;1210&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;6571&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;11784&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;14522&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;7050&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;1042&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;14&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Here, the &lt;em&gt;mode&lt;/em&gt; of Betti numbers is a value of 4, with 14522
occurrences out of 42426 triangulations. The homology type of
this signature is the one of a genus-4 surface. Again, higher
values get progressively less likely because only 10 vertices
are permitted.&lt;/p&gt;
&lt;p&gt;I am not yet sure what to make of this, but it sure is a nice
test case and application scenario for Aleph. One of the next
blog posts will give more details about this calculation, and
its implementation using the library. Stay tuned!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 30 Jul 2017 01:53:30 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/homology_statistics_2_manifolds/</guid></item><item><title>My 85 year-old grandpa's to-do app</title><link>https://www.wints.org/notes/2017.07.29/</link><description>&lt;p&gt;A very successful salesman for 50+ years, my grandpa recently retired at the ripe old age of 85.&lt;/p&gt;
&lt;p&gt;Even though he doesn&amp;rsquo;t work anymore, he still follows a similar routine, including sticking to his system for getting things done.&lt;/p&gt;
&lt;p&gt;With writing that&amp;rsquo;s probably legible only to himself, he lists out the tasks for the next day on a diary page.
He carries that piece of paper, folded up in his pocket, crossing off tasks as he completes them.
If a task is not completed by the end of day, it&amp;rsquo;s meticulously copied over to the next day.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Sat, 29 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.29/</guid></item><item><title>Benford’s Law as a Fraud Detection technique</title><link>https://trigonaminima.github.io/2017/07/benfords-law-fraud-detection/</link><description>Recently, I picked up a handy technique for narrowing down the dataset to look for fraud anomalies - Benford’s Law. It basically states that, in a collection of naturally occurring numerical values, the frequency of the first digit follows a exponential decreasing trend as digit goes from 1 to 9.</description><author>Playground</author><pubDate>Sat, 29 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2017/07/benfords-law-fraud-detection/</guid></item><item><title>Go auth (and other) progress</title><link>https://liza.io/go-auth-and-other-progress/</link><description>&lt;h2 id="july-28"&gt;July 28&lt;/h2&gt;
&lt;p&gt;Made a bit more progress on the authentication basics today. Relevant commits are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/drakonka/gosnaillife/commit/ecb83ff72a47842d471ccad5ed7f5eedc5dfe3ca"&gt;Add http package; have auth0 test delete user it has just registered after test is done&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/drakonka/gosnaillife/commit/9fd17c89b582c8844e826403c4fbd05f2561bb78"&gt;Create json util; add logout test&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="july-29"&gt;July 29&lt;/h2&gt;
&lt;p&gt;Today I focused a bit on the building and installation of &lt;code&gt;snaillifecli&lt;/code&gt;. I switched my custom app configuration code for &lt;a href="https://github.com/spf13/viper"&gt;Viper&lt;/a&gt; because it apparently integrates really well with &lt;a href="https://github.com/spf13/cobra"&gt;Cobra&lt;/a&gt;, which is a library to help make CLI applications. It is really tempting to avoid plugging in existing libraries and write everything from scratch because I&amp;rsquo;m positive that it will teach me a lot about Go, but the existing solutions seem more than suitable and I want to get to working on actual snails at some point.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Fri, 28 Jul 2017 22:31:06 GMT</pubDate><guid isPermaLink="true">https://liza.io/go-auth-and-other-progress/</guid></item><item><title>Importance of Deadlines</title><link>https://www.wints.org/notes/2017.07.28/</link><description>&lt;p&gt;TLDR; with a deadline looming, my productivity shot up exponentially.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve had mixed feelings about deadlines. Having perfectionist tendencies, I often felt that they prevent me from doing my best work.
When I do the best work I can do, I feel extremely satisfied. Like a craftsman after a finished piece of work.
However, this also leads to a lot of unfinished projects.&lt;/p&gt;
&lt;p&gt;On the flip side, when deadlines have been set, my productivity goes up by multiples, and I experience a different sort satisfaction - the joy of solving a problem.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 28 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.28/</guid></item><item><title>Review: Breville Boss To Go Blender</title><link>https://solomon.io/breville-boss-to-go-blender-review/</link><description>The Breville Boss To Go is a sleek, powerful personal blender with a die-cast metal driveshaft. It easily liquifies leafy greens and finely grinds seeds.</description><author>Sam Solomon</author><pubDate>Fri, 28 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/breville-boss-to-go-blender-review/</guid></item><item><title>Playing with authentication in Go</title><link>https://liza.io/playing-with-authentication-in-go/</link><description>&lt;p&gt;It&amp;rsquo;s almost 2am and I&amp;rsquo;m sleepy, but I wanted to write this down while it&amp;rsquo;s relatively fresh in my mind.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Fri, 28 Jul 2017 02:52:49 GMT</pubDate><guid isPermaLink="true">https://liza.io/playing-with-authentication-in-go/</guid></item><item><title>The Sanity Test</title><link>https://rjp.is/blogging/posts/the-sanity-test/</link><description>In which we are salty about some Perl.</description><author>infrequent oscillations</author><pubDate>Thu, 27 Jul 2017 14:42:26 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/the-sanity-test/</guid></item><item><title>Beating The Samson Option</title><link>https://blog.eutopian.io/beating-the-samson-option/</link><description>1300-1600 words, 6 1/2 to 8 1/2 minutes.
An Etching of Samson by Julius Schnorr von Carolsfeld, from an 1882 German Bible.
&amp;ldquo;He grasped two pillars of the temple and bowed himself with all his might&amp;rdquo; - Judges 16:30.
Introduction This post is about online services which rely partly, or wholly, on user-contributed content. It&amp;rsquo;s about what happens to that content if those services close.
I&amp;rsquo;ll examine the constraints and motivations of the parties involved.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 27 Jul 2017 13:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/beating-the-samson-option/</guid></item><item><title>Processes On Unix</title><link>https://venam.net/blog/unix/2017/07/27/processes-on-unix.html</link><description>In this episode we'll tackle a topic that joins many parts of the systems and so is hard to fully cover. It has a relationship with everything in the system, it glues it together.  We're going to be discussing processes on Unix.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Thu, 27 Jul 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/07/27/processes-on-unix.html</guid></item><item><title>Injecting Dynamic Elements to Components</title><link>https://dylanpaulus.com/posts/2017/injecting-react-tag-types/</link><description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Let's say we're working on an UI component library using React JS. We make a super awesome looking button, maybe even the best button in the world. But suddenly, our computer shuts off without saving our component!&lt;br /&gt;
Like Tenacious D, we create a tribute to the button which looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AwesomeButton extends Component {
  render() {
    const { children, ...other } = this.props;

    return &amp;lt;button {...other}&amp;gt;{children}&amp;lt;/button&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything is working great. We create buttons all over the place &lt;code&gt;&amp;lt;AwesomeButton onClick={doStuff}&amp;gt;Click ME&amp;lt;/AwesomeButton&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The next day, the boss comes over, "This button is amazing, let's make a button link to Google!"&lt;br /&gt;
Easy enough, we create a new component that instead uses an anchor tag.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AwesomeButtonLink extends Component {
  render() {
    const { children, ...other } = this.props;

    return &amp;lt;a {...other}&amp;gt;{children}&amp;lt;/a&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Weeks later, another programmer walks over, "Hey, we're converting to using React Router. Can we get a button that can use the Link component?"&lt;br /&gt;
Mumbling under your breath, we create yet another Awesome component.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AwesomeButtonReactRouterLink extends Component {
  render() {
    const { children, ...other } = this.props;

    return &amp;lt;Link {...other}&amp;gt;{children}&amp;lt;/Link&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have ourselves a problem. Every time there is a new request we have to create new components that are very similar, just using slightly different render elements. What if the company decides to re-brand. Instead of blue, we are a red company now. Little changes to the visuals of these AwesomeButton components need to be updated individually. Think DRY! Is there a better way of doing this? Stay tuned.&lt;/p&gt;
&lt;h3&gt;Dynamically Injecting Elements&lt;/h3&gt;
&lt;p&gt;What if the consumer of a component could define its base element? Let's look at the example below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AwesomeButton extends React.Component {
  render() {
    const { children, tag = "button", ...other } = this.props;
    const Tag = tag;

    return &amp;lt;Tag {...other}&amp;gt;{children}&amp;lt;/Tag&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we have this new property called tag. Tag will be our way of passing in an element/component into AwesomeButton. If the es6 destructing looks different, let me explain. We will pull out the &lt;code&gt;tag&lt;/code&gt; prop from &lt;code&gt;this.props&lt;/code&gt;. If no value is defined for tag, we will set its default value to be &lt;code&gt;"button"&lt;/code&gt; (A Button HTML element).&lt;br /&gt;
The next line, &lt;code&gt;const Tag = tag;&lt;/code&gt; is so we can fulfill what React's JSX considers a component. All components must be uppercase, where html elements need to be lowercase. Since we are using then variable &lt;code&gt;tag&lt;/code&gt;, JSX will always treat the incoming values as a component. So, we have to uppercase our variable.&lt;br /&gt;
We now render the prop &lt;code&gt;Tag&lt;/code&gt; as our element. Whatever &lt;code&gt;tag&lt;/code&gt; equals, that will be our element!&lt;/p&gt;
&lt;p&gt;A few examples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;AwesomeButton onClick={doSomething}&amp;gt;Click Me!&amp;lt;AwesomeButton&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will render the default button. &lt;code&gt;&amp;lt;button onClick={doSomething}&amp;gt;Click Me!&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;AwesomeButton tag="a" href={`/myPage`}&amp;gt;Click Me!&amp;lt;AwesomeButton&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will render using an anchor tag &lt;code&gt;&amp;lt;a href={'/myPage'}&amp;gt;Click Me!&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;AwesomeButton tag={Link} to={`/myPage`}&amp;gt;Click Me!&amp;lt;AwesomeButton&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will render using a React Router Link component &lt;code&gt;&amp;lt;Link to={'/myPage'}&amp;gt;Click Me!&amp;lt;/Link&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Neat! But why is this happening?&lt;/p&gt;
&lt;h3&gt;JSX Transformations&lt;/h3&gt;
&lt;p&gt;Our JSX, in the render function, gets transformed into plain jsx functions that the browsers can use. With this in mind, our AwesomeButton's JSX gets transformed into a &lt;code&gt;React.createElement()&lt;/code&gt; function with the element name as the first argument.&lt;br /&gt;
With the help of our good friend Babel, let's see what different components compile to!&lt;/p&gt;
&lt;p&gt;First, let's look at a simple component that just renders a div with the text "test".&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AwesomeButton extends React.Component {
  render() {
    return &amp;lt;div&amp;gt;test&amp;lt;/div&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://babeljs.io/repl/#?babili=false&amp;amp;evaluate=true&amp;amp;lineWrap=false&amp;amp;presets=es2015%2Creact%2Cstage-2&amp;amp;targets=&amp;amp;browsers=&amp;amp;builtIns=false&amp;amp;debug=false&amp;amp;code_lz=MYGwhgzhAECCDuBTCB7AtogQgVwC65QDtpEAPXRQgExgCVExhcA6AYXQAcjLdoBvALAAoaKOgAnSlUTiAFAEp-wsSomJc2ccVnLVqgDxUAlgDcAfBQi59AemPnouvfIDcT6AF9hHoA"&gt;Compiled Example - Click Me!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we look in the render method, we can see what our JSX actually compiles to.&lt;/p&gt;
&lt;p&gt;&lt;img alt="div Compiled Code" title="div Compiled Code" /&gt;&lt;/p&gt;
&lt;p&gt;Well that's cool. So our div element just gets defined as the first parameter of &lt;code&gt;React.createElement&lt;/code&gt;. I wonder what happens if we try this with our element injecting AwesomeButton?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class AwesomeButton extends React.Component {
  render() {
    const { children, tag = "button", ...other } = this.props;
    const Tag = tag;

    return &amp;lt;Tag {...other}&amp;gt;{children}&amp;lt;/Tag&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://babeljs.io/repl/#?babili=false&amp;amp;evaluate=true&amp;amp;lineWrap=false&amp;amp;presets=es2015%2Creact%2Cstage-2&amp;amp;targets=&amp;amp;browsers=&amp;amp;builtIns=false&amp;amp;debug=false&amp;amp;code_lz=MYGwhgzhAECCDuBTCB7AtogQgVwC65QDtpEAPXRQgExgCVExhcA6AYXQAcjLdoBvALAAoaKOgAnSlUTiAFAEp-wsSujAiEXnzUALAJYgqkwgBpouMAHNoAXmgAiAEZ4Che2eaeUuHTOgBfW3N9CGYOcRQOCABuZVVRdUJNaAAVKyCLS1ihOPjJXGxxYllc-NEAHjTrPk9mb19xfwA-PmB9Q2N_coB6KqboUpV5bJV_YX8gA"&gt;&amp;lt;AwesomeButton&amp;gt;Click Me!&amp;lt;/AwesomeButton&amp;gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Looking at the render method in AwesomeButton:&lt;/p&gt;
&lt;p&gt;&lt;img alt="AwesomeButton Compiled Code" title="AwesomeButton Compiled Code" /&gt;&lt;/p&gt;
&lt;p&gt;Woah, our Tag variable just gets put where the element is! This is exactly the same to how components are treated in JSX. They get ploped straight into the first argument of &lt;code&gt;React.createElement&lt;/code&gt;. Now, when the boss asks for a new feature in &lt;code&gt;AwesomeButton&lt;/code&gt;, we only have to change this one implementation of the component. All consumers of the component might use it vastly differently, but we are able to keep our code DRY and highly reusable!&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Wed, 26 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2017/injecting-react-tag-types/</guid></item><item><title>Get element offset in JavaScript</title><link>https://muffinman.io/blog/javascript-get-element-offset/</link><description>&lt;article class="article"&gt;&lt;p&gt;When we left jQuery behind and embraced modern JavaScript frameworks,
we thought we would never touch DOM directly again.
Well that is not entirely true.
There are a lot of cases when you need to get some DOM element size.
For element&amp;#x27;s dimensions &lt;code&gt;.offsetWidth&lt;/code&gt; and &lt;code&gt;.offsetHeight&lt;/code&gt; are great way to do it.&lt;/p&gt;
&lt;p&gt;But one of the other common tasks is getting element&amp;#x27;s offset, top and left.
I&amp;#x27;ll show you two ways to get those.&lt;/p&gt;
&lt;h2 id="using-offsettop--offsetleft"&gt;Using &lt;code&gt;offsetTop&lt;/code&gt; / &lt;code&gt;offsetLeft&lt;/code&gt; &lt;a class="anchor-link" href="#using-offsettop--offsetleft"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This one is old school, and there is nothing wrong with it.
Even today, this method lives in my &lt;code&gt;helpers.js&lt;/code&gt;.
It is looping to the root of the DOM tree and performance obsessed people may having problem with it.
But so far I never had performance issue with it, and I&amp;#x27;m talking about production level projects.&lt;/p&gt;
&lt;p&gt;One important thing to note - it is not taking CSS transforms into calculations.
Everything is calculated from element&amp;#x27;s original position.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;getElementOffset&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;el&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;let&lt;/span&gt; top &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;let&lt;/span&gt; left &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;let&lt;/span&gt; element &lt;span class="token operator"&gt;=&lt;/span&gt; el&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Loop through the DOM tree&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// and add it&amp;#x27;s parent&amp;#x27;s offset to get page offset&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;do&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    top &lt;span class="token operator"&gt;+=&lt;/span&gt; element&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;offsetTop&lt;/span&gt; &lt;span class="token operator"&gt;||&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    left &lt;span class="token operator"&gt;+=&lt;/span&gt; element&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;offsetLeft&lt;/span&gt; &lt;span class="token operator"&gt;||&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    element &lt;span class="token operator"&gt;=&lt;/span&gt; element&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;offsetParent&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token keyword"&gt;while&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;element&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    top&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    left&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="using-getboundingclientrect"&gt;Using &lt;code&gt;getBoundingClientRect&lt;/code&gt; &lt;a class="anchor-link" href="#using-getboundingclientrect"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Another way is using &lt;code&gt;getBoundingClientRect&lt;/code&gt; which is cool because it
takes CSS transforms into calculations and it is natively supported.
No need to loop through the element&amp;#x27;s parents.
But it&amp;#x27;s &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;left&lt;/code&gt; properties are distances from the viewport, not from the document.
Because of this, you need to add document scroll to it.&lt;/p&gt;
&lt;p&gt;Just note one thing, there is a &lt;a href="https://openradar.appspot.com/radar?id=6668472289329152"&gt;known bug&lt;/a&gt;
with iOS and &lt;code&gt;getBoundingClientRect&lt;/code&gt; in combination with &lt;code&gt;position: fixed&lt;/code&gt;. I found about this bug few days ago when I was working on &lt;a href="https://github.com/Stanko/react-plx"&gt;react-plx&lt;/a&gt;. Sometimes it is just returning the wrong values. So, when you have fixed elements, you probably want to fallback to the method above&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;getElementOffset&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;el&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; rect &lt;span class="token operator"&gt;=&lt;/span&gt; el&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    top&lt;span class="token operator"&gt;:&lt;/span&gt; rect&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;top&lt;/span&gt; &lt;span class="token operator"&gt;+&lt;/span&gt; &lt;span class="token dom variable"&gt;window&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;pageYOffset&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    left&lt;span class="token operator"&gt;:&lt;/span&gt; rect&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;left&lt;/span&gt; &lt;span class="token operator"&gt;+&lt;/span&gt; &lt;span class="token dom variable"&gt;window&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;pageXOffset&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// If you want to support IE8 and lower&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Use&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;//&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// top: rect.top + (window.pageYOffset || document.documentElement.scrollTop),&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft),&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 26 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/javascript-get-element-offset/</guid></item><item><title>SIGGRAPH 2017 Paper- Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes</title><link>https://blog.yiningkarlli.com/2017/07/spectral-and-decomposition-tracking.html</link><description>&lt;p&gt;Some recent work I was part of at Walt Disney Animation Studios has been published in the July 2017 issue of ACM Transactions on Graphics as part of SIGGRAPH 2017!
The paper is titled “&lt;a href="http://dl.acm.org/citation.cfm?id=3073665"&gt;Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes&lt;/a&gt;”, and the project was a collaboration between the Hyperion development team at &lt;a href="http://disneyanimation.com"&gt;Walt Disney Animation Studios&lt;/a&gt; (WDAS) and the rendering group at &lt;a href="http://www.disneyresearch.com/research-labs/disney-research-zurich"&gt;Disney Research Zürich&lt;/a&gt; (DRZ).
From the WDAS side, the authors are &lt;a href="http://peterkutz.com"&gt;Peter Kutz&lt;/a&gt; (who was at Penn at the same time as me), &lt;a href="https://www.linkedin.com/in/ralf-habel-6a74bb2/"&gt;Ralf Habel&lt;/a&gt;, and myself.
On the DRZ side, our collaborator was &lt;a href="https://jannovak.info"&gt;Jan Novák&lt;/a&gt;, the head of DRZ’s rendering research group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/color_explosion.png"&gt;&lt;img alt="Image from paper Figure 12: a colorful explosion with chromatic extinction rendered using spectral tracking." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/color_explosion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the paper abstract:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We present two novel unbiased techniques for sampling free paths in heterogeneous participating media. Our decomposition tracking accelerates free-path construction by splitting the medium into a control component and a residual component and sampling each of them separately. To minimize expensive evaluations of spatially varying collision coefficients, we define the control component to allow constructing free paths in closed form. The residual heterogeneous component is then homogenized by adding a fictitious medium and handled using weighted delta tracking, which removes the need for computing strict bounds of the extinction function. Our second contribution, spectral tracking, enables efficient light transport simulation in chromatic media. We modify free-path distributions to minimize the fluctuation of path throughputs and thereby reduce the estimation variance. To demonstrate the correctness of our algorithms, we derive them directly from the radiative transfer equation by extending the integral formulation of null-collision algorithms recently developed in reactor physics. This mathematical framework, which we thoroughly review, encompasses existing trackers and postulates an entire family of new estimators for solving transport problems; our algorithms are examples of such. We analyze the proposed methods in canonical settings and on production scenes, and compare to the current state of the art in simulating light transport in heterogeneous participating media.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The paper and related materials can be found at:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.disneyanimation.com/technology/publications/96"&gt;Official WDAS Project Page (Preprint paper and supplemental materials)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.yiningkarlli.com/projects/specdecomptracking.html"&gt;Project Page (Author’s Version)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://dl.acm.org/citation.cfm?doid=3072959.3073665"&gt;Official Print Version (ACM Library)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Peter Kutz will be presenting the paper at &lt;a href="http://s2017.siggraph.org"&gt;SIGGRAPH 2017&lt;/a&gt; in Log Angeles as part of the &lt;a href="http://s2017.siggraph.org/technical-papers/sessions/rendering-volumes"&gt;Rendering Volumes&lt;/a&gt; Technical Papers session.&lt;/p&gt;

&lt;p&gt;Instead of repeating the contents of the paper here (which is pointless since the paper already says everything we want to say), I thought instead I’d use this blog post to talk about some of the process we went through while writing this paper.
Please note that everything stated in this post are my own opinions and thoughts, not Disney’s.&lt;/p&gt;

&lt;p&gt;This project started over a year ago, when we began an effort to significantly overhaul and improve Hyperion’s volume rendering system.
Around the same time that we began to revisit volume rendering, we heard a lecture from a visiting professor on multilevel Monte Carlo (MLMC) methods.
Although the final paper has nothing to do with MLMC methods, the genesis of this project was in initial conversations we had about how MLMC methods might be applied to volume rendering.
We concluded that MLMC could be applicable, but weren’t entirely sure how.
However, these conversations eventually gave Peter the idea to develop the technique that would eventually become decomposition tracking (importantly, decomposition tracking does not actually use MLMC though).
Further conversations about weighted delta tracking then led to Peter developing the core ideas behind what would become spectral tracking.
After testing some initial implementations of these prototype version of decomposition and spectral tracking, Peter, Ralf, and I shared the techniques with Jan.
Around the same time, we also shared the techniques with our sister teams, Pixar’s RenderMan development group in Seattle and the Pixar Research Group in Emeryville, who were able to independently implement and verify our techniques.
Being able to share research between Walt Disney Animation Studios, Disney Research, the Renderman group, Pixar Animation Studios, Industrial Light &amp;amp; Magic, and Imagineering is one of the reasons why Disney is such an amazing place to be for computer graphics folks.&lt;/p&gt;

&lt;p&gt;At this point we had initial rudimentary proofs for why decomposition and spectral tracking worked separately, but we still didn’t have a unified framework that could be used to explain and combine the two techniques.
Together with Jan, we began by deep-diving into the origins of delta/Woodcock tracking in neutron transport and reactor physics papers from the 1950s and 1960s and working our way forward to the present.
All of the key papers we dug up during this deep-dive are cited in our paper.
Some of these early papers were fairly difficult to find.
For example, the original delta tracking paper, “Techniques used in the GEM code for Monte Carlo neutronics calculations in reactors and other systems of complex geometry” (Woodcock et al. 1965), is often cited in graphics literature, but a cursory Google search doesn’t provide any links to the actual paper itself.
We eventually managed to track down a copy of the original paper in the archives of the United States Department of Commerce, which for some reason hosts a lot of archive material from Argonne National Laboratory.
Since the original Woodcock paper has been in the public domain for some time now but is fairly difficult to find, I’m hosting a &lt;a href="http://yiningkarlli.com/projects/specdecomptracking/references/Woodcock1965.pdf"&gt;copy here&lt;/a&gt; for any researchers that may be interested.&lt;/p&gt;

&lt;p&gt;Several other papers we were only able to obtain by requesting archival microfilm scans from several university libraries.
I won’t host copies here, since the public domain status for several of them isn’t clear, but if you are a researcher looking for any of the papers that we cited and can’t find it, feel free to contact me.
One particularly cool find was “The Relativistic Doppler Problem” (Zerby et al. 1961), which Peter obtained by writing to the Oak Ridge National Laboratory’s research library.
Their staff were eventually able to find the paper in their records/archives, and subsequently scanned and uploaded the paper online.
The paper is now &lt;a href="https://www.osti.gov/scitech/biblio/4836227"&gt;publicly available here&lt;/a&gt;, on the United States Department of Energy’s Office of Scientific and Technical Information website.&lt;/p&gt;

&lt;p&gt;Eventually, through significant effort from Jan, we came to understand Galtier et al.’s 2013 paper, “&lt;a href="https://www.researchgate.net/publication/258211025_Integral_formulation_of_null-collision_Monte_Carlo_algorithms"&gt;Integral Formulation of Null-Collision Monte Carlo Algorithms&lt;/a&gt;”, and were able to import the integral formulation into computer graphics and demonstrate how to derive both decomposition and spectral tracking directly from the radiative transfer equation using the integral formulation.
This step also allowed Peter to figure out how to combine spectral and decomposition tracking into a single technique.
With all of these pieces in place, we had the framework for our SIGGRAPH paper.
We then put significant effort into working out remaining details, such as finding a good mechanism for bounding the free-path-sampling coefficient in spectral tracking.
Producing all of the renders, results, charts, and plots in the paper also took an enormous amount of time; it turns out that producing all of this stuff can take significantly longer than the amount of time originally spent coming up with and implementing the techniques in the first place!&lt;/p&gt;

&lt;p&gt;One major challenge we faced in writing the final paper was finding the best order in which to present the three main pieces of the paper: decomposition tracking, spectral tracking, and the integral formulation of null-collision algorithms.
At one point, we considered first presenting decomposition tracking, since on a general level decomposition tracking is the easiest of the three contributions to understand.
Then, we planned to use the proof of decomposition tracking to expand out into the integral formulation of the RTE with null collisions, and finally derive spectral tracking from the integral formulation.
The idea was essentially to introduce the easiest technique first, expand out to the general mathematical framework, and then demonstrate the flexibility of the framework by deriving the second technique.
However, this approach in practice felt disjointed, especially with respect to the body of prior work we wanted to present, which underpinned the integral framework but wound up being separated by the decomposition tracking section.
So instead, we arrived on the final presentation order, where we first present the integral framework and derive out prior techniques such as delta tracking, and then demonstrate how to derive out new decomposition tracking and spectral tracking techniques.
We hope that presenting the paper in this way will encourage other researchers to adopt the integral framework and derive other, new techniques from the framework.
For Peter’s presentation at SIGGRAPH, however, Peter chose to go with the original order since it made for a better presentation.&lt;/p&gt;

&lt;p&gt;Since our final paper was already quite long, we had to move some content into a separate supplemental document.
Although the supplemental content isn’t necessary for implementing the core algorithms presented, I think the supplemental content is very useful for gaining a better understanding of the techniques.
The supplemental content contains, among other things, an extended proof of the minimum-of-exponents mechanism that decomposition tracking is built on, various proofs related to choosing bounds for the local collision weight in spectral tracking, and various additional results and further analysis.
We also provide a nifty interactive viewer for comparing our techniques against vanilla delta tracking; the interactive viewer framework was originally developed by &lt;a href="http://zurich.disneyresearch.com/~fabricer/"&gt;Fabrice Rousselle&lt;/a&gt;, Jan Novák and &lt;a href="https://benedikt-bitterli.me"&gt;Benedikt Bitterli&lt;/a&gt; at Disney Research Zürich.&lt;/p&gt;

&lt;p&gt;One of the major advantages of doing rendering research at a major animation or VFX studio is the availability of hundreds of extremely talented artists, who are always eager to try out new techniques and software.
Peter, Ralf, and I worked closely with a number of artists at WDAS to test our techniques and produce interesting scenes with which to generate results and data for the paper.
Henrik Falt and Alex Nijmeh had created a number of interesting clouds in the process of testing our general volume rendering improvements, and worked with us to adapt a cloud dataset for use in Figure 11 of our paper.
The following is one of the renders from Figure 11:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/single_cloud.png"&gt;&lt;img alt="Image from paper Figure 11: an optically thick cloud rendered using decomposition tracking." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/single_cloud.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Henrik and Alex also constructed the cloudscape scene used as the banner image on the first page of the paper.
After we submitted the paper, Henrik and Alex continued iterating on this scene, which eventually resulted in the more detailed version seen in our SIGGRAPH Fast Forward video.
The version of the cloudscape used in our paper is reproduced below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/beauty_clouds.png"&gt;&lt;img alt="Image from paper Figure 1: a cloudscape rendered using spectral and decomposition tracking." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/beauty_clouds.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To test out spectral tracking, we wanted an interesting, dynamic, colorful dataset.
After describing spectral tracking to Jesse Erickson, we arrived at the idea of a color explosion similar in spirit to certain visuals used in recent &lt;a href="https://www.youtube.com/watch?v=WVPRkcczXCY"&gt;Apple&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=BzMLA8YIgG0"&gt;Microsoft&lt;/a&gt; ads, which in turn were inspired by the &lt;a href="https://en.wikipedia.org/wiki/Holi"&gt;Holi festival&lt;/a&gt; celebrated in India and Nepal.
Jesse authored the color explosion in Houdini and provided a set of VDBs for each color section, which we were then able to shade, light, and render using Hyperion’s implementation of spectral tracking.
The final result was the color explosion from Figure 12 of the paper, seen at the top of this post.
We were honored to learn that the color explosion figure was chosen to be one of the pictures on the back cover of this year’s conference proceedings!&lt;/p&gt;

&lt;p&gt;At one point we also remembered that brute force path-traced subsurface scattering is just volume rendering inside of a bounded surface, which led to the translucent heterogeneous Stanford dragon used in Figure 15 of the paper:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/sss_dragon.png"&gt;&lt;img alt="Image from paper Figure 15: a subsurface scattering heterogeneous Stanford dragon rendered using spectral and decomposition tracking." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/sss_dragon.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For our video for the SIGGRAPH 2017 Fast Forward, we were able to get a lot of help from a number of artists. Alex and Henrik and a number of other artists significantly expanded and improved the cloudscape scene, and we also rendered out several more color explosion variants. The final fast forward video contains work from Alex Nijmeh, Henrik Falt, Jesse Erickson, Thom Wickes, Michael Kaschalk, Dale Mayeda, Ben Frost, Marc Bryant, John Kosnik, Mir Ali, Vijoy Gaddipati, and Dimitre Berberov. The awesome title effect was thought up by and created by Henrik. The final video is a bit noisy since we were severely constrained on available renderfarm resources (we were basically squeezing our renders in between actual production renders), but I think the end result is still really great:&lt;/p&gt;

&lt;div class="embed-container"&gt;Spectral and Decomposition Tracking for Rendering Homogeneous Volumes- SIGGRAPH 2017 Fast Forward Video&lt;/div&gt;

&lt;p&gt;Here are a couple of cool stills from the fast forward video:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/fastforward_01.png"&gt;&lt;img alt="An improved cloudscape from our SIGGRAPH Fast Forward video." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/fastforward_01.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/fastforward_02.png"&gt;&lt;img alt="An orange-purple color explosion from our SIGGRAPH Fast Forward video." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/fastforward_02.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Jul/fastforward_03.png"&gt;&lt;img alt="A green-yellow color explosion from our SIGGRAPH Fast Forward video." src="https://blog.yiningkarlli.com/content/images/2017/Jul/preview/fastforward_03.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We owe an enormous amount of thanks to fellow Hyperion teammate Patrick Kelly, who played an instrumental role in designing and implementing our overall new volume rendering system, and who discussed with us extensively throughout the project.
Hyperion teammate David Adler also helped out a lot in profiling and instrumenting our code.
We also must thank Thomas Müller, Marios Papas, Géraldine Conti, and David Adler for proofreading, and Brent Burley, Michael Kaschalk, and Rajesh Sharma for providing support, encouragement, and resources for this project.&lt;/p&gt;

&lt;p&gt;I’ve worked on a &lt;a href="http://blog.yiningkarlli.com/2014/11/sky-paper.html"&gt;SIGGRAPH Asia paper&lt;/a&gt; before, but working on a large scale publication in the context of a major animation studio instead of in school was a very different experience.
The support and resources we were given and the amount of talent and help that we were able to tap into made this project possible.
This project is also an example of the incredible value that comes from companies maintaining in-house industrial research labs; this project absolutely would not have been possible without all of the collaboration from DRZ, in both the form of direct collaboration from Jan and indirect collaboration from all of the DRZ researchers that provided discussions and feedback.
Everyone worked really hard, but overall the whole process was immensely intellectually satisfying and fun, and seeing our new techniques in use by talented, excited artists makes all of the work absolutely worthwhile!&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Tue, 25 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2017/07/spectral-and-decomposition-tracking.html</guid></item><item><title>Transitioning from uncontrolled inputs to controlled</title><link>https://goshacmd.com/turn-uncontrolled-into-controlled/</link><author>Gosha Spark</author><pubDate>Tue, 25 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/turn-uncontrolled-into-controlled/</guid></item><item><title>Recent creations</title><link>https://rjp.is/blogging/posts/recent-creations-2017-30-2/</link><description>In which we summarise some craftings.</description><author>infrequent oscillations</author><pubDate>Mon, 24 Jul 2017 18:02:10 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/recent-creations-2017-30-2/</guid></item><item><title>Why I moved from Fitbit to Apple Watch</title><link>https://rjp.is/blogging/posts/why-i-moved-from-fitbit-to-watch-2/</link><description>In which we get annoyed with Fitbit and defect.</description><author>infrequent oscillations</author><pubDate>Mon, 24 Jul 2017 14:02:09 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/why-i-moved-from-fitbit-to-watch-2/</guid></item><item><title>Plx - React parallax component</title><link>https://muffinman.io/blog/plx-react-parallax-component/</link><description>&lt;article class="article"&gt;&lt;p&gt;I&amp;#x27;m becoming predictable. Again, I haven&amp;#x27;t found component I like, so I wrote my own.&lt;/p&gt;
&lt;p&gt;This time, I&amp;#x27;ve build React component for parallax (on scroll) effects.
Check the &lt;a href="https://muffinman.io/react-plx/"&gt;live demo&lt;/a&gt;. It is called &lt;code&gt;Plx&lt;/code&gt;, it is open source and available on &lt;a href="https://github.com/Stanko/react-plx"&gt;GitHub&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/react-plx"&gt;npm&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="what-it-does"&gt;What it does &lt;a class="anchor-link" href="#what-it-does"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far in my career, I&amp;#x27;ve built so many parallax components. Parallax is actually
&lt;span class="sidenote__text" tabindex="0"&gt;wrong term&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;the effect whereby the position or direction of an object appears to differ when
viewed from different positions, e.g. through the viewfinder and the lens of a camera.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
here, but it got accepted by development community.&lt;/p&gt;
&lt;p&gt;Designers love them and users are fascinated by fancy effects. Simply explained as you scroll the page down something is changed relative to the scroll position. For example, as you scroll you can make things explode! Just check the &lt;a href="https://muffinman.io/react-plx/"&gt;demo&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Make things explode! Plx demo" height="774" src="./plx-explode.png" width="908" /&gt;&lt;/figure&gt;
&lt;p&gt;There is a lot of solutions out there, but IMHO they are usually bloated or not performant or complicated to use. And as I&amp;#x27;m using React a lot, I decided to collect what I have learned about implementing on scroll effects in React and create standalone component. Most of the code in this component is pulled out from my existing projects and glued together.&lt;/p&gt;
&lt;h2 id="performance"&gt;Performance &lt;a class="anchor-link" href="#performance"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Plx is really performant, thanks to a few optimizations.&lt;/p&gt;
&lt;p&gt;First and the most important one - it is not listening to window scroll event.
It is using simple scroll manager, which checks if scroll has changed every 16ms (to get smooth 60fps).
When scroll changes it broadcasts custom event.
All of the Plx components are listening to this event and share the same scroll manager (it is singleton).
Singleton is created with the first component, and destroyed when last one unmounts.&lt;/p&gt;
&lt;p&gt;Another optimization is that elements are not animated when not in viewport.
Actually, they are not animated if they are more than 50px outside of viewport.
So component &amp;quot;gets ready&amp;quot; 50px before it enters the viewport.
You can force animating element even outside of viewport by setting &lt;code&gt;animateWhenNotInViewport&lt;/code&gt; prop to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Beside that, every update is done in &lt;code&gt;requestAnimationFrame&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Still you need to avoid common &amp;quot;don&amp;#x27;t dos&amp;quot; when making a parallax page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid &lt;code&gt;background-size: cover&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Don’t animate massive images or dramatically resize them&lt;/li&gt;
&lt;li&gt;Avoid animating 100 things at once&lt;/li&gt;
&lt;li&gt;Only use properties that are cheap for browsers to animate - opacity and transform (scale, rotate, skew, scale)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Read this &lt;a href="https://medium.com/@dhg/parallax-done-right-82ced812e61c"&gt;great article&lt;/a&gt; to find out more (that is where I got my initial inspiration).&lt;/p&gt;
&lt;h2 id="supported-effects--properties"&gt;Supported effects / properties &lt;a class="anchor-link" href="#supported-effects--properties"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Plx supports every CSS property that has numeric value (
&lt;span class="sidenote__text" tabindex="0"&gt;&lt;code&gt;opacity&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;The most performant properties to animate are &lt;code&gt;opacity&lt;/code&gt; and &lt;code&gt;transform&lt;/code&gt;. So stick to those two to keep your parallax effects performant. Of course you can animate something else here and there, but be careful and test it throughly.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
...). I wrote a formula (this sounds way more sciency than it is)
which calculates property value depending on the scroll position and given input values.&lt;/p&gt;
&lt;p&gt;It also supports &lt;code&gt;transform&lt;/code&gt;, and you can pass multiple transform functions (&lt;code&gt;translateX&lt;/code&gt;, &lt;code&gt;rotate&lt;/code&gt;, &lt;code&gt;skewZ&lt;/code&gt;...).
You can even animate colors on scroll (background, text and border colors are supported)! Colors are broken down to their R/G/B/A values, and then same formula is applied to each one of them.&lt;/p&gt;
&lt;h2 id="at-the-end"&gt;At the end &lt;a class="anchor-link" href="#at-the-end"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What are you waiting?! Get it from npm and start using it :)&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;$ &lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; &lt;span class="token parameter variable"&gt;--save&lt;/span&gt; react-plx
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Documentation is available on &lt;a href="https://github.com/Stanko/react-plx"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;Plx&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-plx&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;Example&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword control-flow"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Plx&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        className&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;MyAwesomeParallax&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        parallaxData&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token spread operator"&gt;...&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token comment"&gt;// your parallax effects, see documentation&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token comment"&gt;/* Your content */&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Plx&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Feel free to contribute, cheers!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 24 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/plx-react-parallax-component/</guid></item><item><title>Integrating your Rails project with GitLab review apps</title><link>https://kyrofa.com/posts/integrating-your-rails-project-with-gitlab-review-apps/</link><description>My first foray into software development when I was a kid was as a web developer. I don&amp;rsquo;t admit this to many people, but the first language I ever learned halfway decently was PHP. I led a confused childhood. After that, though, I was introduced to Ruby on Rails, and I&amp;rsquo;ve been using it ever since.
I don&amp;rsquo;t do web development professionally anymore, but I have a number of web-based side projects, making websites for friends or family.</description><author>kyrofa's blog</author><pubDate>Mon, 24 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/integrating-your-rails-project-with-gitlab-review-apps/</guid></item><item><title>Cryptocurrencies: It's all about incentive</title><link>https://olshansky.info/posts/2017-07-23-cryptocurrencies-all-about-incentive/</link><description>One of the major selling points of cryptocurrencies is that everything is decentralized and trust no longer lies in single a third party…</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 23 Jul 2017 20:16:04 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-07-23-cryptocurrencies-all-about-incentive/</guid></item><item><title>Arch Linux on a Chromebook Asus C301SA</title><link>https://blog.nobugware.com/post/2017/asus_c301s_arch_linux_chromeos_write_protection/</link><description>I&amp;rsquo;ve got an Asus C301S at work, it&amp;rsquo;s a Chromebook with Chromeos.
I like those little laptops, for the price it&amp;rsquo;s actually a very good little machine.
ChromeOS is responding very well, ssh and Chrome are working too.
But I often need more, like X11 forwarding or offline coding &amp;hellip;
You will see the C301SA is marked as a C300SA internally.
Here are the steps to install Arch Linux on it, do it at your own risk, you can brick your computer, you will need an external USB keyboard.</description><author>Fabrice Aneche</author><pubDate>Sun, 23 Jul 2017 04:28:24 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2017/asus_c301s_arch_linux_chromeos_write_protection/</guid></item><item><title>Get ready for the chip wars!</title><link>https://jasoneckert.github.io/myblog/get-ready-for-the-chip-wars/</link><description>&lt;p&gt;&lt;img alt="chipwars" src="chipwars.png#center" title="chipwars" /&gt;&lt;/p&gt;
&lt;p&gt;Intel and their x86 computing architecture have pretty much dominated the computing industry since the late 1980s.  In other words, nearly all computers that you’ve used at work or home for the past three decades have used Intel’s proprietary x86 (and later, x64) CPUs.  The Intel 80-386 running DOS and Win3.1 won the PC wars by the early 1990s.  Then came the Intel 80-486, Pentium, Pentium II, Pentium III, Pentium IV, Core Duos, Core i7s, as well as the AMD equivalents that ran the same x86/x64 instruction sets.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Sat, 22 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/get-ready-for-the-chip-wars/</guid></item><item><title>Graphing performance as investigative endeavour</title><link>https://rjp.is/blogging/posts/graphing-performance-as-investigative-endeavour-2/</link><description>In which we see if lap times can tell us about endurance.</description><author>infrequent oscillations</author><pubDate>Fri, 21 Jul 2017 16:32:24 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/graphing-performance-as-investigative-endeavour-2/</guid></item><item><title>Links - July 21st, 2017</title><link>https://faingezicht.com/links/2017/07/21/links/</link><description>It seems like this is a post where articles are paired up in some way or another. That didn't happen on purpose.</description><author>Avy Faingezicht</author><pubDate>Fri, 21 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/07/21/links/</guid></item><item><title>Game Review: SimCity - SNES</title><link>https://kernelcurry.com/blog/snes-simcity/</link><description>&lt;figure&gt;&lt;img src="https://kernelcurry.com/blog/snes-simcity/cart-front.png" /&gt;&lt;figcaption&gt;
 &lt;h4&gt;SimCity Cartridge&lt;/h4&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;How does a city work? Why does building a Police Station not reduce crime some times? Will you get elected as Mayor of your own town next year? Find out in this addicting game as you build for hours.&lt;/p&gt;
&lt;h2 id="first-impressions"&gt;First Impressions&lt;/h2&gt;
&lt;p&gt;The push of a power switch and the sweet sweet sound of 16-bit music fills the air. As the music plays, I am starting to get excited about what is about to come&amp;hellip; Wait What?! The intro theme is only 8 measures long? Eight measures of 3/4? I know music takes up a bunch of space, but these eight measures were one of the most annoying loops I have ever heard! Smashing the start button to save my ears, the journey was about to begin.&lt;/p&gt;</description><author>KernelCurry</author><pubDate>Fri, 21 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kernelcurry.com/blog/snes-simcity/</guid></item><item><title>Designing Database Schemas</title><link>https://www.wints.org/notes/2017.07.21/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
Going back to the drawing board, I realized that I complicated matters by involving a database.
Defining a schema was harder than I thought. I finally settled on the following for displaying inventory.&lt;/p&gt;
&lt;h5 id="schemas"&gt;Schemas &lt;a href="#schemas"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;I decided I would manually create tables for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;color&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;finish&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;location&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;thickness&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To determine whats in stock, I would pull a report from the inventory management system, then compare it to the &lt;code&gt;colors&lt;/code&gt; table.
If the report has a color, the corresponding color, finish, location and thickness from the database.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 21 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.21/</guid></item><item><title>Trying Out Go</title><link>https://liza.io/trying-out-go/</link><description>&lt;p&gt;A couple of weeks ago I had the genius idea to rewrite SnailLife in Go. I’ve already looked into doing this once before a couple of years ago, but wasn’t really feeling it and stuck with PHP (mostly for nostaligia reasons). Now though, SnailLife is this bloated PHP app. Most of the core functionality is in. After weeks of battling infrastructure issues, when everything was back up and running again, I took a step back and saw how big the app (or rather the 3 apps now) had become. At the same time I’d been reading in passing about Go and became curious, so I figured - why not look into learning Go by rewriting SnailLife? Not because I think Go itself will necessarily make anything better, but because a rewrite might.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Thu, 20 Jul 2017 21:23:36 GMT</pubDate><guid isPermaLink="true">https://liza.io/trying-out-go/</guid></item><item><title>Test friendly mixins</title><link>https://qubyte.codes/blog/test-friendly-mixins</link><description>&lt;p&gt;I've recently been attempting to code a clone of the classic game asteroids
using canvas in the browser. Since this is me, I've been distracted by all sorts
of programming detours.&lt;/p&gt;
&lt;p&gt;This post is roughly the process I went through for one such detour.&lt;/p&gt;
&lt;p&gt;I began planning the game by sketching out the objects it would contain. This
lead to a relatively (for the subject matter) deep class hierarchy including an
abstract entity as a base class, a ship class, an asteroid class, a bullet
class, and so on. It quickly became obvious that it was getting convoluted, with
some repetition to avoid artificial seeming relationships between these classes.&lt;/p&gt;
&lt;p&gt;To avoid this sort of convolution, I could eschew classes in favour of plain
objects and mixins, where mixins embody chunks of useful behaviour which are
copied onto host objects. For example, most objects in the game can move, so I'd
write a mixin function to copy a move method onto host objects.&lt;/p&gt;
&lt;p&gt;I'm not a purist though. There's still value to a base class to encode all
essential properties of all objects in the game. Extending the base class for
other objects in the game makes sense for those behaviours and properties unique
to the child class. For example, the ship can be controlled by the user, so such
control would be defined as part of the &lt;code&gt;Ship&lt;/code&gt; child class. Other behaviours
will not be unique to child classes, so these can go into mixins.&lt;/p&gt;
&lt;p&gt;There are various approaches to mixins in the wild, but I decided to roll my
own. I wrote a function which builds and returns another function. The returned
function applies a mixin. It looked like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createMixin&lt;/span&gt;(&lt;span class="hljs-params"&gt;descriptors&lt;/span&gt;) {
  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;mix&lt;/span&gt;(&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;defineProperties&lt;/span&gt;(obj, descriptors);
  };
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The argument &lt;code&gt;descriptors&lt;/code&gt; is an object with &lt;a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties"&gt;property descriptors&lt;/a&gt;. I use
these rather than simple object fields since it allows me to create mixins which
are extremely configurable.&lt;/p&gt;
&lt;p&gt;Using this I can program the bulk of the behaviour of objects in the game. For
example, since all objects can be assumed to have position and velocity, one
such mixin could add a &lt;code&gt;move&lt;/code&gt; method (which I suggested earlier in this post):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; movable = &lt;span class="hljs-title function_"&gt;createMixin&lt;/span&gt;({
  &lt;span class="hljs-attr"&gt;move&lt;/span&gt;: {
    &lt;span class="hljs-title function_"&gt;value&lt;/span&gt;(&lt;span class="hljs-params"&gt;dt&lt;/span&gt;) {
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;position&lt;/span&gt;.&lt;span class="hljs-property"&gt;x&lt;/span&gt; += &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;velocity&lt;/span&gt;.&lt;span class="hljs-property"&gt;x&lt;/span&gt; * dt;
      &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;position&lt;/span&gt;.&lt;span class="hljs-property"&gt;y&lt;/span&gt; += &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;velocity&lt;/span&gt;.&lt;span class="hljs-property"&gt;y&lt;/span&gt; * dt;
    },
    &lt;span class="hljs-attr"&gt;configurable&lt;/span&gt;: &lt;span class="hljs-literal"&gt;true&lt;/span&gt;, &lt;span class="hljs-comment"&gt;// These three properties&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;enumerable&lt;/span&gt;: &lt;span class="hljs-literal"&gt;false&lt;/span&gt;,  &lt;span class="hljs-comment"&gt;// are like how class&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;writable&lt;/span&gt;: &lt;span class="hljs-literal"&gt;true&lt;/span&gt;      &lt;span class="hljs-comment"&gt;// methods are set.&lt;/span&gt;
  }
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Consider the ship at the centre of the game. We could code it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; ship = {
  &lt;span class="hljs-attr"&gt;position&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;50&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;50&lt;/span&gt; },
  &lt;span class="hljs-attr"&gt;velocity&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;1&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;2&lt;/span&gt; }
};

&lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(ship); &lt;span class="hljs-comment"&gt;// Apply the mixin.&lt;/span&gt;

ship.&lt;span class="hljs-title function_"&gt;move&lt;/span&gt;(&lt;span class="hljs-number"&gt;2&lt;/span&gt;); &lt;span class="hljs-comment"&gt;// Now at x: 51, y: 52&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I want the ship to be a class extending a base class though:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-comment"&gt;// Base class for all game objects.&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Entity&lt;/span&gt; {
  &lt;span class="hljs-title function_"&gt;constructor&lt;/span&gt;(&lt;span class="hljs-params"&gt;{ position, velocity }&lt;/span&gt;) {
    &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;position&lt;/span&gt; = { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: position.&lt;span class="hljs-property"&gt;x&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: position.&lt;span class="hljs-property"&gt;y&lt;/span&gt; };
    &lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;.&lt;span class="hljs-property"&gt;velocity&lt;/span&gt; = { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: velocity.&lt;span class="hljs-property"&gt;x&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: velocity.&lt;span class="hljs-property"&gt;y&lt;/span&gt; };
  }
}

&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt; &lt;span class="hljs-keyword"&gt;extends&lt;/span&gt; &lt;span class="hljs-title class_ inherited__"&gt;Entity&lt;/span&gt; {
  &lt;span class="hljs-comment"&gt;// Ship specific behaviour in here.&lt;/span&gt;
}

&lt;span class="hljs-comment"&gt;// Give all Ship instances access to move.&lt;/span&gt;
&lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(&lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;.&lt;span class="hljs-property"&gt;&lt;span class="hljs-keyword"&gt;prototype&lt;/span&gt;&lt;/span&gt;);

&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; ship = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;({
  &lt;span class="hljs-attr"&gt;position&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;50&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;50&lt;/span&gt;},
  &lt;span class="hljs-attr"&gt;velocity&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;1&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;2&lt;/span&gt; }
});

&lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(ship); &lt;span class="hljs-comment"&gt;// Apply the mixin.&lt;/span&gt;

ship.&lt;span class="hljs-title function_"&gt;move&lt;/span&gt;(&lt;span class="hljs-number"&gt;2&lt;/span&gt;); &lt;span class="hljs-comment"&gt;// Now at x: 51, y: 52&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All sorts of objects and classes may be composed with mixins.&lt;/p&gt;
&lt;p&gt;I'm a professional JavaScript programmer, which means that each time I write
something there's a little voice in my head asking me how hard it'll be to write
tests for it. Applying the mixin to a simple object makes writing tests for the
mixin in isolation possible. In mocha:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-title function_"&gt;describe&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;movable&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-function"&gt;() =&amp;gt;&lt;/span&gt; {
  &lt;span class="hljs-title function_"&gt;it&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;appends a single method &amp;quot;move&amp;quot;&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-function"&gt;() =&amp;gt;&lt;/span&gt; {
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; entity = {
      &lt;span class="hljs-attr"&gt;position&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt; },
      &lt;span class="hljs-attr"&gt;velocity&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt; }
    };

    &lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(entity);

    assert.&lt;span class="hljs-title function_"&gt;equal&lt;/span&gt;(&lt;span class="hljs-keyword"&gt;typeof&lt;/span&gt; entity.&lt;span class="hljs-property"&gt;move&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#x27;function&amp;#x27;&lt;/span&gt;);
  });

  &lt;span class="hljs-title function_"&gt;it&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;updates the position given a dt&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-function"&gt;() =&amp;gt;&lt;/span&gt; {
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; entity = {
      &lt;span class="hljs-attr"&gt;position&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;5&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;6&lt;/span&gt; },
      &lt;span class="hljs-attr"&gt;velocity&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;1&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;2&lt;/span&gt; }
    };

    &lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(entity);

    entity.&lt;span class="hljs-title function_"&gt;move&lt;/span&gt;(&lt;span class="hljs-number"&gt;3&lt;/span&gt;);

    assert.&lt;span class="hljs-title function_"&gt;deepEqual&lt;/span&gt;(entity.&lt;span class="hljs-property"&gt;position&lt;/span&gt;, { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;8&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;12&lt;/span&gt; });
  });
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I'd be more exhaustive in real world tests, but I hope you get the gist.&lt;/p&gt;
&lt;p&gt;What about objects which have mixins applied to them though? How can we test
them? Naïvely you could write the above tests for every class that uses the
mixin. That's repetitive though. It would be nicer to have some mechanism to ask
a mixin if an object has had the mixin applied to it. Then test for a class can
use a single test for each mixin to check that the mixin has been applied, and
all the repetition can be avoided.&lt;/p&gt;
&lt;p&gt;Revisiting the mixin creating function, the first go at such a mechanism looks
like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createMixin&lt;/span&gt;(&lt;span class="hljs-params"&gt;descriptors&lt;/span&gt;) {
  &lt;span class="hljs-comment"&gt;// References to objects the mixin has been&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// applied to.&lt;/span&gt;
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; mixed = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;WeakSet&lt;/span&gt;();

  &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;mix&lt;/span&gt;(&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;defineProperties&lt;/span&gt;(obj, descriptors);
    mixed.&lt;span class="hljs-title function_"&gt;add&lt;/span&gt;(obj);
  };

  mix.&lt;span class="hljs-property"&gt;isMixed&lt;/span&gt; = &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; (&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; mixed.&lt;span class="hljs-title function_"&gt;has&lt;/span&gt;(obj);
  };

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; mix;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I've used a &lt;a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakSet"&gt;&lt;code&gt;WeakSet&lt;/code&gt;&lt;/a&gt; here. A &lt;code&gt;WeakSet&lt;/code&gt; contains &lt;em&gt;weak&lt;/em&gt; references to
objects. These are references which the garbage collector ignores. When no
strong references to an object in a &lt;code&gt;WeakSet&lt;/code&gt; remain, the garbage collector can
clear the object. If I used a regular &lt;code&gt;Set&lt;/code&gt; or an array here, the references
contained would be strong, and references could never be cleaned up
automatically by the garbage collector, resulting in a memory leak. This would
be a problem in particular for asteroids, as each time one is destroyed the
object itself would be held in the &lt;code&gt;Set&lt;/code&gt; or array be a strong reference, leading
it to grow as more and more asteroids are spawned.&lt;/p&gt;
&lt;p&gt;Now we can ask the mixin if an object has had the mixin applied to it:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;movable.&lt;span class="hljs-title function_"&gt;isMixed&lt;/span&gt;(entity); &lt;span class="hljs-comment"&gt;// false&lt;/span&gt;

&lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(entity);

movable.&lt;span class="hljs-title function_"&gt;isMixed&lt;/span&gt;(entity); &lt;span class="hljs-comment"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What about classes though? This won't work because the mixin is applied to the
prototype and no reference to an instance will be stored by the mixin. We can
fix this by climbing up the prototype chain and checking each prototype object:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createMixin&lt;/span&gt;(&lt;span class="hljs-params"&gt;descriptors&lt;/span&gt;) {
  &lt;span class="hljs-comment"&gt;// References to objects the mixin has been&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// applied to.&lt;/span&gt;
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; mixed = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;WeakSet&lt;/span&gt;();

  &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;mix&lt;/span&gt;(&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;defineProperties&lt;/span&gt;(obj, descriptors);
    mixed.&lt;span class="hljs-title function_"&gt;add&lt;/span&gt;(obj);
  };

  mix.&lt;span class="hljs-property"&gt;isMixed&lt;/span&gt; = &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; (&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-comment"&gt;// Walk up the prototype chain and check&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// if each step has had the mixin applied&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// to it.&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;let&lt;/span&gt; o = obj; o; o = &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;getPrototypeOf&lt;/span&gt;(o)) {
      &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (mixed.&lt;span class="hljs-title function_"&gt;has&lt;/span&gt;(o)) {
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;true&lt;/span&gt;;
      }
    }

    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;false&lt;/span&gt;;
  };

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; mix;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This works perfectly well now, and any child classes can inherit the method as
expected and the &lt;code&gt;isMixed&lt;/code&gt; check will still work. It is now possible to avoid
duplication of tests. For example, part of a test suite for the ship class might
look like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-title function_"&gt;it&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;is movable&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-function"&gt;() =&amp;gt;&lt;/span&gt; {
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; ship = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;({
    &lt;span class="hljs-attr"&gt;position&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt; },
    &lt;span class="hljs-attr"&gt;velocity&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt; }
  });

  assert.&lt;span class="hljs-title function_"&gt;ok&lt;/span&gt;(movable.&lt;span class="hljs-title function_"&gt;isMixed&lt;/span&gt;(ship));
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One final adjustment can be made. It's a shame that we can use &lt;code&gt;instanceof&lt;/code&gt; for
objects constructed by a class, but not objects which have had the mixin applied
to them. This can be achieved by using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance"&gt;&lt;code&gt;Symbol.hasInstance&lt;/code&gt;&lt;/a&gt;. A first
attempt:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createMixin&lt;/span&gt;(&lt;span class="hljs-params"&gt;descriptors&lt;/span&gt;) {
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; mixed = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;WeakSet&lt;/span&gt;();

  &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;mix&lt;/span&gt;(&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;defineProperties&lt;/span&gt;(obj, descriptors);
    mixed.&lt;span class="hljs-title function_"&gt;add&lt;/span&gt;(obj);
  };

  mix[&lt;span class="hljs-title class_"&gt;Symbol&lt;/span&gt;.&lt;span class="hljs-property"&gt;hasInstance&lt;/span&gt;] = &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; (&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;let&lt;/span&gt; o = obj; o; o = &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;getPrototypeOf&lt;/span&gt;(o)) {
      &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (mixed.&lt;span class="hljs-title function_"&gt;has&lt;/span&gt;(o)) {
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;true&lt;/span&gt;;
      }
    }
  };

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; mix;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unfortunately this doesn't work because &lt;code&gt;Function.prototype[Symbol.hasInstance]&lt;/code&gt;
is not writable. When appending a property to something, the field you're
appending it as is checked for writability, and that check propagates up the
prototype chain. Since &lt;code&gt;mix&lt;/code&gt; is a function, it has a non-writable
&lt;code&gt;Symbol.hasInstance&lt;/code&gt; field in its prototype chain, and we need to work around
that.&lt;/p&gt;
&lt;p&gt;We can once again use &lt;code&gt;Object.defineProperty&lt;/code&gt; to do it:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createMixin&lt;/span&gt;(&lt;span class="hljs-params"&gt;descriptors&lt;/span&gt;) {
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; mixed = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;WeakSet&lt;/span&gt;();

  &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;mix&lt;/span&gt;(&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
    &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;defineProperties&lt;/span&gt;(obj, descriptors);
    mixed.&lt;span class="hljs-title function_"&gt;add&lt;/span&gt;(obj);
  };

  &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;defineProperty&lt;/span&gt;(mix, &lt;span class="hljs-title class_"&gt;Symbol&lt;/span&gt;.&lt;span class="hljs-property"&gt;hasInstance&lt;/span&gt;, {
    &lt;span class="hljs-title function_"&gt;value&lt;/span&gt;(&lt;span class="hljs-params"&gt;obj&lt;/span&gt;) {
      &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;let&lt;/span&gt; o = obj; o; o = &lt;span class="hljs-title class_"&gt;Object&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;getPrototypeOf&lt;/span&gt;(o)) {
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (mixed.&lt;span class="hljs-title function_"&gt;has&lt;/span&gt;(o)) {
          &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;true&lt;/span&gt;;
        }
      }
    },
    &lt;span class="hljs-attr"&gt;configurable&lt;/span&gt;: &lt;span class="hljs-literal"&gt;false&lt;/span&gt;,
    &lt;span class="hljs-attr"&gt;enumerable&lt;/span&gt;: &lt;span class="hljs-literal"&gt;false&lt;/span&gt;,
    &lt;span class="hljs-attr"&gt;writable&lt;/span&gt;: &lt;span class="hljs-literal"&gt;false&lt;/span&gt;
  });

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; mix;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally we can do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt; &lt;span class="hljs-keyword"&gt;extends&lt;/span&gt; &lt;span class="hljs-title class_ inherited__"&gt;Entity&lt;/span&gt; { &lt;span class="hljs-comment"&gt;/* ... */&lt;/span&gt; }

&lt;span class="hljs-title function_"&gt;movable&lt;/span&gt;(&lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;.&lt;span class="hljs-property"&gt;&lt;span class="hljs-keyword"&gt;prototype&lt;/span&gt;&lt;/span&gt;);

&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; ship = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;({ &lt;span class="hljs-comment"&gt;/* ... */&lt;/span&gt; });

ship &lt;span class="hljs-keyword"&gt;instanceof&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Entity&lt;/span&gt;;  &lt;span class="hljs-comment"&gt;// true&lt;/span&gt;
ship &lt;span class="hljs-keyword"&gt;instanceof&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;;    &lt;span class="hljs-comment"&gt;// true&lt;/span&gt;
ship &lt;span class="hljs-keyword"&gt;instanceof&lt;/span&gt; movable; &lt;span class="hljs-comment"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the test suite for a ship can include tests like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-title function_"&gt;it&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;is movable&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-function"&gt;() =&amp;gt;&lt;/span&gt; {
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; ship = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Ship&lt;/span&gt;({
    &lt;span class="hljs-attr"&gt;position&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt; },
    &lt;span class="hljs-attr"&gt;velocity&lt;/span&gt;: { &lt;span class="hljs-attr"&gt;x&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt;, &lt;span class="hljs-attr"&gt;y&lt;/span&gt;: &lt;span class="hljs-number"&gt;0&lt;/span&gt; }
  });

  assert.&lt;span class="hljs-title function_"&gt;ok&lt;/span&gt;(ship &lt;span class="hljs-keyword"&gt;instanceof&lt;/span&gt; movable);
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So there you have it! All the test friendliness of classes with the
composability of mixins.&lt;/p&gt;
&lt;p&gt;I wrapped this code up in a module called &lt;a href="https://www.npmjs.com/package/mixomatic"&gt;mixomatic&lt;/a&gt;, which I intend to use
heavily in my gaming codebases.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Thu, 20 Jul 2017 16:30:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/test-friendly-mixins</guid></item><item><title>Makeshift Security Camera</title><link>https://denvaar.dev/posts/makeshift_security_camera.html</link><description>Fun project using the Raspberry Pi camera module to catch creeps, thieves, and what-have-you.</description><author>denvaar's website</author><pubDate>Tue, 18 Jul 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/makeshift_security_camera.html</guid></item><item><title>Querying with sqlalchemy</title><link>https://www.wints.org/notes/2017.07.18/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
Still having some trouble wrapping my head around sqlalchemy&amp;rsquo;s orm, putting things into postgres and then querying it. The flow isn&amp;rsquo;t clear to me yet.&lt;/p&gt;
&lt;h5 id="querying"&gt;Querying &lt;a href="#querying"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;
# Automaps the database here.
d = sps.Database()

# Tables are available in the classes property
Inventory = d.base.classes.inventory

# Creates a list of sqlalchemy object with all the rows (that's how my query_all method is implemented)
data = d.query_all(Inventory)

# I can access each row with this.
first_color = data[0].product

first_color

&amp;gt; u'Alaska Cream 3cm'
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This should work for now. Took me a good 8 hours to understand this. SQLalchemy is hard to grok for me.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Tue, 18 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.18/</guid></item><item><title>Analytics on easy mode with Redux-Saga</title><link>https://goshacmd.com/analytics-easy-redux-saga/</link><author>Gosha Spark</author><pubDate>Tue, 18 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/analytics-easy-redux-saga/</guid></item><item><title>July 2017 Projects</title><link>https://venam.net/blog/programming/2017/07/18/july-2017.html</link><description>It's been four months since the last post about my personal projects and endeavours. These past months I've been following, slowly but steadily, on the activities I had set the pace for previously.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Tue, 18 Jul 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/programming/2017/07/18/july-2017.html</guid></item><item><title>The digital precision</title><link>https://rybakov.com/blog/digital_precision/</link><description>&lt;!--  --&gt; 
&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/monet.jpg" /&gt;




&lt;/figure&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Mon, 17 Jul 2017 23:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/digital_precision/</guid></item><item><title>Captain Fantastic</title><link>https://olshansky.info/movie/captain_fantastic/</link><description>Olshansky's review of Captain Fantastic</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 17 Jul 2017 16:13:15 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/captain_fantastic/</guid></item><item><title>The Ultimate Guide to JavaScript Fatigue: Realities of our industry</title><link>https://lucasfcosta.com/blog/The-Ultimate-Guide-to-JavaScript-Fatigue/</link><description>Complaining about JS Fatigue is just like complaining about the fact that humanity has created too many tools to solve the problems we have, from email to airplanes and spaceships.

Last week I've ...</description><author>Lucas F. Costa - Blog</author><pubDate>Mon, 17 Jul 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/The-Ultimate-Guide-to-JavaScript-Fatigue/</guid></item><item><title>2017: A Central Europe Odyssey</title><link>https://thomashunter.name/posts/2017-07-17-2017-a-central-europe-odyssey</link><author>Thomas Hunter II</author><pubDate>Mon, 17 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-07-17-2017-a-central-europe-odyssey</guid></item><item><title>SQLAlchemy: Querying</title><link>https://www.wints.org/notes/2017.07.17/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I need to query my database through SQLAlchemy to generate reports and add results to the website.&lt;/p&gt;
&lt;h5 id="postgres-and-sqlalchemy"&gt;Postgres and SQLAlchemy &lt;a href="#postgres-and-sqlalchemy"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Querying in sqlalchemy is taking some time to grok.&lt;/p&gt;
&lt;p&gt;Most of the examples showed something like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;'''
Tables already created using sqlalchemy models and filled with data.
'''

from sqlalchemy import *

r = session.query(Table).filter(Table.name=="test").first()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This doesn&amp;rsquo;t really work for me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I have a pandas dataframe that needs to be inserted.&lt;/li&gt;
&lt;li&gt;Each day this dataframe is updated.&lt;/li&gt;
&lt;li&gt;Using the &lt;code&gt;to_sql&lt;/code&gt; pandas method, sqlalchemy models are useless (I&amp;rsquo;m using automap_base instead of declarative_base)&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;m unsure of how to get a usable list/table of results from a query.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wanted to write a reusable method to specifically query inventory tables.
So perhaps specifying some of the inputs and leaving the rest to the use case.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 17 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.17/</guid></item><item><title>Syntactic sugar in C - (ab)using "for" loops</title><link>https://zserge.com/posts/c-for-loop-tricks/</link><description>The for loop is one of the most powerful constructions in the C language.
It consists of three different parts. The first one is initialization, performed exactly once at the beginning of the loop. The second one is the conditional part, called every time before the loop body. The last one is the increment part, executed on every iteration right after the loop body. Such a loop combines both, linear code and branching in a very customizable manner, which we will explore below.</description><author>zserge's blog</author><pubDate>Mon, 17 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://zserge.com/posts/c-for-loop-tricks/</guid></item><item><title>Onward, a short review</title><link>https://faingezicht.com/articles/2017/07/16/onward/</link><description>Ever since I heard Howard Schultz speak at Northwestern four years ago, I wanted to read his books. As a coffee snob who regularly complains about Starbucks's quality, I went to the event with low expectations, and interested mostly in the cult of personality. Even though I hate their product, he did a good job and got me interested in his company. Now, years later, having finally read one out of two, I have to say I feel conflicted about _Onward_. The book lays out the reasons for Starbucks outsized role in the industry, and its influence in American coffee culture, but it does so with a self-indulgent tone that's hard to take seriously.

The narrative is entertaining: a classic "second round as CEO" tale where a retired founder comes back to rescue his beloved company in distress. However, &lt;a href="https://i.imgflip.com/1skr7d.jpg"&gt;the PR speak is strong with this one&lt;/a&gt;. I know that when reading a book like this, you need to be prepared to separate the wheat from the chaff (the &lt;a href="https://en.wikipedia.org/wiki/Coffee_production#Hulling"&gt;beans from the parchment&lt;/a&gt;?), but I did not expect _Onward_ to be so over the top. If the ghostwriter's self-promoting tone was not enough of a clue, the book consistently makes its optimistic angle clear.  Every problem the company faces is magically solved by the new executive team. Everything is about coffee, and everything about coffee is good. Its pages are peppered with cutesy coffee related phrases that no one would use in real life, like descriptions of partners who are "_steeped_ in the coffee business," and recurring appearances of Schultz's favorite french press. Nevertheless, once you get past the publicity, there are a few wortwhile nuggets on culture[^culture] and growth[^growth].

The bulk of the book talks about Starbucks's fall from grace and its return to the top. The book frames the company's decline mainly as a consequence of hubris and aimless growth, paired with the double whammy of increased competition and the financial crisis of 2007/2008. After opening thousands of unprofitable stores, and going into orthogonal businesses, the brand had been diluted, and the user experience had deteriorated. This is when Schultz comes in to save the day. Schultz credits the turnaround to his "transformational agenda," which can be summarized in six points:

* **Optimizing Stores**: Cutting back on growth and closing underperforming stores. They discuss the implications not just on the people who work there but also on the communities built around the people who go to their stores every day[^community]. The company had to choose between cutting benefits and cutting jobs, and ultimately chose to close ~600 stores in 2008. While they make a big deal out of holding on to their generous benefits, it seems like they're not &lt;a href="https://www.nytimes.com/interactive/2014/08/13/us/starbucks-workers-scheduling-hours.html"&gt;as positive as the book makes them seem&lt;/a&gt;.
* **Re-enabling the workforce**: Two recurring themes are empowering managers with tools and technology, and retraining baristas to improve the quality of the product. A startling example is a deal with HP, through which every store would get its own computer for the first time.
* **Developing new products**: There are plenty of examples in the book of product line diversification: innovations like Pike Place Roast and Via Instant Coffee, the successful acquisition of Clover, and the failed experiments of Sorbetto and Vivano, to name a few. Especially interesting was the section on its new high-end stores, which focused on using design and architecture to compete with small local roasters.
* **Tightening the supply chain**: At the macro scale, this meant improving sourcing via closer partnerships with farmers and developing farmer support centers. At the micro scale, each store employed concepts from &lt;a href="https://en.wikipedia.org/wiki/Lean_manufacturing"&gt;lean manufacturing&lt;/a&gt; to reduce waste[^lean].
* **Expanding brand loyalty**: Through creative strategies, the company drove consumers to build a deeper connection with the Starbucks brand. This was the beginning of the Starbucks card.
* **Focusing on long term value**: At Schultz's request, the company eliminated public disclosure of &lt;a href="http://www.investopedia.com/terms/c/comps.asp"&gt;comps&lt;/a&gt;, which allowed individual store managers to think beyond the quarter to quarter metrics. Wall Street was not happy.

Schultz likes to emphasize minutiae, such as the "honey pouring off a spoon" consistency of the espresso, and the importance of avoiding the smell of melting cheese, which overpowers the aroma of the coffee ground in-house, but in the end what it really took to revive Starbucks were better business practices, and paying attention to day to day operations.

_Onward_ is light on analysis, and it is best described as a very one-sided history book. The most interesting part ended up being about the company's origin story, and its connection to Starbucks's undeniable cultural impact. Until I read it, I did not know anything about Starbucks's history. I also didn't know that _they_ had made coffee shops _a thing_ in the United States[^history].

The book devotes a full chapter to the company's beginnings, but here is a short summary: A business trip to Italy led Schultz to quit his job as Director of Marketing at a small coffee roaster called Starbucks to start his own coffee shop. While in Italy, Schultz was surprised by the ubiquity of the cafés, and their role as "a third place" where people could meet - away from home, and away from work. He became obsessed with the country's coffee culture, where ordering an espresso "was so much more than a coffee break. This was theater; an experience in and of itself." He wanted to replicate it back in Seattle. Upon his return, he opened Il Giornale, the precursor to today's Starbucks. Eventually, Schultz bought the Starbucks brand from its owners, renamed his coffee shop, and focused on growing the business into what we know today.

The modern coffee shop is so ingrained in our collective consciousness that it is hard to comprehend that this image was not the norm just over thirty years ago. _Onward_ makes a convincing argument that Starbucks played a big role in popularizing the model, and in kicking off &lt;a href="https://en.wikipedia.org/wiki/Third_wave_of_coffee"&gt;the third wave of coffee&lt;/a&gt;.

_Onward_ offers a well defined window into Starbucks, its corporate values, and the image it wants to project onto the market. If that sounds exciting, by all means go read it, but otherwise, you can probably take this review as your TL;DR. It has been nearly 10 years since the book was written, and Starbucks has grown from 16k stores worldwide to 25k. The book might overplay it, but &lt;a href="https://qz.com/208457/a-cartographic-guide-to-starbucks-global-domination/"&gt;it seems&lt;/a&gt; like they did something right.

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: by me, not at a Starbucks, previously posted on &lt;a href="/photos/2017/05/22/pdx/"&gt;Portlanding&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;

[^culture]: "Every enterprise and organization has a memory, and those memories create a path for people to follow [...] memory of collective lessons will inform our future."

[^history]: An interesting thought I had on this shift was the transition from Seinfeld's Monk's Café, which really is a diner, to Friends' Central Perk.

[^growth]: "Ironically, the toughest challenges were not technical. They were human, like convincing leaders throughout the company to dedicate resources"

[^community]: When explaining these communities, there was a striking comparison with church that reminded me of &lt;a href="https://www.theguardian.com/business/2016/jun/08/mcdonalds-community-centers-us-physical-social-networks"&gt;Chris Arnade's essay about McDonalds&lt;/a&gt;: "stores are like secular chapels. No sign on the wall says you must be quiet, polite or contemplative, but people are. Ritual abounds."

[^lean]: In fact my supply chain modeling professor mentioned the Starbucks example in class, touching on the implications of higher efficiency at the expense of a worse user experience.</description><author>Avy Faingezicht</author><pubDate>Sun, 16 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/07/16/onward/</guid></item><item><title>Redis and Node Part 4: Lua Scripting</title><link>https://thomashunter.name/posts/2017-07-14-redis-and-node-part-4-lua-scripting</link><author>Thomas Hunter II</author><pubDate>Fri, 14 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-07-14-redis-and-node-part-4-lua-scripting</guid></item><item><title>From Script to Package</title><link>https://www.wints.org/notes/2017.07.14/</link><description>&lt;p&gt;Correctly applying architecture patterns to what you&amp;rsquo;re building, based on the problem being solved isn&amp;rsquo;t talked about much.
Having mostly written scripts in the past, building a module requires a lot more thought &lt;em&gt;upfront&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, when writing a method, what sorts of inputs do you want to allow for, vs. already having some of those inputs as part of the method.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SOLUTION A
def clean_report(report, list_of_column_to_drop, dict_of_column_to_rename):
    
    report = report.drop(list_of_columns_to_drop, axis=1)
    for x in report.columns:
        report.rename(columns={x:new_x}, inplace=True)

    return report
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;VS.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 14 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.14/</guid></item><item><title>Wenlock Olympian Triathlon 2017</title><link>https://caiustheory.com/wenlock-olympian-triathlon-2017/</link><description>&lt;p&gt;Second year in a row doing this Tri, &lt;a href="http://caiustheory.com/much-wenlock-triathlon-2016/"&gt;last year&lt;/a&gt; I came away feeling like I hadn&amp;rsquo;t given it my best and wanted to return to complete unfinished business. &lt;em&gt;(Spoilers: I managed better this year.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;500m Swim: 00:10:37&lt;/strong&gt; &lt;em&gt;(&lt;a href="https://www.strava.com/activities/1076088498"&gt;Strava&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Started last in a lane of three, didn&amp;rsquo;t get overtaken which meant swimming at my own pace without being under pressure was easily achieved. Failed to exit the pool initially, dropped a handful of seconds there for sure.&lt;/p&gt;
&lt;p&gt;Didn&amp;rsquo;t feel like I was pushing too hard, certainly felt energetic after leaving the building. Given my lack of swimming this year, I&amp;rsquo;m surprised at how well it went. Strength training over the winter months has definitely paid off more than I expected.&lt;/p&gt;
&lt;p&gt;Took nearly a minute off my previous swim time, which is more than I would&amp;rsquo;ve expected. Was only +7 seconds off my estimated time when entering too!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;19km Cycle 00:45:44&lt;/strong&gt; &lt;em&gt;(&lt;a href="https://www.strava.com/activities/1076088548"&gt;Strava&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The wonderful (👻) cycle route down and back up Wenlock Edge. Ran out of gear heading down the valley side (again), coasted most of the way down. Attempted to pace myself on the climbing, keeping an eye on my heart rate to know whether I could push harder or needed to ease off. Felt strong nearly all the way round, only came close to blowing on the final 15% climb (which was also nearer the end than I remembered/expected!)&lt;/p&gt;
&lt;p&gt;Got off the bike with less left in my legs than I thought whilst I was in the saddle. Took a solid 11 minutes 10 seconds off my previous time (which did include walking to be fair - none of that this year) which I&amp;rsquo;m &lt;em&gt;very&lt;/em&gt; happy with. Think I paced it nigh on perfectly on the day. Probably my strongest discipline currently too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7km Run 00:53:06&lt;/strong&gt; &lt;em&gt;(&lt;a href="https://www.strava.com/activities/1076088534"&gt;Strava&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Started the run feeling like crap. First couple of km is a mostly flat trail run, where I didn&amp;rsquo;t push very hard and was basically attempting to find some energy from somewhere. Pretty sure this was a mental battle rather than physical, no cramps or super tired muscles.&lt;/p&gt;
&lt;p&gt;A friend overtook me about 2.5km in and rather handily goaded me on by saying, &amp;ldquo;See you at the end!&amp;rdquo; as he went past (Thanks Paul!) which naturally made me kick harder and try to stick with him. Clung on to the halfway point (and the massive hill they make you climb just to turn round at the summit), and pulled ahead coming back down the route.&lt;/p&gt;
&lt;p&gt;Resorted to walking some sections of the run (probably about 750m in total), tailing and then dropping back from my mate in the last kilometre. (Dropped a minute in total to him on the run.) Technically I ran a 10k this season, but I&amp;rsquo;ve not run aside from that.&lt;/p&gt;
&lt;p&gt;(Also binned my trainers upon returning home. They&amp;rsquo;ve finally given up after being beaten on pavements &amp;amp; woodland floors for about 50 miles.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Total 01:49:27&lt;/strong&gt; &lt;em&gt;(Previously 02:14:40)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Completed in under two hours! Completely astounded at that, especially as I don&amp;rsquo;t &lt;em&gt;feel&lt;/em&gt; like I&amp;rsquo;ve been training much this year. (I have, but more socially than on a strict timetable and without doing many previous events this season.)&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d told me at the end of last year that my second attempt would take ~25 minutes off my finish time, I&amp;rsquo;d have laughed at you.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.wenlock-olympian-society.org.uk/games/triathlon/"&gt;Wenlock Olympian Triathlon&lt;/a&gt; is definitely my favourite Triathlon, and also the most challenging I&amp;rsquo;ve done to date. I&amp;rsquo;m intending on doing it next year and seriously aiming to take at least another 10 minutes off my total time.&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Thu, 13 Jul 2017 15:55:45 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/wenlock-olympian-triathlon-2017/</guid></item><item><title>Redis and Node Part 3: Atomicity with MULTI</title><link>https://thomashunter.name/posts/2017-07-13-redis-and-node-part-3-atomicity-with-multi</link><author>Thomas Hunter II</author><pubDate>Thu, 13 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-07-13-redis-and-node-part-3-atomicity-with-multi</guid></item><item><title>Extracting movies from libreoffice</title><link>https://purpleidea.com/blog/2017/07/12/extracting-movies-from-libreoffice/</link><description>&lt;p&gt;I have a short movie that I imported into a &lt;a href="https://libreoffice.org/"&gt;libreoffice&lt;/a&gt; presentation. I wanted a copy of that movie back, but I couldn&amp;rsquo;t figure out how to extract a copy. In desperation, I figured I&amp;rsquo;d try opening the file with &lt;a href="https://wiki.gnome.org/Apps/FileRoller"&gt;file-roller&lt;/a&gt;, the &lt;a href="https://gnome.org/"&gt;GNOME&lt;/a&gt; archive manager.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-fallback"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:/tmp$ file mgmt-berlin-osdc-17may2017.odp 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;mgmt-berlin-osdc-17may2017.odp: OpenDocument Presentation
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:/tmp$ mkdir out
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:/tmp$ file-roller -f mgmt-berlin-osdc-17may2017.odp -e out/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;[snip]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:/tmp$ cd out/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:/tmp/out$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;Configurations2/ Media/ meta.xml Pictures/ styles.xml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;content.xml META-INF/ mimetype settings.xml Thumbnails/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:/tmp/out$
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To my amazement, this worked perfectly! I found my video in the &lt;em&gt;Media/&lt;/em&gt; folder, and out it came! You can do this entirely with the GUI if you prefer:&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Wed, 12 Jul 2017 13:09:46 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/07/12/extracting-movies-from-libreoffice/</guid></item><item><title>Redis and Node Part 2: Shared State</title><link>https://thomashunter.name/posts/2017-07-12-redis-and-node-part-2-shared-state</link><author>Thomas Hunter II</author><pubDate>Wed, 12 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-07-12-redis-and-node-part-2-shared-state</guid></item><item><title>Binary Classification in Python - Who's Going to Leave Next?</title><link>https://lukesingham.com/whos-going-to-leave-next/</link><description>&lt;p&gt;This post goes through a binary classification problem with Python's machine learning library &lt;a href="http://scikit-learn.org/"&gt;scikit-learn&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="aim"&gt;Aim &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#aim"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Create a model that predicts who is going to leave the organisation next. Commonly known as churn modelling.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To follow along, I breakdown each piece of the coding journey in this post. Alternatively, you can find a &lt;a href="https://github.com/ucg8j/kaggle_HR"&gt;complete copy of the code on github&lt;/a&gt;. You'll need the following packages loaded:&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; os&lt;br /&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; pandas &lt;span class="token keyword"&gt;as&lt;/span&gt; pd&lt;br /&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; numpy &lt;span class="token keyword"&gt;as&lt;/span&gt; np&lt;br /&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; matplotlib&lt;span class="token punctuation"&gt;.&lt;/span&gt;pyplot &lt;span class="token keyword"&gt;as&lt;/span&gt; plt&lt;br /&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; seaborn &lt;span class="token keyword"&gt;as&lt;/span&gt; sns&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; random &lt;span class="token keyword"&gt;import&lt;/span&gt; sample&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn&lt;span class="token punctuation"&gt;.&lt;/span&gt;linear_model &lt;span class="token keyword"&gt;import&lt;/span&gt; LogisticRegression&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn &lt;span class="token keyword"&gt;import&lt;/span&gt; tree&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn&lt;span class="token punctuation"&gt;.&lt;/span&gt;ensemble &lt;span class="token keyword"&gt;import&lt;/span&gt; RandomForestClassifier&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn&lt;span class="token punctuation"&gt;.&lt;/span&gt;svm &lt;span class="token keyword"&gt;import&lt;/span&gt; SVC&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn&lt;span class="token punctuation"&gt;.&lt;/span&gt;neighbors &lt;span class="token keyword"&gt;import&lt;/span&gt; KNeighborsClassifier&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn&lt;span class="token punctuation"&gt;.&lt;/span&gt;naive_bayes &lt;span class="token keyword"&gt;import&lt;/span&gt; GaussianNB&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn&lt;span class="token punctuation"&gt;.&lt;/span&gt;cross_validation &lt;span class="token keyword"&gt;import&lt;/span&gt; cross_val_score&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; sklearn &lt;span class="token keyword"&gt;import&lt;/span&gt; metrics&lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; IPython&lt;span class="token punctuation"&gt;.&lt;/span&gt;display &lt;span class="token keyword"&gt;import&lt;/span&gt; Image  &lt;br /&gt;&lt;span class="token keyword"&gt;from&lt;/span&gt; pydotplus &lt;span class="token keyword"&gt;import&lt;/span&gt; graph_from_dot_data&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The dataset for this exercise was originally found on &lt;a href="https://www.kaggle.com/"&gt;kaggle&lt;/a&gt;. It's no longer available via Kaggle, so you can download a copy from my GitHub repo by running:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token function"&gt;curl&lt;/span&gt; https://raw.githubusercontent.com/ucg8j/kaggle_HR/master/HR_comma_sep.csv &lt;span class="token operator"&gt;&gt;|&lt;/span&gt; HR_comma_sep.csv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then to read in the data:&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Set working directory&lt;/span&gt;&lt;br /&gt;path &lt;span class="token operator"&gt;=&lt;/span&gt; os&lt;span class="token punctuation"&gt;.&lt;/span&gt;path&lt;span class="token punctuation"&gt;.&lt;/span&gt;expanduser&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;'~/Projects/kaggle_HR/'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;os&lt;span class="token punctuation"&gt;.&lt;/span&gt;chdir&lt;span class="token punctuation"&gt;(&lt;/span&gt;path&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Read in the data&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;read_csv&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;'HR_comma_sep.csv'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It contains data of 14,999 employees who are either in the organisation or have left, and 10 columns.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;shape&lt;br /&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;14999&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;columns&lt;span class="token punctuation"&gt;.&lt;/span&gt;tolist&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'satisfaction_level'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'last_evaluation'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'number_project'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'average_montly_hours'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'time_spend_company'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'Work_accident'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'promotion_last_5years'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'sales'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class="token string"&gt;'salary'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to get some sense of how balanced our dataset is...&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Some basic stats on the target variable&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; &lt;span class="token string"&gt;'# people left = {}'&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;format&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;len&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# people left = 3571&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; &lt;span class="token string"&gt;'# people stayed = {}'&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;format&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;len&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# people stayed = 11428&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; &lt;span class="token string"&gt;'% people left = {}%'&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;format&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;round&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;float&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;len&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;==&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt; &lt;span class="token builtin"&gt;len&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;*&lt;/span&gt; &lt;span class="token number"&gt;100&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;3&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# % people left = 24.0%&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Knowing that 76% of the workforce will stay helps us not be excited by machine learning diagnostics that aren't much better than 76%. If I predicted that &lt;strong&gt;all&lt;/strong&gt; staff would remain in the organisation, I would be 76% accurate!&lt;/p&gt;
&lt;p&gt;I next check for missing values.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token builtin"&gt;apply&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;lambda&lt;/span&gt; x&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token builtin"&gt;sum&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;x&lt;span class="token punctuation"&gt;.&lt;/span&gt;isnull&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;0&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;satisfaction_level       &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;last_evaluation          &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;number_project           &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;average_montly_hours     &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;time_spend_company       &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;Work_accident            &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;left                     &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;promotion_last_5years    &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;sales                    &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;salary                   &lt;span class="token number"&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No missing values, that's great. Next I look for correlations in the data.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Correlation heatmap&lt;/span&gt;&lt;br /&gt;correlation &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;corr&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;plt&lt;span class="token punctuation"&gt;.&lt;/span&gt;figure&lt;span class="token punctuation"&gt;(&lt;/span&gt;figsize&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;sns&lt;span class="token punctuation"&gt;.&lt;/span&gt;heatmap&lt;span class="token punctuation"&gt;(&lt;/span&gt;correlation&lt;span class="token punctuation"&gt;,&lt;/span&gt; vmax&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; square&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; annot&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; cmap&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'cubehelix'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/07/heatmap_correl.png" /&gt;&lt;/p&gt;
&lt;p&gt;Unsurprisingly, &lt;code&gt;satisfaction_level&lt;/code&gt; has the largest correlation with the decision to stay or leave. Next up, pairwise plots provide a lot information for one diagram.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# take a 5% sample as this is computationally expensive&lt;/span&gt;&lt;br /&gt;df_sample &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;sample&lt;span class="token punctuation"&gt;(&lt;/span&gt;frac&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;0.05&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Pairwise plots&lt;/span&gt;&lt;br /&gt;pplot &lt;span class="token operator"&gt;=&lt;/span&gt; sns&lt;span class="token punctuation"&gt;.&lt;/span&gt;pairplot&lt;span class="token punctuation"&gt;(&lt;/span&gt;df_sample&lt;span class="token punctuation"&gt;,&lt;/span&gt; hue&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;"left"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/07/pairwise.png" /&gt;&lt;/p&gt;
&lt;p&gt;On the diagonal we can see the distribution of each variable, including the target variable of who has left (this visualises the balance). There are some interesting groupings of those who leave (Green dots) when looking at the plots of &lt;code&gt;satisfaction_level&lt;/code&gt; by &lt;code&gt;last_evaluation&lt;/code&gt; and by &lt;code&gt;average_montly_hours&lt;/code&gt; - they look to be the same sub-populations. E.g. Low satisfaction but high evaluation and monthly hours, there's also a grouping of a high number of projects completed with low satisfaction levels by those who leave. Perhaps these are &lt;em&gt;high performers&lt;/em&gt; that easily leave when they are not satisfied by their job. There are other interesting groupings so it's worth spending some time looking at this output examining these relationships. It's great to have these groupings, as our classifier should be able to differentiate between those who leave and those that remain. If there were no relationships revealed in this plot, we would face a very difficult problem and perhaps have to go back to examine what data we could collect to help predict the outcome.&lt;/p&gt;
&lt;p&gt;Two variables were left out of the above plots, &lt;code&gt;Salary&lt;/code&gt; and &lt;code&gt;Sales&lt;/code&gt;. I need to deal with these separately prior to modelling, as our machine learning classifier will expect numbers to crunch rather than text.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;salary&lt;span class="token punctuation"&gt;.&lt;/span&gt;unique&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;array&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'low'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'medium'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'high'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; dtype&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token builtin"&gt;object&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;sales&lt;span class="token punctuation"&gt;.&lt;/span&gt;unique&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;array&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'sales'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'accounting'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'hr'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'technical'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'support'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'management'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'IT'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'product_mng'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'marketing'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'RandD'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; dtype&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token builtin"&gt;object&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Salary&lt;/code&gt; has 3 values &lt;em&gt;low&lt;/em&gt;, &lt;em&gt;medium&lt;/em&gt; and &lt;em&gt;high&lt;/em&gt;. These factor variables have an order. I'm going to go use dummy encoding as a simple and common method to handle factor variables. The downsides to this is I am not handling the &lt;em&gt;ordering&lt;/em&gt; and will introduce extra dimensions to the data (see &lt;a href="https://en.wikipedia.org/wiki/Curse_of_dimensionality"&gt;Curse of dimensionality&lt;/a&gt; for why this is bad). Helmert, Forward/Backward differencing or Orthogonal encoding would &lt;em&gt;probably&lt;/em&gt; be better.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id="as-an-aside..."&gt;As an aside... &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#as-an-aside..."&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;R&lt;/code&gt; makes factors really easy to handle. For example, let's say we have data with an unordered factor variable &lt;code&gt;df$unordered.variable&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# Order a factor variable in R&lt;/span&gt;&lt;br /&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;ordered.var &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; factor&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token operator"&gt;$&lt;/span&gt;unordered.var&lt;span class="token punctuation"&gt;,&lt;/span&gt; levels &lt;span class="token operator"&gt;=&lt;/span&gt; c&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;'low'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'medium'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'high'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2 id="dummy-encoding"&gt;Dummy Encoding &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#dummy-encoding"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Dummy encoding, or &lt;em&gt;one hot encoding&lt;/em&gt;, transforms categorical variables into a series of binary columns. Before I one hot encode the &lt;code&gt;sales&lt;/code&gt; and &lt;code&gt;salary&lt;/code&gt; I prepend the column names to the categories, that way I know later which column each new column came from. This helps particularly in cases where the columns use the same category names e.g. 'high' could apply to &lt;code&gt;sales&lt;/code&gt; and &lt;code&gt;salary&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Prepend string prior to encoding&lt;/span&gt;&lt;br /&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'salary'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'$_'&lt;/span&gt; &lt;span class="token operator"&gt;+&lt;/span&gt; df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'salary'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;astype&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;str&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'sales'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;'sales_'&lt;/span&gt; &lt;span class="token operator"&gt;+&lt;/span&gt; df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'sales'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;astype&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;str&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Create 'salary' dummies and join&lt;/span&gt;&lt;br /&gt;one_hot_salary &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;get_dummies&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'salary'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;join&lt;span class="token punctuation"&gt;(&lt;/span&gt;one_hot_salary&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Create 'sales' dummies and join&lt;/span&gt;&lt;br /&gt;one_hot_sales &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;get_dummies&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'sales'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;join&lt;span class="token punctuation"&gt;(&lt;/span&gt;one_hot_sales&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we proceeded to modelling without dropping columns, we would run into the &lt;em&gt;dummy variable trap&lt;/em&gt;. To illustrate what the dummy variable trap is, let's say that our data has a column for &lt;code&gt;Gender&lt;/code&gt; in the form &lt;code&gt;['male','female','male','female'...]&lt;/code&gt;. If we use &lt;code&gt;pd.get_dummies()&lt;/code&gt;&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Generate 'Gender' variable&lt;/span&gt;&lt;br /&gt;Gender &lt;span class="token operator"&gt;=&lt;/span&gt; np&lt;span class="token punctuation"&gt;.&lt;/span&gt;random&lt;span class="token punctuation"&gt;.&lt;/span&gt;choice&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'male'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;span class="token string"&gt;'female'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;4&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Create DataFrame&lt;/span&gt;&lt;br /&gt;df1 &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;Gender&lt;span class="token punctuation"&gt;,&lt;/span&gt; columns&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Gender'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# One hot encode Gender&lt;/span&gt;&lt;br /&gt;dummies &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;get_dummies&lt;span class="token punctuation"&gt;(&lt;/span&gt;df1&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Gender'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Join dummies to 'df1'&lt;/span&gt;&lt;br /&gt;df1 &lt;span class="token operator"&gt;=&lt;/span&gt; df1&lt;span class="token punctuation"&gt;.&lt;/span&gt;join&lt;span class="token punctuation"&gt;(&lt;/span&gt;dummies&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; df1&lt;br /&gt;   Gender  female  male&lt;br /&gt;&lt;span class="token number"&gt;0&lt;/span&gt;    male       &lt;span class="token number"&gt;0&lt;/span&gt;     &lt;span class="token number"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span class="token number"&gt;1&lt;/span&gt;  female       &lt;span class="token number"&gt;1&lt;/span&gt;     &lt;span class="token number"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;span class="token number"&gt;2&lt;/span&gt;    male       &lt;span class="token number"&gt;0&lt;/span&gt;     &lt;span class="token number"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span class="token number"&gt;3&lt;/span&gt;  female       &lt;span class="token number"&gt;1&lt;/span&gt;     &lt;span class="token number"&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that the dummy columns of &lt;code&gt;female&lt;/code&gt; and &lt;code&gt;male&lt;/code&gt; reflect the &lt;code&gt;Gender&lt;/code&gt; column, a row with column &lt;code&gt;Gender='male'&lt;/code&gt; has &lt;code&gt;female=0&lt;/code&gt; and &lt;code&gt;male=1&lt;/code&gt;. In modelling, we are looking for &lt;em&gt;independent&lt;/em&gt; variables to predict a &lt;em&gt;dependent&lt;/em&gt; outcome. One of our dummy variables is completely &lt;em&gt;dependent&lt;/em&gt; on the other (&lt;a href="https://en.wikipedia.org/wiki/Multicollinearity"&gt;see Multicollinearity&lt;/a&gt;). We can naturally drop one of the dummy variables to avoid this trap whilst not losing any valuable information.&lt;/p&gt;
&lt;p&gt;To avoid the dummy variable trap in the Kaggle HR dataset, I'm dropping the columns, &lt;code&gt;sales_IT&lt;/code&gt; and low salary &lt;code&gt;$_low&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Drop unnecessary columns to avoid the dummy variable trap&lt;/span&gt;&lt;br /&gt;df &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'salary'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'sales'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'$_low'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'sales_IT'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="split-into-test-and-training-sets"&gt;Split Into Test and Training Sets &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#split-into-test-and-training-sets"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now to split the dataset up into our training, testing and &lt;em&gt;optionally&lt;/em&gt; our validation sets. This is best done randomly to avoid having one subgroup of the data overrepresented in either our training or testing datasets, hence &lt;code&gt;df.sample()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Randomly, split the data into test/training/validation sets&lt;/span&gt;&lt;br /&gt;train&lt;span class="token punctuation"&gt;,&lt;/span&gt; test&lt;span class="token punctuation"&gt;,&lt;/span&gt; validate &lt;span class="token operator"&gt;=&lt;/span&gt; np&lt;span class="token punctuation"&gt;.&lt;/span&gt;split&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;.&lt;/span&gt;sample&lt;span class="token punctuation"&gt;(&lt;/span&gt;frac&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token builtin"&gt;int&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;.6&lt;/span&gt;&lt;span class="token operator"&gt;*&lt;/span&gt;&lt;span class="token builtin"&gt;len&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token builtin"&gt;int&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token number"&gt;.8&lt;/span&gt;&lt;span class="token operator"&gt;*&lt;/span&gt;&lt;span class="token builtin"&gt;len&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;df&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; train&lt;span class="token punctuation"&gt;.&lt;/span&gt;shape&lt;span class="token punctuation"&gt;,&lt;/span&gt; test&lt;span class="token punctuation"&gt;.&lt;/span&gt;shape&lt;span class="token punctuation"&gt;,&lt;/span&gt; validate&lt;span class="token punctuation"&gt;.&lt;/span&gt;shape&lt;br /&gt;&lt;span class="token comment"&gt;# (8999, 20) (3000, 20) (3000, 20)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Separate target and predictors&lt;/span&gt;&lt;br /&gt;y_train &lt;span class="token operator"&gt;=&lt;/span&gt; train&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;x_train &lt;span class="token operator"&gt;=&lt;/span&gt; train&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;y_test &lt;span class="token operator"&gt;=&lt;/span&gt; test&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;x_test &lt;span class="token operator"&gt;=&lt;/span&gt; test&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;y_validate &lt;span class="token operator"&gt;=&lt;/span&gt; validate&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;x_validate &lt;span class="token operator"&gt;=&lt;/span&gt; validate&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Check the balance of the splits on y_&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; y_test&lt;span class="token punctuation"&gt;.&lt;/span&gt;mean&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token number"&gt;0.23933333333333334&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;.&lt;/span&gt;mean&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token number"&gt;0.24091565729525502&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Feature importance can be ascertained from a random forest, alternatively &lt;a href="https://en.wikipedia.org/wiki/Principal_component_analysis"&gt;Principal Components Analysis (PCA)&lt;/a&gt; can be used.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Variable importance&lt;/span&gt;&lt;br /&gt;rf &lt;span class="token operator"&gt;=&lt;/span&gt; RandomForestClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; &lt;span class="token string"&gt;"Features sorted by their score:"&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; &lt;span class="token builtin"&gt;sorted&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;zip&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token builtin"&gt;map&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;lambda&lt;/span&gt; x&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token builtin"&gt;round&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;x&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token number"&gt;4&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; rf&lt;span class="token punctuation"&gt;.&lt;/span&gt;feature_importances_&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; x_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; reverse&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;#[(0.3523, 'satisfaction_level'), (0.1738, 'time_spend_company'), (0.1705, 'number_project'), (0.158, 'average_montly_hours'), (0.1043, 'last_evaluation'), (0.0077, '$_high'), (0.0065, 'Work_accident'), (0.0059, '$_medium'), (0.0042, 'sales_technical'), (0.0034, 'sales_sales'), (0.0028, 'sales_support'), (0.0024, 'sales_hr'), (0.0023, 'sales_accounting'), (0.0019, 'sales_management'), (0.0014, 'sales_RandD'), (0.001, 'sales_product_mng'), (0.001, 'sales_marketing'), (0.0006, 'promotion_last_5years')]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A very rough plot of &lt;code&gt;importances&lt;/code&gt; reveals that past the first 5 columns, we really don't get that much more variance explained by the additional columns.&lt;br /&gt;
&lt;img alt="" src="https://lukesingham.com/content/images/2017/07/rf_variable_importance-1.png" /&gt;&lt;/p&gt;
&lt;p&gt;From hereon in I'll only use the first 5 variables.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Create variable lists and drop&lt;/span&gt;&lt;br /&gt;all_vars &lt;span class="token operator"&gt;=&lt;/span&gt; x_train&lt;span class="token punctuation"&gt;.&lt;/span&gt;columns&lt;span class="token punctuation"&gt;.&lt;/span&gt;tolist&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;top_5_vars &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'satisfaction_level'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'number_project'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'time_spend_company'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'average_montly_hours'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'last_evaluation'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;bottom_vars &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;cols &lt;span class="token keyword"&gt;for&lt;/span&gt; cols &lt;span class="token keyword"&gt;in&lt;/span&gt; all_vars &lt;span class="token keyword"&gt;if&lt;/span&gt; cols &lt;span class="token keyword"&gt;not&lt;/span&gt; &lt;span class="token keyword"&gt;in&lt;/span&gt; top_5_vars&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Drop less important variables leaving the top_5&lt;/span&gt;&lt;br /&gt;x_train    &lt;span class="token operator"&gt;=&lt;/span&gt; x_train&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;bottom_vars&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;x_test     &lt;span class="token operator"&gt;=&lt;/span&gt; x_test&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;bottom_vars&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;x_validate &lt;span class="token operator"&gt;=&lt;/span&gt; x_validate&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;bottom_vars&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="model-evaluation-basics"&gt;Model Evaluation Basics &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#model-evaluation-basics"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The formula for &lt;strong&gt;accuracy&lt;/strong&gt; is:&lt;br /&gt;
&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mtext&gt;Accuracy&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/math&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TP&lt;/strong&gt; is the number of true positives&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Predicted as leaving and they do&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TN&lt;/strong&gt; is the number of true negatives&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Predicted as remaining and they do&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FP&lt;/strong&gt; is the number of false positives&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Predicted as leaving, but they aren't - whoops!&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FN&lt;/strong&gt; is the number of false negatives&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Predicted as remaining and they don't - eek!&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As mentioned before, if we were aiming to predict those who remain (76%) then if we predicted 100%, we would have &lt;code&gt;(0 + 11428) / 14999&lt;/code&gt; or 76% accuracy. As the &lt;a href="https://en.wikipedia.org/wiki/Accuracy_paradox"&gt;Accuracy Paradox wiki&lt;/a&gt; states precision and recall are probably more appropriate evaluation metrics. Here's a really quick definition of sensitivity (AKA recall), specificity and precision:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sensitivity/Recall&lt;/strong&gt; - &lt;code&gt;TP / (TP + FN)&lt;/code&gt; how well the model &lt;em&gt;recalls&lt;/em&gt;/identifies those that will leave. AKA the true positive rate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specificity&lt;/strong&gt; - &lt;code&gt;TN / (TN + FP)&lt;/code&gt; how well the model identifies those that will stay.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Precision&lt;/strong&gt; &lt;code&gt;TP / (TP + FP)&lt;/code&gt; how believable is the model? A low precision model will alarm you to those who are leaving that are actually staying.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;F1 score&lt;/strong&gt; &lt;code&gt;2 * (precision * recall)/(precision + recall)&lt;/code&gt; is the harmonic mean between precision and recall or the &lt;em&gt;balance&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this problem, we are perhaps most interested in knowing who is going to leave next. That way an organisation can respond with workforce planning and recruitment activities. Therefore, precision and recall will be the metrics we focus on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Intuitively, precision is the ability of the classifier not to label as positive a sample that is negative, and recall is the ability of the classifier to find all the positive samples.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Source: &lt;a href="http://scikit-learn.org/stable/modules/model_evaluation.html#precision-recall-and-f-measures"&gt;scikit-learn&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="modelling"&gt;Modelling &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#modelling"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="1.-logistic-regression"&gt;1. Logistic Regression &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#1.-logistic-regression"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Starting off with a very simple model, logistic regression.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Instantiate&lt;/span&gt;&lt;br /&gt;logit_model &lt;span class="token operator"&gt;=&lt;/span&gt; LogisticRegression&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Fit&lt;/span&gt;&lt;br /&gt;logit_model &lt;span class="token operator"&gt;=&lt;/span&gt; logit_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# How accurate?&lt;/span&gt;&lt;br /&gt;logit_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;score&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;#0.7874&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# How does it perform on the test dataset?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predictions on the test dataset&lt;/span&gt;&lt;br /&gt;predicted &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;logit_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Probabilities on the test dataset&lt;/span&gt;&lt;br /&gt;probs &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;logit_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict_proba&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;print&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;accuracy_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token number"&gt;0.785&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let's look at the confusion matrix and the metrics we care about.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token keyword"&gt;print&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;confusion_matrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;2100&lt;/span&gt;  &lt;span class="token number"&gt;182&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt; &lt;span class="token number"&gt;463&lt;/span&gt;  &lt;span class="token number"&gt;255&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="token operator"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; &lt;span class="token keyword"&gt;print&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;classification_report&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;             precision    recall  f1&lt;span class="token operator"&gt;-&lt;/span&gt;score   support&lt;br /&gt;&lt;br /&gt;          &lt;span class="token number"&gt;0&lt;/span&gt;       &lt;span class="token number"&gt;0.82&lt;/span&gt;      &lt;span class="token number"&gt;0.92&lt;/span&gt;      &lt;span class="token number"&gt;0.87&lt;/span&gt;      &lt;span class="token number"&gt;2282&lt;/span&gt;&lt;br /&gt;          &lt;span class="token number"&gt;1&lt;/span&gt;       &lt;span class="token number"&gt;0.58&lt;/span&gt;      &lt;span class="token number"&gt;0.36&lt;/span&gt;      &lt;span class="token number"&gt;0.44&lt;/span&gt;       &lt;span class="token number"&gt;718&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;avg &lt;span class="token operator"&gt;/&lt;/span&gt; total       &lt;span class="token number"&gt;0.76&lt;/span&gt;      &lt;span class="token number"&gt;0.79&lt;/span&gt;      &lt;span class="token number"&gt;0.77&lt;/span&gt;      &lt;span class="token number"&gt;3000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's double check the &lt;code&gt;classification_report&lt;/code&gt;. Focusing on those who will leave.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Precision = TP/(TP+FP) = 255/(255+182) = 0.58&lt;br /&gt;
Recall = TP/(TP+FN) = 255/(255+463) = 0.36&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Perhaps we could optimise this model, however there are a range of models to test that may perform better out-of-the-box. I'll quickly run through a range of models...&lt;/p&gt;
&lt;h3 id="2.-decision-tree"&gt;2. Decision Tree &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#2.-decision-tree"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Decision trees are highly interpretable and tend to perform well on classification problems.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Instantiate with a max depth of 3&lt;/span&gt;&lt;br /&gt;tree_model &lt;span class="token operator"&gt;=&lt;/span&gt; tree&lt;span class="token punctuation"&gt;.&lt;/span&gt;DecisionTreeClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;max_depth&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;3&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Fit a decision tree&lt;/span&gt;&lt;br /&gt;tree_model &lt;span class="token operator"&gt;=&lt;/span&gt; tree_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Training accuracy&lt;/span&gt;&lt;br /&gt;tree_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;score&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predictions/probs on the test dataset&lt;/span&gt;&lt;br /&gt;predicted &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;tree_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;probs &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;tree_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict_proba&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Store metrics&lt;/span&gt;&lt;br /&gt;tree_accuracy &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;accuracy_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree_roc_auc &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;roc_auc_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; probs&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree_confus_matrix &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;confusion_matrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree_classification_report &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;classification_report&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree_precision &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;precision_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree_recall &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;recall_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;tree_f1 &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;f1_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# evaluate the model using 10-fold cross-validation&lt;/span&gt;&lt;br /&gt;tree_cv_scores &lt;span class="token operator"&gt;=&lt;/span&gt; cross_val_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;tree&lt;span class="token punctuation"&gt;.&lt;/span&gt;DecisionTreeClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;max_depth&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;3&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; x_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; scoring&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; cv&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# output decision plot&lt;/span&gt;&lt;br /&gt;dot_data &lt;span class="token operator"&gt;=&lt;/span&gt; tree&lt;span class="token punctuation"&gt;.&lt;/span&gt;export_graphviz&lt;span class="token punctuation"&gt;(&lt;/span&gt;tree_model&lt;span class="token punctuation"&gt;,&lt;/span&gt; out_file&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;None&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                     feature_names&lt;span class="token operator"&gt;=&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;.&lt;/span&gt;columns&lt;span class="token punctuation"&gt;.&lt;/span&gt;tolist&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                     class_names&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'remain'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;                     filled&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; rounded&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;  &lt;br /&gt;                     special_characters&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;  &lt;br /&gt;graph &lt;span class="token operator"&gt;=&lt;/span&gt; graph_from_dot_data&lt;span class="token punctuation"&gt;(&lt;/span&gt;dot_data&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;graph&lt;span class="token punctuation"&gt;.&lt;/span&gt;write_png&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;"images/decision_tree.png"&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/07/decision_tree.png" /&gt;&lt;/p&gt;
&lt;h3 id="3.-random-forest"&gt;3. Random Forest &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#3.-random-forest"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Instantiate&lt;/span&gt;&lt;br /&gt;rf &lt;span class="token operator"&gt;=&lt;/span&gt; RandomForestClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;    &lt;br /&gt;&lt;span class="token comment"&gt;# Fit&lt;/span&gt;&lt;br /&gt;rf_model &lt;span class="token operator"&gt;=&lt;/span&gt; rf&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# training accuracy 99.74%&lt;/span&gt;&lt;br /&gt;rf_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;score&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predictions/probs on the test dataset&lt;/span&gt;&lt;br /&gt;predicted &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;rf_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;probs &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;rf_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict_proba&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Store metrics&lt;/span&gt;&lt;br /&gt;rf_accuracy &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;accuracy_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_roc_auc &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;roc_auc_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; probs&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_confus_matrix &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;confusion_matrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_classification_report &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;classification_report&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_precision &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;precision_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_recall &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;recall_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_f1 &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;f1_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Evaluate the model using 10-fold cross-validation&lt;/span&gt;&lt;br /&gt;rf_cv_scores &lt;span class="token operator"&gt;=&lt;/span&gt; cross_val_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;RandomForestClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; x_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; scoring&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; cv&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;rf_cv_mean &lt;span class="token operator"&gt;=&lt;/span&gt; np&lt;span class="token punctuation"&gt;.&lt;/span&gt;mean&lt;span class="token punctuation"&gt;(&lt;/span&gt;rf_cv_scores&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has performed possibly a little too well!&lt;/p&gt;
&lt;h3 id="4.-support-vector-machine"&gt;4. SUPPORT VECTOR MACHINE &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#4.-support-vector-machine"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Instantiate&lt;/span&gt;&lt;br /&gt;svm_model &lt;span class="token operator"&gt;=&lt;/span&gt; SVC&lt;span class="token punctuation"&gt;(&lt;/span&gt;probability&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Fit&lt;/span&gt;&lt;br /&gt;svm_model &lt;span class="token operator"&gt;=&lt;/span&gt; svm_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Accuracy&lt;/span&gt;&lt;br /&gt;svm_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;score&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predictions/probs on the test dataset&lt;/span&gt;&lt;br /&gt;predicted &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;svm_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;probs &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;svm_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict_proba&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Store metrics&lt;/span&gt;&lt;br /&gt;svm_accuracy &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;accuracy_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_roc_auc &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;roc_auc_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; probs&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_confus_matrix &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;confusion_matrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_classification_report &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;classification_report&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_precision &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;precision_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_recall &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;recall_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_f1 &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;f1_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Evaluate the model using 10-fold cross-validation&lt;/span&gt;&lt;br /&gt;svm_cv_scores &lt;span class="token operator"&gt;=&lt;/span&gt; cross_val_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;SVC&lt;span class="token punctuation"&gt;(&lt;/span&gt;probability&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;True&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; x_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; scoring&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; cv&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;svm_cv_mean &lt;span class="token operator"&gt;=&lt;/span&gt; np&lt;span class="token punctuation"&gt;.&lt;/span&gt;mean&lt;span class="token punctuation"&gt;(&lt;/span&gt;svm_cv_scores&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="5.-knn"&gt;5. KNN &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#5.-knn"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# instantiate learning model (k = 3)&lt;/span&gt;&lt;br /&gt;knn_model &lt;span class="token operator"&gt;=&lt;/span&gt; KNeighborsClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;n_neighbors&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;3&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# fit the model&lt;/span&gt;&lt;br /&gt;knn_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Accuracy&lt;/span&gt;&lt;br /&gt;knn_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;score&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predictions/probs on the test dataset&lt;/span&gt;&lt;br /&gt;predicted &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;knn_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;probs &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;knn_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict_proba&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Store metrics&lt;/span&gt;&lt;br /&gt;knn_accuracy &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;accuracy_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_roc_auc &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;roc_auc_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; probs&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_confus_matrix &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;confusion_matrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_classification_report &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;classification_report&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_precision &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;precision_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_recall &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;recall_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_f1 &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;f1_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Evaluate the model using 10-fold cross-validation&lt;/span&gt;&lt;br /&gt;knn_cv_scores &lt;span class="token operator"&gt;=&lt;/span&gt; cross_val_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;KNeighborsClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;n_neighbors&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;3&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; x_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; scoring&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; cv&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;knn_cv_mean &lt;span class="token operator"&gt;=&lt;/span&gt; np&lt;span class="token punctuation"&gt;.&lt;/span&gt;mean&lt;span class="token punctuation"&gt;(&lt;/span&gt;knn_cv_scores&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="6.-two-class-bayes"&gt;6. TWO CLASS BAYES &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#6.-two-class-bayes"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Instantiate&lt;/span&gt;&lt;br /&gt;bayes_model &lt;span class="token operator"&gt;=&lt;/span&gt; GaussianNB&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Fit the model&lt;/span&gt;&lt;br /&gt;bayes_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Accuracy&lt;/span&gt;&lt;br /&gt;bayes_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;score&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_train&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_train&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Predictions/probs on the test dataset&lt;/span&gt;&lt;br /&gt;predicted &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;bayes_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;probs &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;bayes_model&lt;span class="token punctuation"&gt;.&lt;/span&gt;predict_proba&lt;span class="token punctuation"&gt;(&lt;/span&gt;x_test&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Store metrics&lt;/span&gt;&lt;br /&gt;bayes_accuracy &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;accuracy_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_roc_auc &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;roc_auc_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; probs&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_confus_matrix &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;confusion_matrix&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_classification_report &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;classification_report&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_precision &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;precision_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_recall &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;recall_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_f1 &lt;span class="token operator"&gt;=&lt;/span&gt; metrics&lt;span class="token punctuation"&gt;.&lt;/span&gt;f1_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; predicted&lt;span class="token punctuation"&gt;,&lt;/span&gt; pos_label&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Evaluate the model using 10-fold cross-validation&lt;/span&gt;&lt;br /&gt;bayes_cv_scores &lt;span class="token operator"&gt;=&lt;/span&gt; cross_val_score&lt;span class="token punctuation"&gt;(&lt;/span&gt;KNeighborsClassifier&lt;span class="token punctuation"&gt;(&lt;/span&gt;n_neighbors&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;3&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; x_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; y_test&lt;span class="token punctuation"&gt;,&lt;/span&gt; scoring&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; cv&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;10&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;bayes_cv_mean &lt;span class="token operator"&gt;=&lt;/span&gt; np&lt;span class="token punctuation"&gt;.&lt;/span&gt;mean&lt;span class="token punctuation"&gt;(&lt;/span&gt;bayes_cv_scores&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="results"&gt;Results &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#results"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Model comparison&lt;/span&gt;&lt;br /&gt;models &lt;span class="token operator"&gt;=&lt;/span&gt; pd&lt;span class="token punctuation"&gt;.&lt;/span&gt;DataFrame&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class="token string"&gt;'Model'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'Logistic'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'d.Tree'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'r.f.'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'SVM'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'kNN'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;  &lt;span class="token string"&gt;'Bayes'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class="token string"&gt;'Accuracy'&lt;/span&gt; &lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;logit_accuracy&lt;span class="token punctuation"&gt;,&lt;/span&gt; tree_accuracy&lt;span class="token punctuation"&gt;,&lt;/span&gt; rf_accuracy&lt;span class="token punctuation"&gt;,&lt;/span&gt; svm_accuracy&lt;span class="token punctuation"&gt;,&lt;/span&gt; knn_accuracy&lt;span class="token punctuation"&gt;,&lt;/span&gt; bayes_accuracy&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class="token string"&gt;'Precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;logit_precision&lt;span class="token punctuation"&gt;,&lt;/span&gt; tree_precision&lt;span class="token punctuation"&gt;,&lt;/span&gt; rf_precision&lt;span class="token punctuation"&gt;,&lt;/span&gt; svm_precision&lt;span class="token punctuation"&gt;,&lt;/span&gt; knn_precision&lt;span class="token punctuation"&gt;,&lt;/span&gt; bayes_precision&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class="token string"&gt;'recall'&lt;/span&gt; &lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;logit_recall&lt;span class="token punctuation"&gt;,&lt;/span&gt; tree_recall&lt;span class="token punctuation"&gt;,&lt;/span&gt; rf_recall&lt;span class="token punctuation"&gt;,&lt;/span&gt; svm_recall&lt;span class="token punctuation"&gt;,&lt;/span&gt; knn_recall&lt;span class="token punctuation"&gt;,&lt;/span&gt; bayes_recall&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class="token string"&gt;'F1'&lt;/span&gt; &lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;logit_f1&lt;span class="token punctuation"&gt;,&lt;/span&gt; tree_f1&lt;span class="token punctuation"&gt;,&lt;/span&gt; rf_f1&lt;span class="token punctuation"&gt;,&lt;/span&gt; svm_f1&lt;span class="token punctuation"&gt;,&lt;/span&gt; knn_f1&lt;span class="token punctuation"&gt;,&lt;/span&gt; bayes_f1&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class="token string"&gt;'cv_precision'&lt;/span&gt; &lt;span class="token punctuation"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;logit_cv_mean&lt;span class="token punctuation"&gt;,&lt;/span&gt; tree_cv_mean&lt;span class="token punctuation"&gt;,&lt;/span&gt; rf_cv_mean&lt;span class="token punctuation"&gt;,&lt;/span&gt; svm_cv_mean&lt;span class="token punctuation"&gt;,&lt;/span&gt; knn_cv_mean&lt;span class="token punctuation"&gt;,&lt;/span&gt; bayes_cv_mean&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Print table and sort by test precision&lt;/span&gt;&lt;br /&gt;models&lt;span class="token punctuation"&gt;.&lt;/span&gt;sort_values&lt;span class="token punctuation"&gt;(&lt;/span&gt;by&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;'Precision'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; ascending&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token boolean"&gt;False&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   Model         F1 Accuracy Precision  cv_precision    recall&lt;br /&gt;    r&lt;span class="token punctuation"&gt;.&lt;/span&gt;f&lt;span class="token punctuation"&gt;.&lt;/span&gt;   &lt;span class="token number"&gt;0.976812&lt;/span&gt; &lt;span class="token number"&gt;0.989333&lt;/span&gt;  &lt;span class="token number"&gt;0.994100&lt;/span&gt;      &lt;span class="token number"&gt;0.988294&lt;/span&gt;  &lt;span class="token number"&gt;0.960114&lt;/span&gt;&lt;br /&gt;  d&lt;span class="token punctuation"&gt;.&lt;/span&gt;Tree   &lt;span class="token number"&gt;0.915088&lt;/span&gt; &lt;span class="token number"&gt;0.959667&lt;/span&gt;  &lt;span class="token number"&gt;0.901798&lt;/span&gt;      &lt;span class="token number"&gt;0.899632&lt;/span&gt;  &lt;span class="token number"&gt;0.928775&lt;/span&gt;&lt;br /&gt;     SVM   &lt;span class="token number"&gt;0.902098&lt;/span&gt; &lt;span class="token number"&gt;0.953333&lt;/span&gt;  &lt;span class="token number"&gt;0.885989&lt;/span&gt;      &lt;span class="token number"&gt;0.863300&lt;/span&gt;  &lt;span class="token number"&gt;0.918803&lt;/span&gt;&lt;br /&gt;     kNN   &lt;span class="token number"&gt;0.902959&lt;/span&gt; &lt;span class="token number"&gt;0.953000&lt;/span&gt;  &lt;span class="token number"&gt;0.873502&lt;/span&gt;      &lt;span class="token number"&gt;0.831590&lt;/span&gt;  &lt;span class="token number"&gt;0.934473&lt;/span&gt;&lt;br /&gt;   Bayes   &lt;span class="token number"&gt;0.530179&lt;/span&gt; &lt;span class="token number"&gt;0.808000&lt;/span&gt;  &lt;span class="token number"&gt;0.620229&lt;/span&gt;      &lt;span class="token number"&gt;0.831590&lt;/span&gt;  &lt;span class="token number"&gt;0.462963&lt;/span&gt;&lt;br /&gt;Logistic   &lt;span class="token number"&gt;0.327684&lt;/span&gt; &lt;span class="token number"&gt;0.762000&lt;/span&gt;  &lt;span class="token number"&gt;0.483333&lt;/span&gt;      &lt;span class="token number"&gt;0.526624&lt;/span&gt;  &lt;span class="token number"&gt;0.247863&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the above results table, it is clear the Random Forest is the best model based on Accuracy, Precision and Recall metrics. The performance is so good, that I would be concerned about overfitting and a lack of generalisation to future periods of data. However, the classifier was evaluated with K-folds cross-validation (K=10) and also evaluated on the test dataset.&lt;/p&gt;
&lt;p&gt;To use the trained model later, it's first best practice to re-train on the entire dataset to get the best trained model. Then save the pickle i.e. serialised model.&lt;/p&gt;
&lt;pre class="language-python"&gt;&lt;code class="language-python"&gt;&lt;span class="token comment"&gt;# Create x and y from all data&lt;/span&gt;&lt;br /&gt;y &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;br /&gt;x &lt;span class="token operator"&gt;=&lt;/span&gt; df&lt;span class="token punctuation"&gt;.&lt;/span&gt;drop&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;&lt;span class="token string"&gt;'left'&lt;/span&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; axis&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token number"&gt;1&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Re-train model on all data&lt;/span&gt;&lt;br /&gt;rf_model &lt;span class="token operator"&gt;=&lt;/span&gt; rf&lt;span class="token punctuation"&gt;.&lt;/span&gt;fit&lt;span class="token punctuation"&gt;(&lt;/span&gt;x&lt;span class="token punctuation"&gt;,&lt;/span&gt; y&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Save model&lt;/span&gt;&lt;br /&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; cPickle&lt;br /&gt;&lt;span class="token keyword"&gt;with&lt;/span&gt; &lt;span class="token builtin"&gt;open&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;'churn_classifier.pkl'&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;'wb'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token keyword"&gt;as&lt;/span&gt; fid&lt;span class="token punctuation"&gt;:&lt;/span&gt;&lt;br /&gt;    cPickle&lt;span class="token punctuation"&gt;.&lt;/span&gt;dump&lt;span class="token punctuation"&gt;(&lt;/span&gt;rf_model&lt;span class="token punctuation"&gt;,&lt;/span&gt; fid&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The unabridged version of the above code can be found &lt;a href="https://github.com/ucg8j/kaggle_HR"&gt;here on github&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="good-resources"&gt;Good Resources &lt;a class="direct-link" href="https://lukesingham.com/whos-going-to-leave-next/#good-resources"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.statsmodels.org/dev/contrasts.html"&gt;Contrasts/Encoding in Python&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://stats.idre.ucla.edu/sas/webbooks/reg/chapter5/regression-with-saschapter-5-additional-coding-systems-for-categorical-variables-in-regressionanalysis/"&gt;UCLA's Contrasts/Encoding in SAS&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://rstudio-pubs-static.s3.amazonaws.com/65059_586f394d8eb84f84b1baaf56ffb6b47f.html"&gt;Contrasts/Encoding in R&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://scikit-learn.org/stable/modules/preprocessing.html"&gt;Sci-kit Learn's &amp;quot;Preprocessing&amp;quot; Doc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.algosome.com/articles/dummy-variable-trap-regression.html"&gt;Simple Explanation of the Dummy Variable Trap&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://stats.stackexchange.com/questions/199549/how-can-machine-learning-models-gbm-nn-etc-be-used-for-survival-analysis/263946#263946"&gt;Cross Validated: How can machine learning models be used for survival analysis?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://ragulpr.github.io/2016/12/22/WTTE-RNN-Hackless-churn-modeling/"&gt;Healthy criticism of the approach I took&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://tryolabs.com/blog/2013/03/25/why-accuracy-alone-bad-measure-classification-tasks-and-what-we-can-do-about-it/"&gt;A very well written (human speak) blog on accuracy vs. recall &amp;amp; precision&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.damienfrancois.be/blog/files/modelperfcheatsheet.pdf"&gt;Model Performance Cheat Sheet&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://classeval.wordpress.com/introduction/"&gt;Very simple explanation of ML evaluation metrics with nice visuals&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://kevinzakka.github.io/2016/07/13/k-nearest-neighbor/"&gt;A good blog on KNN using Python&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.datasciencecentral.com/profiles/blogs/customer-churn-logistic-regression-with-r"&gt;Good process schema&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.capgemini.com/wp-content/uploads/2017/07/Predictive_Modeling_Using_Transactional_Data.pdf"&gt;High level overview of using transactional data for churn modelling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Wed, 12 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/whos-going-to-leave-next/</guid></item><item><title>How to show an iOS network activity indicator when a request is in progress?</title><link>https://goshacmd.com/react-native-activity-indicator-fetch/</link><author>Gosha Spark</author><pubDate>Wed, 12 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/react-native-activity-indicator-fetch/</guid></item><item><title>Apache Impala Internals Deep Dive with Tanel Poder + Gluent New World Training Month</title><link>https://tanelpoder.com/2017/07/11/apache-impala-internals-deep-dive-with-tanel-poder-gluent-new-world-training-month/</link><description>&lt;p&gt;We are running a “Gluent New World training month” in this July and have scheduled 3 webinars on following Wednesdays for this!&lt;/p&gt;
&lt;p&gt;The first webinar with Michael Rainey is going to cover modern alternatives to the traditional old-school “ETL on a RDBMS” approach for data integration and sharing. Then on the next Wednesday I will demonstrate some Apache Impala SQL engine’s internals, with commentary from an Oracle database geek’s angle (I plan to get pretty deep &amp;amp; technical). And in the end of the month, a Gluent customer Vistra Energy will talk about their journey towards a modern analytics platforms.&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Tue, 11 Jul 2017 19:51:21 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/2017/07/11/apache-impala-internals-deep-dive-with-tanel-poder-gluent-new-world-training-month/</guid></item><item><title>Wanted: Collaborative Writer in Berlin</title><link>https://svedic.org/personal/wanted-collaborative-writer-in-berlin</link><description>“The advantage of collaborative writing is that you end up with something for which you will not be personally blamed.&amp;#8221;—Scott Adams This is a unique job, for unique writers. The client is a well-off individual, the owner of a boring &amp;#8230; &lt;a href="https://svedic.org/personal/wanted-collaborative-writer-in-berlin"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Tue, 11 Jul 2017 14:17:13 GMT</pubDate><guid isPermaLink="true">https://svedic.org/personal/wanted-collaborative-writer-in-berlin</guid></item><item><title>CPU core estimation with JavaScript</title><link>https://eligrey.com/blog/cpu-core-estimation-with-javascript/</link><description>(Update) Standardization I have standardized navigator.cores as navigator.hardwareConcurrency, and it is now supported natively in Chrome, Safari, Firefox, and Opera. Our polyfill has renamed the APIs accordingly. Since the initial blog post, Core Estimator has been updated to estimate much faster and now has instant estimation in Chrome through PNaCl. navigator.cores So you just built some [&amp;#8230;]</description><author>Eli Grey</author><pubDate>Tue, 11 Jul 2017 11:44:52 GMT</pubDate><guid isPermaLink="true">https://eligrey.com/blog/cpu-core-estimation-with-javascript/</guid></item><item><title>Redis and Node Part 1: The Basics</title><link>https://thomashunter.name/posts/2017-07-11-redis-and-node-part-1-the-basics</link><author>Thomas Hunter II</author><pubDate>Tue, 11 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-07-11-redis-and-node-part-1-the-basics</guid></item><item><title>Generating Random Poems with Python</title><link>https://www.hallada.net/2017/07/11/generating-random-poems-with-python.html</link><description>&lt;p&gt;In this post, I will demonstrate how to generate random text using a few lines
of standard python and then progressively refine the output until it looks
poem-like.&lt;/p&gt;

&lt;p&gt;If you would like to follow along with this post and run the code snippets
yourself, you can clone &lt;a href="https://github.com/thallada/nlp/"&gt;my NLP repository&lt;/a&gt;
and run &lt;a href="https://github.com/thallada/nlp/blob/master/edX%20Lightning%20Talk.ipynb"&gt;the Jupyter
notebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You might not realize it, but you probably use an app everyday that can generate
random text that sounds like you: your phone keyboard.
&lt;!--excerpt--&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Suggested next words UI feature on the iOS
keyboard" src="/img/blog/phone_keyboard.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Just by tapping the next suggested word over and over, you can generate text. So how does it work?&lt;/p&gt;

&lt;h2 id="corpus"&gt;Corpus&lt;/h2&gt;

&lt;p&gt;First, we need a &lt;strong&gt;corpus&lt;/strong&gt;: the text our generator will recombine into new
sentences. In the case of your phone keyboard, this is all the text you’ve ever
typed into your keyboard. For our example, let’s just start with one sentence:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;corpus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'The quick brown fox jumps over the lazy dog'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="tokenization"&gt;Tokenization&lt;/h2&gt;

&lt;p&gt;Now we need to split this corpus into individual &lt;strong&gt;tokens&lt;/strong&gt; that we can operate
on. Since our objective is to eventually predict the next word from the previous
word, we will want our tokens to be individual words. This process is called
&lt;strong&gt;tokenization&lt;/strong&gt;. The simplest way to tokenize a sentence into words is to split
on spaces:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'The'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'brown'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'fox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'jumps'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'over'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'lazy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="bigrams"&gt;Bigrams&lt;/h2&gt;

&lt;p&gt;Now, we will want to create &lt;strong&gt;bigrams&lt;/strong&gt;. A bigram is a pair of two words that
are in the order they appear in the corpus. To create bigrams, we will iterate
through the list of the words with two indices, one of which is offset by one:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;bigrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&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="n"&gt;words&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;bigrams&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s"&gt;'The'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'brown'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'brown'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'fox'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'fox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'jumps'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'jumps'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'over'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'over'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'lazy'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'lazy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'dog'&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 do we use the bigrams to predict the next word given the first word?&lt;/p&gt;

&lt;p&gt;Return every second element where the first element matches the &lt;strong&gt;condition&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'the'&lt;/span&gt;
&lt;span class="n"&gt;next_words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bigram&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;for&lt;/span&gt; &lt;span class="n"&gt;bigram&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bigrams&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bigram&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;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;next_words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'lazy'&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;We have now found all of the possible words that can follow the condition “the”
according to our corpus: “quick” and “lazy”.&lt;/p&gt;

&lt;pre&gt;
(&lt;span style="color: blue;"&gt;The&lt;/span&gt; &lt;span style="color: red;"&gt;quick&lt;/span&gt;) (quick brown) ... (&lt;span style="color: blue;"&gt;the&lt;/span&gt; &lt;span style="color: red;"&gt;lazy&lt;/span&gt;) (lazy dog)
&lt;/pre&gt;

&lt;p&gt;Either “&lt;span style="color: red;"&gt;quick&lt;/span&gt;” or “&lt;span style="color: red;"&gt;lazy&lt;/span&gt;” could be the next word.&lt;/p&gt;

&lt;h2 id="trigrams-and-n-grams"&gt;Trigrams and N-grams&lt;/h2&gt;

&lt;p&gt;We can partition our corpus into groups of threes too:&lt;/p&gt;

&lt;pre&gt;
(&lt;span style="color: blue;"&gt;The&lt;/span&gt; &lt;span style="color: red;"&gt;quick brown&lt;/span&gt;) (quick brown fox) ... (&lt;span style="color: blue;"&gt;the&lt;/span&gt; &lt;span style="color: red;"&gt;lazy dog&lt;/span&gt;)
&lt;/pre&gt;

&lt;p&gt;Or, the condition can be two words (&lt;code class="language-plaintext highlighter-rouge"&gt;condition = 'the lazy'&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;
(The quick brown) (quick brown fox) ... (&lt;span style="color: blue;"&gt;the lazy&lt;/span&gt; &lt;span style="color: red;"&gt;dog&lt;/span&gt;)
&lt;/pre&gt;

&lt;p&gt;These are called &lt;strong&gt;trigrams&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can partition any &lt;strong&gt;N&lt;/strong&gt; number of words together as &lt;strong&gt;n-grams&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id="conditional-frequency-distributions"&gt;Conditional Frequency Distributions&lt;/h2&gt;

&lt;p&gt;Earlier, we were able to compute the list of possible words to follow a
condition:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;next_words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'lazy'&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;But, in order to predict the next word, what we really want to compute is what
is the most likely next word out of all of the possible next words. In other
words, find the word that occurred the most often after the condition in the
corpus.&lt;/p&gt;

&lt;p&gt;We can use a &lt;strong&gt;Conditional Frequency Distribution (CFD)&lt;/strong&gt; to figure that out! A
&lt;strong&gt;CFD&lt;/strong&gt; can tell us: given a &lt;strong&gt;condition&lt;/strong&gt;, what is &lt;strong&gt;likelihood&lt;/strong&gt; of each
possible outcome.&lt;/p&gt;

&lt;p&gt;This is an example of a CFD with two conditions, displayed in table form. It is
counting words appearing in a text collection (source: nltk.org).&lt;/p&gt;

&lt;p&gt;&lt;img alt="Two tables, one for each condition: &amp;quot;News&amp;quot; and &amp;quot;Romance&amp;quot;. The first column of
each table is 5 words: &amp;quot;the&amp;quot;, &amp;quot;cute&amp;quot;, &amp;quot;Monday&amp;quot;, &amp;quot;could&amp;quot;, and &amp;quot;will&amp;quot;. The second
column is a tally of how often the word at the start of the row appears in the
corpus." src="http://www.nltk.org/images/tally2.png" /&gt;&lt;/p&gt;

&lt;p&gt;Let’s change up our corpus a little to better demonstrate the CFD:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'The quick brown fox jumped over the '&lt;/span&gt;
         &lt;span class="s"&gt;'lazy dog and the quick cat'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'The'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'brown'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'fox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'jumped'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'over'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'lazy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'and'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'cat'&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;Now, let’s build the CFD. I use
&lt;a href="https://docs.python.org/2/library/collections.html#defaultdict-objects"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;defaultdicts&lt;/code&gt;&lt;/a&gt;
to avoid having to initialize every new dict.&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;
&lt;span class="n"&gt;cfd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&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;for&lt;/span&gt; &lt;span class="n"&gt;i&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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  &lt;span class="c1"&gt;# loop to the next-to-last word
&lt;/span&gt;    &lt;span class="n"&gt;cfd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;words&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="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()][&lt;/span&gt;&lt;span class="n"&gt;words&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;+&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;lower&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="c1"&gt;# pretty print the defaultdict
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfd&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'and'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'the'&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="s"&gt;'brown'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'fox'&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="s"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'and'&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="s"&gt;'fox'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'jumped'&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="s"&gt;'jumped'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'over'&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="s"&gt;'lazy'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'dog'&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="s"&gt;'over'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'the'&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="s"&gt;'quick'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'brown'&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="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'lazy'&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="s"&gt;'quick'&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, what’s the most likely word to follow &lt;code class="language-plaintext highlighter-rouge"&gt;'the'&lt;/code&gt;?&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'the'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="s"&gt;'quick'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whole sentences can be the conditions and values too. Which is basically the way
&lt;a href="http://www.cleverbot.com/"&gt;cleverbot&lt;/a&gt; works.&lt;/p&gt;

&lt;p&gt;&lt;img alt="An example of a conversation with Cleverbot" src="/img/blog/cleverbot.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="random-text"&gt;Random Text&lt;/h2&gt;

&lt;p&gt;Lets put this all together, and with a little help from
&lt;a href="http://www.nltk.org/"&gt;nltk&lt;/a&gt; generate some random text.&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;nltk&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;

&lt;span class="n"&gt;TEXT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nltk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gutenberg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'austen-emma.txt'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# NLTK shortcuts :)
&lt;/span&gt;&lt;span class="n"&gt;bigrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nltk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bigrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cfd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nltk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConditionalFreqDist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bigrams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# pick a random word from the corpus to start with
&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# generate 15 more words
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&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;15&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;word&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;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cfd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;keys&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;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which outputs something like:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;her reserve and concealment towards some feelings in moving slowly together .
You will shew
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great! This is basically what the phone keyboard suggestions are doing. Now how
do we take this to the next level and generate text that looks like a poem?&lt;/p&gt;

&lt;h2 id="random-poems"&gt;Random Poems&lt;/h2&gt;

&lt;p&gt;Generating random poems is accomplished by limiting the choice of the next word
by some constraint:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;words that rhyme with the previous line&lt;/li&gt;
  &lt;li&gt;words that match a certain syllable count&lt;/li&gt;
  &lt;li&gt;words that alliterate with words on the same line&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="rhyming"&gt;Rhyming&lt;/h2&gt;

&lt;h3 id="written-english--spoken-english"&gt;Written English != Spoken English&lt;/h3&gt;

&lt;p&gt;English has a highly &lt;strong&gt;nonphonemic orthography&lt;/strong&gt;, meaning that the letters often
have no correspondence to the pronunciation. E.g.:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“meet” vs. “meat”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The vowels are spelled differently, yet they rhyme &lt;sup id="fnref:1"&gt;&lt;a class="footnote" href="#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;So if the spelling of the words is useless in telling us if two words rhyme,
what can we use instead?&lt;/p&gt;

&lt;h3 id="international-phonetic-alphabet-ipa"&gt;International Phonetic Alphabet (IPA)&lt;/h3&gt;

&lt;p&gt;The IPA is an alphabet that can represent all varieties of human pronunciation.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;meet: /mit/&lt;/li&gt;
  &lt;li&gt;meat: /mit/&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that this is only the IPA transcription for only one &lt;strong&gt;accent&lt;/strong&gt; of English.
Some English speakers may pronounce these words differently which could be
represented by a different IPA transcription.&lt;/p&gt;

&lt;h2 id="syllables"&gt;Syllables&lt;/h2&gt;

&lt;p&gt;How can we determine the number of syllables in a word? Let’s consider the two
words “poet” and “does”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“poet” = 2 syllables&lt;/li&gt;
  &lt;li&gt;“does” = 1 syllable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The vowels in these two words are written the same, but are pronounced
differently with a different number of syllables.&lt;/p&gt;

&lt;p&gt;Can the IPA tell us the number of syllables in a word too?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;poet: /ˈpoʊət/&lt;/li&gt;
  &lt;li&gt;does: /ˈdʌz/&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not really… We cannot easily identify the number of syllables from those
transcriptions. Sometimes the transcriber denotes syllable breaks with a &lt;code class="language-plaintext highlighter-rouge"&gt;.&lt;/code&gt; or
a &lt;code class="language-plaintext highlighter-rouge"&gt;'&lt;/code&gt;, but sometimes they don’t.&lt;/p&gt;

&lt;h3 id="arpabet"&gt;Arpabet&lt;/h3&gt;

&lt;p&gt;The Arpabet is a phonetic alphabet developed by ARPA in the 70s that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Encodes phonemes specific to American English.&lt;/li&gt;
  &lt;li&gt;Meant to be a machine readable code. It is ASCII only.&lt;/li&gt;
  &lt;li&gt;Denotes how stressed every vowel is from 0-2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is perfect! Because of that third bullet, a word’s syllable count equals
the number of digits in the Arpabet encoding.&lt;/p&gt;

&lt;h3 id="cmu-pronouncing-dictionary-cmudict"&gt;CMU Pronouncing Dictionary (CMUdict)&lt;/h3&gt;

&lt;p&gt;A large open source dictionary of English words to North American pronunciations
in Arpanet encoding. Conveniently, it is also in NLTK…&lt;/p&gt;

&lt;h3 id="counting-syllables"&gt;Counting Syllables&lt;/h3&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nltk.corpus&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cmudict&lt;/span&gt;
&lt;span class="n"&gt;cmu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cmudict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_syllables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;lower_word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&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;lower_word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cmu&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;max&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;y&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;y&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="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="n"&gt;digits&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;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cmu&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lower_word&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"poet: {}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;does: {}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count_syllables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"poet"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                  &lt;span class="n"&gt;count_syllables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"does"&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;Results in:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;poet: 2
does: 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="buzzfeed-haiku-generator"&gt;Buzzfeed Haiku Generator&lt;/h2&gt;

&lt;p&gt;To see this in action, try out a haiku generator I created that uses Buzzfeed
article titles as a corpus. It does not incorporate rhyming, it just counts the
syllables to make sure it’s &lt;a href="https://en.wikipedia.org/wiki/Haiku"&gt;5-7-5&lt;/a&gt;. You can view the full code
&lt;a href="https://github.com/thallada/nlp/blob/master/generate_poem.py"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Buzzfeed Haiku Generator" src="/img/blog/buzzfeed.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Run it live at:
&lt;a href="http://mule.hallada.net/nlp/buzzfeed-haiku-generator/"&gt;http://mule.hallada.net/nlp/buzzfeed-haiku-generator/&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="syntax-aware-generation"&gt;Syntax-aware Generation&lt;/h2&gt;

&lt;p&gt;Remember these?&lt;/p&gt;

&lt;p&gt;&lt;img alt="Example Mad Libs: &amp;quot;A Visit to the Dentist&amp;quot;" src="/img/blog/madlibs.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Mad Libs worked so well because they forced the random words (chosen by the
players) to fit into the syntactical structure and parts-of-speech of an
existing sentence.&lt;/p&gt;

&lt;p&gt;You end up with &lt;strong&gt;syntactically&lt;/strong&gt; correct sentences that are &lt;strong&gt;semantically&lt;/strong&gt;
random. We can do the same thing!&lt;/p&gt;

&lt;h3 id="nltk-syntax-trees"&gt;NLTK Syntax Trees!&lt;/h3&gt;

&lt;p&gt;NLTK can parse any sentence into a &lt;a href="http://www.nltk.org/book/ch08.html"&gt;syntax
tree&lt;/a&gt;. We can utilize this syntax tree
during poetry generation.&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;stat_parser&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Parser&lt;/span&gt;
&lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Parser&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="s"&gt;'The quick brown fox jumps over the lazy dog.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Syntax tree output as an
&lt;a href="https://en.wikipedia.org/wiki/S-expression"&gt;s-expression&lt;/a&gt;:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;(S
  (NP (DT the) (NN quick))
  (VP
    (VB brown)
    (NP
      (NP (JJ fox) (NN jumps))
      (PP (IN over) (NP (DT the) (JJ lazy) (NN dog)))))
  (. .))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pretty_print&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;And the same tree visually pretty printed in ASCII:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;                              S                            
      ________________________|__________________________   
     |               VP                                  | 
     |           ____|_____________                      |  
     |          |                  NP                    | 
     |          |         _________|________             |  
     |          |        |                  PP           | 
     |          |        |          ________|___         |  
     NP         |        NP        |            NP       | 
  ___|____      |     ___|____     |     _______|____    |  
 DT       NN    VB   JJ       NN   IN   DT      JJ   NN  . 
 |        |     |    |        |    |    |       |    |   |  
the     quick brown fox     jumps over the     lazy dog  . 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;NLTK also performs &lt;a href="http://www.nltk.org/book/ch05.html"&gt;part-of-speech tagging&lt;/a&gt;
on the input sentence and outputs the tag at each node in the tree. Here’s what
each of those mean:&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Sentence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;VP&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Verb Phrase&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;NP&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Noun Phrase&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;DT&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Determiner&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;NN&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Noun (common, singular)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;VB&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Verb (base form)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;JJ&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Adjective (or numeral, ordinal)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Punctuation&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Now, let’s use this information to swap matching syntax sub-trees between two
corpora (&lt;a href="https://github.com/thallada/nlp/blob/master/syntax_aware_generate.py"&gt;source for the generate
function&lt;/a&gt;).&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;syntax_aware_generate&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt;

&lt;span class="c1"&gt;# inserts matching syntax subtrees from trump.txt into
# trees from austen-emma.txt
&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'trump.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;(SBARQ
  (SQ
    (NP (PRP I))
    (VP (VBP do) (RB not) (VB advise) (NP (DT the) (NN custard))))
  (. .))
I do not advise the custard .
==============================
I do n't want the drone !
(SBARQ
  (SQ
    (NP (PRP I))
    (VP (VBP do) (RB n't) (VB want) (NP (DT the) (NN drone))))
  (. !))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Above the line is a sentence selected from a corpus of Jane Austen’s &lt;em&gt;Emma&lt;/em&gt;.
Below it is a sentence generated by walking down the syntax tree and finding
sub-trees from a corpus of Trump’s tweets that match the same syntactical
structure and then swapping the words in.&lt;/p&gt;

&lt;p&gt;The result can sometimes be amusing, but more often than not, this approach
doesn’t fare much better than the n-gram based generation.&lt;/p&gt;

&lt;h3 id="spacy"&gt;spaCy&lt;/h3&gt;

&lt;p&gt;I’m only beginning to experiment with the &lt;a href="https://spacy.io/"&gt;spaCy&lt;/a&gt; Python
library, but I like it a lot. For one, it is much, much faster than NLTK:&lt;/p&gt;

&lt;p&gt;&lt;img alt="spaCy speed comparison" src="/img/blog/spacy_speed.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://spacy.io/docs/api/#speed-comparison"&gt;https://spacy.io/docs/api/#speed-comparison&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://spacy.io/docs/api/"&gt;API&lt;/a&gt; takes a little getting used to coming from
NLTK. It doesn’t seem to have any sort of out-of-the-box solution to printing
out syntax trees like above, but it does do &lt;a href="https://spacy.io/docs/api/tagger"&gt;part-of-speech
tagging&lt;/a&gt; and &lt;a href="https://spacy.io/docs/api/dependencyparser"&gt;dependency relation
mapping&lt;/a&gt; which should accomplish
about the same. You can see both of these visually with
&lt;a href="https://demos.explosion.ai/displacy/"&gt;displaCy&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="neural-network-based-generation"&gt;Neural Network Based Generation&lt;/h2&gt;

&lt;p&gt;If you haven’t heard all the buzz about &lt;a href="https://en.wikipedia.org/wiki/Artificial_neural_network"&gt;neural
networks&lt;/a&gt;, they are a
particular technique for &lt;a href="https://en.wikipedia.org/wiki/Machine_learning"&gt;machine
learning&lt;/a&gt; that’s inspired by our
understanding of the human brain. They are structured into layers of nodes which
have connections to other nodes in other layers of the network. These
connections have weights which each node multiplies by the corresponding input
and enters into a particular &lt;a href="https://en.wikipedia.org/wiki/Activation_function"&gt;activation
function&lt;/a&gt; to output a single
number. The optimal weights for solving a particular problem with the network
are learned by training the network using
&lt;a href="https://en.wikipedia.org/wiki/Backpropagation"&gt;backpropagation&lt;/a&gt; to perform
&lt;a href="https://en.wikipedia.org/wiki/Gradient_descent"&gt;gradient descent&lt;/a&gt; on a
particular &lt;a href="https://en.wikipedia.org/wiki/Loss_function"&gt;cost function&lt;/a&gt; that
tries to balance getting the correct answer while also
&lt;a href="https://en.wikipedia.org/wiki/Regularization_(mathematics)"&gt;generalizing&lt;/a&gt; the
network enough to perform well on data the network hasn’t seen before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Long_short-term_memory"&gt;Long short-term memory
(LSTM)&lt;/a&gt; is a type of
&lt;a href="https://en.wikipedia.org/wiki/Recurrent_neural_network"&gt;recurrent neural network
(RNN)&lt;/a&gt; (a network with
cycles) that can remember previous values for a short or long period of time.
This property makes them remarkably effective at a multitude of tasks, one of
which is predicting text that will follow a given sequence. We can use this to
continually generate text by inputting a seed, appending the generated output to
the end of the seed, removing the first element from the beginning of the seed,
and then inputting the seed again, following the same process until we’ve
generated enough text from the network (&lt;a href="http://www.cs.utoronto.ca/~ilya/pubs/2011/LANG-RNN.pdf"&gt;paper on using RNNs to generate
text&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Luckily, a lot of smart people have done most of the legwork so you can just
download their neural network architecture and train it yourself. There’s
&lt;a href="https://github.com/karpathy/char-rnn"&gt;char-rnn&lt;/a&gt; which has some &lt;a href="http://karpathy.github.io/2015/05/21/rnn-effectiveness/"&gt;really exciting
results for generating texts (e.g. fake
Shakespeare)&lt;/a&gt;. There’s
also &lt;a href="https://github.com/larspars/word-rnn"&gt;word-rnn&lt;/a&gt; which is a modified
version of char-rnn that operates on words as a unit instead of characters.
Follow &lt;a href="/2017/06/20/how-to-install-tensorflow-on-ubuntu-16-04.html"&gt;my last blog post on how to install TensorFlow on Ubuntu
16.04&lt;/a&gt; and
you’ll be almost ready to run a TensorFlow port of word-rnn:
&lt;a href="https://github.com/hunkim/word-rnn-tensorflow"&gt;word-rnn-tensorflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I plan on playing around with NNs a lot more to see what kind of poetry-looking
text I can generate from them.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;

      &lt;p&gt;Fun fact: They used to be pronounced differently in Middle English during
the invention of the printing press and standardized spelling. The &lt;a href="https://en.wikipedia.org/wiki/Great_Vowel_Shift"&gt;Great
Vowel Shift&lt;/a&gt; happened
after, and is why they are now pronounced the same. &lt;a class="reversefootnote" href="#fnref:1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>Tyler Hallada - Blog</author><pubDate>Tue, 11 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hallada.net/2017/07/11/generating-random-poems-with-python.html</guid></item><item><title>Stateful Callbacks in Python</title><link>https://tuckersiemens.com/posts/stateful-callbacks-in-python/</link><description>&lt;p&gt;If you're unfamiliar with what a callback is, don't worry, we can sort that out
quickly. If callbacks are old hat for you you might want to skip to
&lt;a href="https://tuckersiemens.com/posts/stateful-callbacks-in-python/#stateful-callbacks"&gt;the interesting bit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Simply put, a callback is a function that is passed as an argument to
another function which may execute it.&lt;/p&gt;</description><author>Reilly Tucker Siemens</author><pubDate>Mon, 10 Jul 2017 18:54:00 GMT</pubDate><guid isPermaLink="true">https://tuckersiemens.com/posts/stateful-callbacks-in-python/</guid></item><item><title>Audio APIs, Part 3: WASAPI / Windows</title><link>https://bastibe.de/2017-07-10-audio-apis-wasapi.html</link><description>&lt;p&gt;This is part three of a three-part series on the native audio APIs for Windows, Linux, and macOS. This third part is about WASAPI on Windows.&lt;/p&gt;
&lt;p&gt;It has long been a major frustration for my work that Python does not have a great package for playing and recording audio. My first step to improve this situation was a small contribution to &lt;a href="https://people.csail.mit.edu/hubert/pyaudio/"&gt;PyAudio&lt;/a&gt;, a CPython extension that exposes the C library &lt;a href="http://www.portaudio.com/"&gt;PortAudio&lt;/a&gt; to Python. However, I soon realized that PyAudio mirrors PortAudio's C API a bit too closely for comfort. Thus, I set out to write &lt;a href="https://github.com/bastibe/PySoundCard"&gt;PySoundCard&lt;/a&gt;, which is a higher-level wrapper for PortAudio that tries to be more pythonic and uses NumPy arrays instead of untyped &lt;code&gt;bytes&lt;/code&gt; buffers for audio data. However, I then realized that PortAudio itself had some inherent problems that a wrapper would not be able to solve, and a truly great solution would need to do it the hard way:&lt;/p&gt;
&lt;p&gt;Instead of relying on PortAudio, I would have to use the native audio APIs of the three major platforms directly, and implement a simple, cross-platform, high-level, NumPy-aware Python API myself. This effort resulted in &lt;a href="https://github.com/bastibe/Python-Audio"&gt;PythonAudio&lt;/a&gt;, a new pure-Python package that uses &lt;a href="http://cffi.readthedocs.io/en/latest/"&gt;CFFI&lt;/a&gt; to talk to &lt;a href="https://www.freedesktop.org/wiki/Software/PulseAudio/"&gt;PulseAudio&lt;/a&gt; on Linux, &lt;a href="https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html"&gt;Core Audio&lt;/a&gt; on macOS, and &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455(v=vs.85"&gt;WASAPI&lt;/a&gt;.aspx)&lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt; on Windows.&lt;/p&gt;
&lt;p&gt;This series of blog posts summarizes my experiences with these three APIs and outlines the basic structure of how to use them. For reference, the singular use case in PythonAudio is block-wise playing/recording of &lt;code&gt;float&lt;/code&gt; data at arbitrary sampling rates and block sizes. All available sound cards should be listable and selectable, with correct detection of the system default sound cards (a feature that is very unreliable in PortAudio).&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;WASAPI&lt;/h1&gt;
&lt;p&gt;WASAPI is one of several native audio libraries in Windows. PortAudio actually &lt;a href="http://portaudio.com/docs/v19-doxydocs/compile_windows.html"&gt;supports five of them&lt;/a&gt;: &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd743883(v=vs.85"&gt;Windows Multimedia (MME)&lt;/a&gt;.aspx), the first built-in audio API for Windows 3.1x; &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ee416960(v=vs.85"&gt;DirectSound&lt;/a&gt;.aspx), the audio subsystem of DirectX for Windows 95;  &lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/kernel-streaming"&gt;Windows Driver Model / Kernel Streaming (WDM/KS)&lt;/a&gt;, the improved audio system for Windows 98; &lt;a href="https://en.wikipedia.org/wiki/Audio_Stream_Input/Output"&gt;ASIO&lt;/a&gt;, a third-party API developed by Steinberg to make pro audio possible on Windows; and finally, &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd370784(v=vs.85"&gt;Windows Audio Session API (WASAPI)&lt;/a&gt;.aspx), introduced in Windows Vista to bring a modern audio API to Windows.&lt;/p&gt;
&lt;p&gt;In other words, audio on Windows has a long and troubled history, and has had a lot of opportunity for experimentation. It should then be no surprise that WASAPI is a clean and well-documented audio API that avoids many of the pitfalls of its predecessors and brethren. After having experienced the audio APIs of Windows, Linux, and macOS, I am beginning to understand why some programmers love Windows.&lt;/p&gt;
&lt;p&gt;But let's take a step back, and give an overview over the API. First of all, this is a cross-language API that is meant to be used from C#, with a solid bridge for C++, and a somewhat funky bridge for C. This is crucial to understand. The whole API is designed for a high-level, object-oriented runtime, but I am accessing it from a low-level language that has no concept of objects, methods, or exceptions.&lt;/p&gt;
&lt;p&gt;Objects are implemented as pointers to opaque structs, with an associated list of function pointers to methods. Every method accepts the object pointer as its first argument, and returns an error value if an exception occurred. Both inputs and outputs are function arguments, with outputs being implemented as pointer-to-pointer values. While this looks convoluted to a C programmer, it is actually a very clean mapping of object oriented concepts to C that never gave me any headaches.&lt;/p&gt;
&lt;p&gt;However, there are a few edge cases that did take me a while to understand: Since the C API is inherently not polymorphic, you sometimes have to manually specify types as cryptic UUID structs. Figuring out how to convert the UUID strings from the header files to such structs was not easy.  Similarly, it took me a while to reverse-engineer that strings in Windows are actually &lt;code&gt;uint16&lt;/code&gt;, despite being declared &lt;code&gt;char&lt;/code&gt;. But issues such as these are to be expected in a cross-language API.&lt;/p&gt;
&lt;p&gt;In general, I did not find a good overview on how to interpret high-level C#-concepts in C. For example, it took a long time until I learned that objects in C# are reference counted, and that I would have to manage reference counts manually. Similarly, I had one rather thorny issue with memory allocations: in rare occasions (&lt;code&gt;PROPVARIANT&lt;/code&gt;), C# is expected to re-allocate memory of an object if the object does not have enough memory when passed into a method. This does not work as intended if you don't use C#'s memory allocator to create the memory. &lt;em&gt;This&lt;/em&gt; was really painful to figure out.&lt;/p&gt;
&lt;p&gt;Another result of the API's cross-language heritage are its headers: There are &lt;em&gt;hundreds&lt;/em&gt;. And they all contain both the C API and the C++ API, separated by the occasional &lt;code&gt;#ifdef __cplusplus&lt;/code&gt; and &lt;code&gt;extern C&lt;/code&gt;. Worse yet, pretty much every data type and declaration is wrapped in multiple levels of preprocessor macros and &lt;code&gt;typedef&lt;/code&gt;. There are no doubt good reasons and a rich history for this, but it took me many hours to assemble all the necessary symbols from dozens of header files to even begin to call WASAPI functions.&lt;/p&gt;
&lt;p&gt;Nevertheless, once these hurdles are overcome, the actual WASAPI API itself is well-structured and reasonably simple. You acquire an &lt;code&gt;IMMDeviceEnumerator&lt;/code&gt;, which returns &lt;code&gt;IMMDeviceCollections&lt;/code&gt; for microphones and speakers. These contain &lt;code&gt;IMMDevices&lt;/code&gt;, which represent sound cards and their properties. You activate an &lt;code&gt;IMMDevice&lt;/code&gt; with a desired data format to get an &lt;code&gt;IAudioClient&lt;/code&gt;, which in turns produces an &lt;code&gt;IAudioRenderClient&lt;/code&gt; or &lt;code&gt;IAudioCaptureClient&lt;/code&gt; for playback or recording, respectively. Playback and recording themselves are done by requesting a buffer, and reading or writing raw data to that buffer. This is about as straight-forward as APIs get.&lt;/p&gt;
&lt;p&gt;The documentation deserves even more praise: I have rarely seen such a well-documented API. There are high-level overview articles, there is commented example code, every object is described abstractly, and every method is described in detail and in reference to related methods and example code. There is no corner case that is left undescribed, and no error code without a detailed explanation. Truly, this is &lt;em&gt;exceptional&lt;/em&gt; documentation that is a joy to work with!&lt;/p&gt;
&lt;p&gt;In conclusion, WASAPI leaves me in a situation I am very unfamiliar with: praising Windows. There is a non-trivial impedance mismatch between C and C# that has to be overcome to &lt;em&gt;use&lt;/em&gt; WASAPI from C. But once I understood this, the API itself and its documentation were easy to use and understand. Impressive!&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;WASAPI is part of the Windows &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd370784(v=vs.85"&gt;Core Audio&lt;/a&gt;.aspx) APIs. To avoid confusion with the macOS API of the same name, I will always to refer to it as WASAPI.&lt;a class="footnote" href="#fnref-1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>bastibe.de</author><pubDate>Mon, 10 Jul 2017 17:12:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-07-10-audio-apis-wasapi.html</guid></item><item><title>Train to Busan</title><link>https://olshansky.info/movie/train_to_busan/</link><description>Olshansky's review of Train to Busan</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 10 Jul 2017 15:25:31 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/train_to_busan/</guid></item><item><title>Hungary travel bookmarks</title><link>https://xenodium.com/hungary-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.lonelyplanet.com/hungary/budapest/travel-tips-and-articles/my-city-budapest/40625c8c-8a11-5710-a052-1479d276913c?"&gt;My city: Budapest - Lonely Planet&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 10 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/hungary-travel-bookmarks</guid></item><item><title>Dulwich: Python library for managing git</title><link>https://www.wints.org/notes/2017.07.10/</link><description>&lt;p&gt;&lt;a href="https://www.dulwich.io/docs"&gt;Dulwich Docs&lt;/a&gt;
&lt;a href="https://www.dulwich.io/apidocs"&gt;Dulwich API Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I need to update my static site using Python, which is hosted on &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt;, and is updated via Git.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Plumbing: This is a lower-level interface with verbs that were designed to be chained together UNIX style.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Porcelain: This is the higher-level API, what an end-user of git would use &amp;ndash; fetch, pull, push etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I need just the &lt;em&gt;porcelain&lt;/em&gt; level api to automate a few commands.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 10 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.10/</guid></item><item><title>Systemd for (Impatient) Sysadmins</title><link>https://blog.tjll.net/systemd-for-impatient-sysadmins/</link><description>&lt;p&gt;
&lt;a href="http://www.freedesktop.org/wiki/Software/systemd/"&gt;systemd&lt;/a&gt;: it&amp;rsquo;s the init system that (some?) love to hate.
&lt;/p&gt;

&lt;p&gt;
Full disclosure: I find systemd a little overbearing, although by no means would consider myself militantly anti-systemd.
It has obvious advantages, and although I&amp;rsquo;m at philosophical odds with it at some levels, I see no reason why everybody shouldn&amp;rsquo;t understand it a bit better - especially now that &lt;i&gt;most&lt;/i&gt; people will need to deal with it on their favorite distros.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
This post is a sort of formalized set of operational notes I&amp;rsquo;ve made frequent use of in my experience with systemd.
I hope this post serves as another tool in your operations/sysadmin utility belt; when you need to get solutions quickly but are working with a system that relies on different tools than your normal sysv toolbox.
&lt;/p&gt;

&lt;p class="note"&gt;
&lt;b&gt;Note&lt;/b&gt;: The paths and examples here will be drawn from Arch Linux, as it&amp;rsquo;s the distro I have easiest access to during the writing of this post.
Most of it should carry over into other distributions.
&lt;/p&gt;
&lt;div class="outline-4" id="outline-container-a-systemd-primer"&gt;
&lt;h4 id="a-systemd-primer"&gt;A systemd Primer&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-org243d092"&gt;
&lt;p&gt;
If you&amp;rsquo;re unfamiliar with The Beast:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;systemd replaces the bash scripts you&amp;rsquo;re normally used to throwing in &lt;code&gt;/etc/init.d/*&lt;/code&gt; (or simple upstart/etc. configs)&lt;/li&gt;
&lt;li&gt;in addition to system services, systemd manages the following as well:
&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;code&gt;init&lt;/code&gt; (PID 1)&lt;/li&gt;
&lt;li&gt;runlevels (analagous to systemd &amp;ldquo;targets&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;several types of common sockets&lt;/li&gt;
&lt;li&gt;logging (through &lt;code&gt;journald&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-common-tasks"&gt;
&lt;h4 id="common-tasks"&gt;Common Tasks&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-orgf82c6d8"&gt;
&lt;p&gt;
I have to do these things often with my normal init scripts, so how does one accomplish them in systemd?
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-service-parameter-overrides"&gt;
&lt;h5 id="service-parameter-overrides"&gt;Service Parameter Overrides&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-orgbf70978"&gt;
&lt;p&gt;
Remember how well-behaved init scripts can be opened up to change their behavior? What if you&amp;rsquo;d like to override how a unit file operates?
&lt;/p&gt;

&lt;p&gt;
For example, say we have the following systemd unit file (actual file pulled from the Arch Linux nginx package):
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Systemd&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-variable-name"&gt;Font used to highlight variable names.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-string"&gt;Font used to highlight strings.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-constant"&gt;Font used to highlight constants and labels.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-builtin"&gt;Font used to highlight builtins.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-type"&gt;Font used to highlight type and class names.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-systemd"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-type"&gt;[Unit]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Description&lt;/span&gt;=A high performance web server and a reverse proxy server&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;After&lt;/span&gt;=network.target&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Service]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Type&lt;/span&gt;=&lt;span class="org-builtin"&gt;forking&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;PIDFile&lt;/span&gt;=/run/nginx.pid&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;PrivateDevices&lt;/span&gt;=&lt;span class="org-constant"&gt;yes&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;SyslogLevel&lt;/span&gt;=err&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;ExecStart&lt;/span&gt;=/usr/bin/nginx -g &lt;span class="org-string"&gt;'pid /run/nginx.pid; error_log stderr;'&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;ExecReload&lt;/span&gt;=/usr/bin/kill -HUP &lt;span class="org-variable-name"&gt;$MAINPID&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;KillSignal&lt;/span&gt;=&lt;span class="org-constant"&gt;SIGQUIT&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;KillMode&lt;/span&gt;=&lt;span class="org-builtin"&gt;mixed&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Install]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;WantedBy&lt;/span&gt;=multi-user.target&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
What if you want to re-nice the daemon so that nginx gets priority under high load?
&lt;/p&gt;

&lt;p&gt;
Typically this could be done under the classic init system by either munging with the init script or maybe using the &lt;a href="http://and.sourceforge.net/"&gt;auto nice daemon&lt;/a&gt;.
However, systemd exposes &lt;a href="http://www.freedesktop.org/software/systemd/man/systemd.exec.html"&gt;multiple settings&lt;/a&gt; to control these types of values.
See &lt;code class="src src-systemd"&gt;&lt;span class="org-keyword"&gt;Nice&lt;/span&gt;=&lt;/code&gt; on that page&amp;rsquo;s documentation.
&lt;/p&gt;

&lt;p&gt;
So, how does one add settings to an existing unit file? It&amp;rsquo;d be bad practice to edit the unit file shipped with the package in &lt;code&gt;/usr/lib/systemd/system&lt;/code&gt;, we want to keep custom configuration where it belongs: &lt;code&gt;/etc&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Add a file like this: &lt;code&gt;/etc/systemd/system/nginx.service.d/nice.conf&lt;/code&gt;
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Systemd&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-type"&gt;Font used to highlight type and class names.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-systemd"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-type"&gt;[Service]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Nice&lt;/span&gt;=&lt;span class="org-negation-char"&gt;-&lt;/span&gt;10&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This lets systemd know that you&amp;rsquo;re overriding the unit file with a custom setting for the service - the rest of the options will be left alone, you&amp;rsquo;re just appending the new value.
This generally works for most settings in unit files, although overriding some options requires special treatment (for example, &lt;code class="src src-systemd"&gt;&lt;span class="org-keyword"&gt;ExecStart&lt;/span&gt;=&lt;/code&gt; requires an empty option before defining a new one to avoid stringing together multiple stanzas).
&lt;/p&gt;

&lt;p&gt;
As an added bonus, if you&amp;rsquo;ve already got sufficient privileges and your &lt;code&gt;EDITOR&lt;/code&gt; environment variable setup, systemd can actually create the necessary directories and files for you - try using:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;shell&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;&lt;code&gt;systemctl edit nginx.service&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
systemd will open your &lt;code&gt;EDITOR&lt;/code&gt; and let you edit an override file, dropping into the appropriate path in &lt;code&gt;/etc&lt;/code&gt; once you write out and close the buffer.
Command-line sugar, but useful in some situations.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-viewing-boot-services"&gt;
&lt;h5 id="viewing-boot-services"&gt;Viewing Boot Services&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-org50051be"&gt;
&lt;p&gt;
One very valid point of comparison with traditional init scripts is the predictability of startup services.
Whereas you may use a command like &lt;code&gt;chkconfig&lt;/code&gt; to view which services will start at the default boot runlevel, there&amp;rsquo;s a &lt;i&gt;lot&lt;/i&gt; of different types of units systemd manages, and finding a command analagous to &lt;code&gt;chkconfig&lt;/code&gt; isn&amp;rsquo;t immediately evident.
&lt;/p&gt;

&lt;p&gt;
The key here is to leverage &lt;i&gt;targets&lt;/i&gt;.
&lt;a href="https://www.freedesktop.org/software/systemd/man/systemd.target.html"&gt;Target&lt;/a&gt; units are (very roughly) comparable to runlevels; as systemd will usually attempt to reach one overarching target at boot-time (oftentimes &lt;code&gt;multi-user.target&lt;/code&gt;).
Typically (as seen with the previous &lt;code&gt;nginx.service&lt;/code&gt; example), services ask to be initialized by your distribution&amp;rsquo;s main target entrypoint (in the &lt;code class="src src-systemd"&gt;&lt;span class="org-type"&gt;[Install]&lt;/span&gt;&lt;/code&gt; section), and that gives us a window into what to expect at boot time.
&lt;/p&gt;

&lt;p&gt;
The following command asks, &amp;ldquo;which units does &lt;code class="src src-systemd"&gt;multi-user.target&lt;/code&gt; ask to be started in order for itself to be considered up?&amp;rdquo;
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;shell&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;&lt;code&gt;systemctl list-dependencies multi-user.target&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The resulting output looks something like this:
&lt;/p&gt;

&lt;pre class="example" id="orgcb2c336"&gt;
&lt;code&gt;multi-user.target&lt;/code&gt;
&lt;code&gt;● ├─fstrim.timer&lt;/code&gt;
&lt;code&gt;● ├─gmetad.service&lt;/code&gt;
&lt;code&gt;● ├─gmond.service&lt;/code&gt;
&lt;code&gt;● ├─basic.target&lt;/code&gt;
&lt;code&gt;● │ ├─-.mount&lt;/code&gt;
&lt;code&gt;● │ ├─snapper-cleanup.timer&lt;/code&gt;
&lt;code&gt;● │ ├─snapper-timeline.timer&lt;/code&gt;
&lt;code&gt;● │ ├─tmp.mount&lt;/code&gt;
&lt;code&gt;● │ ├─paths.target&lt;/code&gt;
&lt;code&gt;● │ ├─slices.target&lt;/code&gt;
&lt;code&gt;● │ │ ├─-.slice&lt;/code&gt;
&lt;code&gt;● │ │ └─system.slice&lt;/code&gt;
&lt;code&gt;● │ ├─sockets.target&lt;/code&gt;
&lt;code&gt;● │ │ ├─cockpit.socket&lt;/code&gt;
&lt;code&gt;● │ │ └─uuidd.socket&lt;/code&gt;
&lt;code&gt;● │ └─timers.target&lt;/code&gt;
&lt;code&gt;● │   ├─logrotate.timer&lt;/code&gt;
&lt;code&gt;● │   ├─shadow.timer&lt;/code&gt;
&lt;code&gt;● │   └─systemd-tmpfiles-clean.timer&lt;/code&gt;
&lt;code&gt;● └─zfs.target&lt;/code&gt;
&lt;code&gt;●   ├─zfs-import-cache.service&lt;/code&gt;
&lt;code&gt;●   ├─zfs-mount.service&lt;/code&gt;
&lt;code&gt;●   ├─zfs-share.service&lt;/code&gt;
&lt;code&gt;●   └─zfs-zed.service&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
(I&amp;rsquo;ve trimmed out a great deal of these for brevity).
Note that in addition to visibility into plain old persistent daemons (like ganglia&amp;rsquo;s &lt;code&gt;gmetad&lt;/code&gt; and &lt;code&gt;gmond&lt;/code&gt;), the command also lists the dependency &lt;code&gt;sockets.target&lt;/code&gt; and its associated dependent sockets, so we have a pretty good picture of not only the services that will come online at boot, but any sockets systemd will open that could potentially start other services via socket activation.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-tricks-with-timers"&gt;
&lt;h4 id="tricks-with-timers"&gt;Tricks with Timers&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-orgb9efd2c"&gt;
&lt;p&gt;
One systemd replacement that I wholeheartedly find more appealing than the traditional tooling is &lt;a href="https://www.freedesktop.org/software/systemd/man/systemd.timer.html"&gt;timers&lt;/a&gt; - output is captured more easily, environment variables are more predictable, and execution is more closely tracked.
There are a few traits that timers expose that are particularly useful to be aware of.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-last-and-next-run"&gt;
&lt;h5 id="last-and-next-run"&gt;Last and Next Run&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-org2981fef"&gt;
&lt;p&gt;
Because systemd tracks when timers execute, their last and next execution time can be easily discovered:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;shell&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;&lt;code&gt;systemctl list-timers&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
You&amp;rsquo;ll see something like this:
&lt;/p&gt;

&lt;pre class="example" id="org58f63a8"&gt;
&lt;code&gt;NEXT                         LEFT                  LAST                         PASSED     UNIT&lt;/code&gt;
&lt;code&gt;Fri 2017-07-07 21:00:00 EDT  34min left            Fri 2017-07-07 20:00:00 EDT  25min ago  snapper-timeline.timer&lt;/code&gt;
&lt;code&gt;Fri 2017-07-07 22:56:43 EDT  2h 30min left         Thu 2017-07-06 22:56:43 EDT  21h ago    snapper-cleanup.timer&lt;/code&gt;
&lt;code&gt;Fri 2017-07-07 23:01:44 EDT  2h 36min left         Thu 2017-07-06 23:01:44 EDT  21h ago    systemd-tmpfiles-clean.timer&lt;/code&gt;
&lt;code&gt;Sat 2017-07-08 00:00:00 EDT  3h 34min left         Fri 2017-07-07 00:00:00 EDT  20h ago    shadow.timer&lt;/code&gt;
&lt;code&gt;Sat 2017-07-08 03:00:00 EDT  6h left               Fri 2017-07-07 03:00:00 EDT  17h ago    logrotate.timer&lt;/code&gt;
&lt;code&gt;Sat 2017-07-08 03:00:00 EDT  6h left               Fri 2017-07-07 03:00:00 EDT  17h ago    snazzer.timer&lt;/code&gt;
&lt;code&gt;Sat 2017-07-08 03:30:00 EDT  7h left               Fri 2017-07-07 03:30:00 EDT  16h ago    man-db.timer&lt;/code&gt;
&lt;code&gt;Mon 2017-07-10 03:00:00 EDT  2 days left           Mon 2017-07-03 03:00:00 EDT  4 days ago fstrim.timer&lt;/code&gt;
&lt;code&gt;Tue 2017-08-01 05:00:00 EDT  3 weeks 3 days left   Sat 2017-07-01 05:00:00 EDT  6 days ago reflector.timer&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
You can pretty easily see, for example, that logrotate will run in about six hours, and that my filesystem got trimmed four days ago on July third.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-persistence"&gt;
&lt;h5 id="persistence"&gt;Persistence&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-org1c55f39"&gt;
&lt;p&gt;
If you&amp;rsquo;ve ever written a script to run periodically, you may have questioned what happens if the machine is off when the execution time passes.
Timers have a convenient option called &lt;a href="https://www.freedesktop.org/software/systemd/man/systemd.timer.html#Persistent="&gt;&lt;code&gt;Persistent=&lt;/code&gt;&lt;/a&gt; that can record when the timer was fired, and if the interval lapsed when the timer wasn&amp;rsquo;t able to fire (if, for example, the host was offline), systemd will trigger the timer once it&amp;rsquo;s able to.
&lt;/p&gt;

&lt;p&gt;
One use case that I have for this is a job to renew Let&amp;rsquo;s Encrypt certificates.
I occasionally bring down my servers for kernel updates, and with a persistent timer, I never worry about an expiring certificate as those timers will trigger once they&amp;rsquo;re able to if the host happened to be down during that time.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-user-instances"&gt;
&lt;h4 id="user-instances"&gt;User Instances&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-orga13c0b9"&gt;
&lt;p&gt;
This is a profoundly userful feature that I&amp;rsquo;ve been using more and more often.
If you&amp;rsquo;ve ever poked around your environment in an ssh login on a systemd-based system, you&amp;rsquo;ll notice that you&amp;rsquo;re in a &lt;i&gt;session&lt;/i&gt; systemd has spawned for your user.
This is a little slice of the system that gives your user some dedicated tools, including your own session to run &lt;i&gt;user units&lt;/i&gt; in.
&lt;/p&gt;

&lt;p&gt;
Note that, by default, most systems only spawn user sessions on login and kill them on logout.
You can ensure users get more permanent sessions at boot that persist after logout with a command:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;shell&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;&lt;code&gt;loginctl enable-linger tylerjl&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
At this point you can do most of the things you can do with normal systemd units, but entirely within userspace and without the need to prepend &lt;code&gt;sudo&lt;/code&gt; to most &lt;code&gt;systemctl&lt;/code&gt; commands.
&lt;/p&gt;

&lt;p&gt;
As an example, I keep &lt;a href="https://kodi.tv/"&gt;Kodi&lt;/a&gt; backups on a ZFS dataset that I prune occasionally. My normal, non-root user has read/write permission on these backups, so why not do this as an unprivileged user (and dodge a possibly destructive &lt;code&gt;find&lt;/code&gt; invocation)?
&lt;/p&gt;

&lt;p&gt;
I have the following file at &lt;code&gt;$HOME/.config/systemd/user/kodi-backup-cleanup.timer&lt;/code&gt;:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Systemd&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-type"&gt;Font used to highlight type and class names.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-systemd"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-type"&gt;[Unit]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Description&lt;/span&gt;=regularly clean kodi backups&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Timer]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;OnCalendar&lt;/span&gt;=Thursday *-*-* 02:00:00&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Install]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;WantedBy&lt;/span&gt;=default.target&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
And an associated service at &lt;code&gt;$HOME/.config/systemd/user/kodi-backup-cleanup.service&lt;/code&gt;
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Systemd&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-string"&gt;Font used to highlight strings.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-type"&gt;Font used to highlight type and class names.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-systemd"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-type"&gt;[Unit]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Description&lt;/span&gt;=clean up old kodi backups&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Service]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;ExecStart&lt;/span&gt;=/usr/bin/find /srv/storage/backups/kodi -type f -name &lt;span class="org-string"&gt;'*.zip'&lt;/span&gt; -mtime +40 -delete&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Two important items of note:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;The units live at a specific path that the user session will recognize.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ve found that the &lt;code&gt;default&lt;/code&gt; target is brought up with the user session, providing the necessary hook to get units started at boot for users. Your distribution may vary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
All that&amp;rsquo;s left is to enable and start the timer, with the &lt;code&gt;--user&lt;/code&gt; flag to connect to the user&amp;rsquo;s instance, not the system one:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;shell&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-shell"&gt;&lt;code&gt;&lt;code&gt;systemctl --user enable --now kodi-backup-cleanup.timer&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
And my timer will fire the &lt;code&gt;find&lt;/code&gt; command as my user on the specified schedule.
What&amp;rsquo;s more, you get all the associated timer goodness in the forementioned sections (like &lt;code&gt;list-timer&lt;/code&gt;, but with &lt;code&gt;--user&lt;/code&gt;).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-path-units"&gt;
&lt;h4 id="path-units"&gt;Path Units&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-org25073b9"&gt;
&lt;p&gt;
&lt;a href="https://www.freedesktop.org/software/systemd/man/systemd.path.html"&gt;Path&lt;/a&gt; unit are a somewhat lesser used type of unit that can make a system very event-driven and add dependencies in a more natural way.
Simply, they provide a mechanism to start other services if files or directories change in some way.
A good illustration here is some of the automation I have around my Let&amp;rsquo;s Encrypt certificate renewals.
&lt;/p&gt;

&lt;p&gt;
As mentioned previously, I have a timer and service that regularly renews my certificates.
Suppose my certificate bundle ends up at &lt;code&gt;/etc/pki/certs/blog_tjll_net-bundle.pem&lt;/code&gt;.
I have a couple of services that consume this certificate; for example, &lt;code&gt;nginx&lt;/code&gt; reads the cert to serve up HTTPS.
My certificate renewal script is a nice, standalone command that just does one thing, and it would be nice to provide a decoupled way to trigger a &lt;code&gt;reload&lt;/code&gt; for nginx if the bundle gets updated.
In addition, it would be convenient for any other applications that consume the certificate (and I have a few) to watch for updates without needing to update my script all the time.
&lt;/p&gt;

&lt;p&gt;
With that in mind, consider the following path unit, &lt;code&gt;cert-bundle.path&lt;/code&gt;:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Systemd&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-type"&gt;Font used to highlight type and class names.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-systemd"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-type"&gt;[Unit]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Description&lt;/span&gt;=watches the cert bundle&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Path]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;PathModified&lt;/span&gt;=/etc/pki/certs/blog_tjll_net-bundle.pem&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Unit&lt;/span&gt;=reload-nginx.service&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Install]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;WantedBy&lt;/span&gt;=multi-user.target&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
When &lt;code class="src src-systemd"&gt;enable&lt;/code&gt;d and &lt;code class="src src-systemd"&gt;start&lt;/code&gt;ed, this unit expresses &amp;ldquo;when the cert file gets updated, start &lt;code&gt;reload-nginx.service&lt;/code&gt;&amp;rdquo;.
The associated &lt;code&gt;service&lt;/code&gt; file looks like this:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Systemd&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-builtin"&gt;Font used to highlight builtins.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-type"&gt;Font used to highlight type and class names.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-systemd"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-type"&gt;[Unit]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Description&lt;/span&gt;=reload nginx&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[Service]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Type&lt;/span&gt;=&lt;span class="org-builtin"&gt;oneshot&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;ExecStart&lt;/span&gt;=/usr/bin/systemctl reload nginx&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Pretty straightforward.
The entire flow &lt;i&gt;seems&lt;/i&gt; overcomplicated at first, but it&amp;rsquo;s actually very convenient as any updates to the certificate file outside of my script (which, because I can write buggy scripts, happens sometimes) will always trigger a reload, making the entire certificate update process agnostic to the method that actually drops the certificate there.
&lt;/p&gt;

&lt;p&gt;
Path units can activate any unit that isn&amp;rsquo;t another path and can monitor most inotify-related events, so there&amp;rsquo;s a great deal of flexibility in how they can be used.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-grab-bag"&gt;
&lt;h4 id="grab-bag"&gt;Grab Bag&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-org83d49de"&gt;
&lt;p&gt;
Aside from those broader topics, there&amp;rsquo;s a few little niceties that I&amp;rsquo;ve been using that may be useful in day-to-day operations with systemd:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Start &lt;i&gt;and&lt;/i&gt; enable a unit with one command with the &lt;code&gt;--now&lt;/code&gt; flag: &lt;code&gt;systemctl enable --now foo.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Want to quickly find problems? List failed units that need attention with &lt;code&gt;systemctl --state=failed&lt;/code&gt; (I use this one &lt;i&gt;a lot&lt;/i&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;cat&lt;/code&gt; operation got some shade thrown at it for re-inventing unix commands, but it actually shows a unit file&amp;rsquo;s contents &lt;i&gt;in addition to&lt;/i&gt; any override files that may be in effect for it (for example &lt;code&gt;systemctl cat nginx.service&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;I haven&amp;rsquo;t dove into &lt;code&gt;journalctl&lt;/code&gt; in this post, but I use filtering fairly regularly. For example, to live-tail logs for both nginx and ssh, try &lt;code&gt;journalctl -f _SYSTEMD_UNIT=nginx.service + _SYSTEMD_UNIT=sshd.service&lt;/code&gt;. The plus is a logical &lt;i&gt;or&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
If you want &lt;i&gt;more&lt;/i&gt; tips like this, I&amp;rsquo;d refer you to &lt;a href="http://sysadvent.blogspot.com/2015/12/day-17-grokking-systemd-for-fun-and.html"&gt;my post over at SysAdvent&lt;/a&gt; that dives more deeply into topics like journald and dbus.
Happying &lt;code class="src src-shell"&gt;systemctl&lt;/code&gt;ing!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>Tyblog</author><pubDate>Sun, 09 Jul 2017 09:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tjll.net/systemd-for-impatient-sysadmins/</guid></item><item><title>2017-07-09</title><link>https://ho.dges.online/pictures/2017-07-09/</link><description/><author>ho.dges.online</author><pubDate>Sun, 09 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-07-09/</guid></item><item><title>Killing a container from the inside</title><link>https://andrestc.com/post/killing-container-inside/</link><description>&lt;p&gt;This past week a &lt;a href="https://tsuru.io"&gt;tsuru&lt;/a&gt; user was having a problem in one of his apps. Some units of his app would simply get stuck, timing out every request and apparently doing nothing. As a workaround he wanted to kill the problematic unit and force it to restart. On tsuru you are able to restart all units of an app but may not choose a particular unit to restart.&lt;/p&gt;
&lt;p&gt;We then “sshed” into the problematic container, by using &lt;code&gt;tsuru app shell -a &amp;lt;app-name&amp;gt;&lt;/code&gt;, and tried sending a &lt;code&gt;SIGKILL&lt;/code&gt; to their application process (pid 1) and surprisingly it did not work.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Sun, 09 Jul 2017 02:34:08 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/killing-container-inside/</guid></item><item><title>Faster cursor movement on macOS</title><link>https://xenodium.com/faster-cursor-movement-on-macos</link><description>&lt;p&gt;Faster cursor movement on macOS by increasing your keyboard's initial key repeat subsequent key repeat.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;defaults write -g KeyRepeat -int 1
defaults write -g InitialKeyRepeat -int 10
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 08 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/faster-cursor-movement-on-macos</guid></item><item><title>YAC - Firebase remote config</title><link>https://prashamhtrivedi.in/yac_firebase_remoteconfig.html</link><description>Firebase is the base behind YAC&amp;rsquo;s many functionalities, remote config is one of them. In this post I have described how remote config solves some of the problems I have.</description><author>Prasham H Trivedi</author><pubDate>Sat, 08 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/yac_firebase_remoteconfig.html</guid></item><item><title>V.I Lenin died and left the stumps behind</title><link>https://rybakov.com/blog/lenin/</link><description>&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/leninpni.jpg" /&gt;




&lt;/figure&gt;
&lt;p&gt;What do we see here?
On the left is a papier-mâché box, with a Palekh style miniature on it. It is dated 1961. The style developed after icon painters from the city of Palekh had to find new jobs following the revolution of 1917.
The painting on the box depicts the tree stumps on which Vladimir Ilich Lenin used to rest and work. In the distance a foreign delegation looks on.&lt;/p&gt;
&lt;p&gt;On the right, Fidel Castro is laying flowers to the tree stumps, on which Lenin used to sit and work.
I repeat, Fidel Alejandro Castro Ruz is laying dying flowers to the dead tree stumps on which the deceased Vladimir Ilich Lenin used to rest and work.&lt;/p&gt;
&lt;p&gt;The thing with the stumps is quite amazing in itself. How else could you stage the absence of a person if not by the stumps that signify the absence of trees that stood there once, tall and proud. The person is long gone and only the absence of the trees is left.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Fri, 07 Jul 2017 23:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/lenin/</guid></item><item><title>Search/insert one-liners with Emacs helm-ag</title><link>https://xenodium.com/search-insert-one-liners-with-emacs-helm-ag</link><description>&lt;p&gt;Emacs &lt;a href="https://github.com/emacs-helm/helm"&gt;helm&lt;/a&gt; is awesome. &lt;a href="https://github.com/syohex/emacs-helm-ag"&gt;helm-ag&lt;/a&gt; is double awesome. Searching for one-liners in your codebase, narrowing down with helm, and easily inserting is triple awesome.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/search-and-insert-one-liners-with-helm-ag/helm-ag-insert.gif" /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(defun ar/helm-ag (arg)
  &amp;quot;Helm-ag search remembering last location.  With ARG, forget the last location.&amp;quot;
  (interactive &amp;quot;P&amp;quot;)
  (defvar ar/helm-ag--default-locaction nil)
  (setq ar/helm-ag--default-locaction
                 (read-directory-name &amp;quot;search in: &amp;quot; (if arg
                                                        default-directory
                                                      ar/helm-ag--default-locaction) nil t))
  (helm-do-ag ar/helm-ag--default-locaction))

(defun ar/helm-ag-insert (arg)
  ;; Helm-ag and insert match.
  (interactive &amp;quot;P&amp;quot;)
  (let* ((actions (helm-make-actions
                   &amp;quot;Insert&amp;quot;
                   (lambda (candidate)
                     ;; Drop file:line:column. For example:
                     ;; arc_hostlink.c:13:2:#include &amp;lt;linux/fs.h&amp;gt;
                     ;; =&amp;gt; #include &amp;lt;linux/fs.h&amp;gt;
                     (insert (replace-regexp-in-string &amp;quot;^[^ ]*:&amp;quot; &amp;quot;&amp;quot; candidate)))))
         (helm-source-do-ag (helm-build-async-source &amp;quot;The Silver Searcher&amp;quot;
                              :init 'helm-ag--do-ag-set-command
                              :candidates-process 'helm-ag--do-ag-candidate-process
                              :persistent-action  'helm-ag--persistent-action
                              :action actions
                              :nohighlight t
                              :requires-pattern 3
                              :candidate-number-limit 9999
                              :keymap helm-do-ag-map
                              :follow (and helm-follow-mode-persistent 1))))
    (call-interactively #'ar/helm-ag)))
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 07 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/search-insert-one-liners-with-emacs-helm-ag</guid></item><item><title>Great books cannot be spoiled</title><link>http://dimitarsimeonov.com/2017/07/07/great-books-cannot-be-spoiled</link><description>&lt;p&gt;The really awesome book don’t go bad if you know what happens. That’s
because they are intricate enough that there is still a lot to be
experienced on a second, third and fourth read.&lt;/p&gt;

&lt;p&gt;Just like poetry, great prose keeps on giving the more you read
it. And great movies keep on giving the more you watch them.&lt;/p&gt;

&lt;p&gt;I recently re-read Hemingway’s “The old man and the sea.” I already
knew what happens. Let me “spoil” it for you. An old fisherman from
Havana goes out into the sea to fish, following twelve weeks of bad
luck. He catches an enormous swordfish, and spends a lot of time until
he can pull the fish out. Ultimately, the fish is too big for the
boat, and sharks eat it before he can reach the shore. Life goes on.&lt;/p&gt;

&lt;p&gt;If you’re interested in the sequence of events, I just saved you hours
of reading of the book. But if you read the book, and read it again
some time later, you start noticing other things.&lt;/p&gt;

&lt;p&gt;For example, Santiago, the old man, refers to things as if they are
to people. Most fish are “him”, and the sea is “her”. This shows
enormous humility towards nature. He goes on to say he loves the
swordfish he caught, and that the fish is his brother, but he needs to
kill the fish. He does the killing without anger or hate. He realizes
that’s the way of nature, even if the way of nature involves the boat,
the fishing line, and the harpoon.&lt;/p&gt;

&lt;p&gt;And also, while he has this great reverence for nature, he realizes
his role as a human. He can control his pain and thus overcome the
fish. He also is reflective of his own thought process and the dangers
of going insane from the strain and lack of sleep. He’s rational.&lt;/p&gt;

&lt;p&gt;But all these observations don’t jump out on the first read. On the
first read, the story takes the central stage. The fight with the fish
and the perseverance, and the remoteness of the sea, are what grabs
our attention. We are rooting for Santiago, and also feel the fear and
adrenalin of the adventure.&lt;/p&gt;

&lt;p&gt;On subsequent reads we are a bit more detached and can see some of the
subtler things. As we uncover more and more details, we peel another
layer of understanding and we start to add personal reflections to our
interpretation. The perseverance of Santiago becomes a metaphor for
our own attempts at that long run or bike ride, the humanization of
animals becomes something we start doing to pets and other animals and
it cause us to be more relaxed in their presence.&lt;/p&gt;

&lt;p&gt;Further re-reads will further shift our focus from the story towards
ourselves. Reading again and again becomes more and more an
experience, and less and less an acquisition of information. That’s
why you can’t spoil and experience with knowing what happens.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 07 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/07/07/great-books-cannot-be-spoiled</guid></item><item><title>Deployment Architecture</title><link>https://www.wints.org/notes/2017.07.07/</link><description>&lt;p&gt;I now have a scraper that works and a static website built with Hugo.&lt;/p&gt;
&lt;p&gt;Putting these together, I need to re-deploy the static website each day with updated inventory, which the scraper provides.&lt;/p&gt;
&lt;p&gt;So my single VPS instance will run a daily cronjob script that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox" /&gt; scrapes the inventory.&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox" /&gt; stores it in the database.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox" /&gt; git pulls the website from Gitlab.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox" /&gt; pulls updated inventory from database.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox" /&gt; inserts updated inventory into website.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox" /&gt; pushes website back to Gitlab, which triggers Netlify to rebuild site.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Item 3 onwards, I need to make a call whether to keep writing modules in the main package or write separate scripts for each.
Maybe a separate module for handling site (re)building&amp;hellip;&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 07 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.07/</guid></item><item><title>Digital Nomad: Inventory Advice</title><link>https://thomashunter.name/posts/2017-07-06-digital-nomad-inventory-advice</link><author>Thomas Hunter II</author><pubDate>Thu, 06 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-07-06-digital-nomad-inventory-advice</guid></item><item><title>Git: Pushing and Deploying to a Private Server</title><link>https://www.wints.org/notes/2017.07.06/</link><description>&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps"&gt;Git Deployment Tutorial&lt;/a&gt;
&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2"&gt;SSH Key Setup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I needed to push to deploy my scraping app to a server. Using git seems to be the way to deploy web apps, so thought to use the same method.&lt;/p&gt;
&lt;h5 id="locations"&gt;Locations &lt;a href="#locations"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;There are four locations to keep in mind. I&amp;rsquo;m deploying to an Ubuntu Server 16.04.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A. &lt;strong&gt;Local Git and Working Repo&lt;/strong&gt;: /Users/dhruvkar/projects/projectname/&lt;/li&gt;
&lt;li&gt;B. &lt;strong&gt;Remote Git Repo&lt;/strong&gt;: /home/gitrepos/projectname.git/&lt;/li&gt;
&lt;li&gt;C. &lt;strong&gt;Remote Working Repo&lt;/strong&gt;: /home/production/projectname/&lt;/li&gt;
&lt;li&gt;D. &lt;strong&gt;Remote Github Repo&lt;/strong&gt;: &lt;a href="https://github.com/dhruvkar/projectname"&gt;https://github.com/dhruvkar/projectname&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Location A is self-explanatory. It contains all the working code and is a git repository on your laptop.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Thu, 06 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.06/</guid></item><item><title>Ubuntu Core: Making a factory image with private snaps</title><link>https://kyrofa.com/posts/ubuntu-core-making-a-factory-image-with-private-snaps/</link><description>This is a follow-up to the ROS prototype to production on Ubuntu Core series to answer a question I received: &amp;ldquo;What if I want to make an image for the factory, but don&amp;rsquo;t want to make my snaps public?&amp;rdquo; This question is of course not robotics-specific, and neither is its answer. In this post we&amp;rsquo;ll cover two ways to do this.
Before we start, you&amp;rsquo;ll need a little bit of an Ubuntu Core imaging background.</description><author>kyrofa's blog</author><pubDate>Thu, 06 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ubuntu-core-making-a-factory-image-with-private-snaps/</guid></item><item><title>Transparente Unternehmen: Warum Customer Experience siegt</title><link>https://philippzentner.com/transparente-unternehmen-warum-customer-experience-siegt.html</link><description>&lt;h3&gt;Wann wurde Transparenz kritisch?&lt;/h3&gt;
&lt;p&gt;Vor gut zehn Jahren mussten sich Unternehmen zunehmend mit einer steigenden Preistransparenz auseinandersetzen. Das Internet als solches war eine Option für den Konsumenten bzw. die Konsumentin, sich nach günstigeren Alternativen umzuschauen. Preisvergleichsseiten kamen zustande und erfreuten sich größter Beliebtheit, denn nun dauerte der Preisvergleich nur noch zwei Minuten, anstatt zwei Stunden. Die Folge daraus war für Unternehmen teilweise fatal. Online-Shops fingen an, eben genau diesen Daten zu nutzen um ihre Preise dynamisch und tagesaktuell anzupassen. Wer ein paar Cents günstiger war, stand eben weiter oben. Der bessere Crawler gewann. Getrickst wurde dann mit Versandkosten, welche mal im Preis mit inbegriffen waren, nun aber rausgerechnet wurden, aber die Preisvergleichsseiten zogen schnell nach. Manche Unternehmen zogen sogar ihre eigenen, auf die Produktkategorie zugeschnittenen Preisvergleichseiten hoch und hatten damit definitiv einen Geschwindigkeits- und Positionierungsvorteil.&lt;/p&gt;</description><author>Philipp Zentner</author><pubDate>Wed, 05 Jul 2017 22:34:31 GMT</pubDate><guid isPermaLink="true">https://philippzentner.com/transparente-unternehmen-warum-customer-experience-siegt.html</guid></item><item><title>Rooting a Oneplus 3T Phone</title><link>https://lukesingham.com/rooting-a-oneplus-3t-phone/</link><description>&lt;p&gt;I recently rooted my Oneplus 3T phone on Android 7.1.1. Finding the right information was not as easy as I thought it might be, so here's my summary. I used my macbook, you will need your USB cord to connect the phone. &lt;strong&gt;Warning&lt;/strong&gt; - you will end up wiping your phone during this process, I'd recommend performing a backup prior. I didn't as I figured most app data are synced to the cloud, the only things I noticed missing was SMSs and things like numbers and Whatsapp history where a sync to the cloud occurred on a weekly basis.&lt;/p&gt;
&lt;h2 id="1.-unlock-the-bootloader"&gt;1. Unlock the &lt;a href="https://www.androidcentral.com/what-is-android-bootloader"&gt;Bootloader&lt;/a&gt; &lt;a class="direct-link" href="https://lukesingham.com/rooting-a-oneplus-3t-phone/#1.-unlock-the-bootloader"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;a. If you haven't already done so, you will need to enable &lt;code&gt;Developer Options&lt;/code&gt; on your phone by tapping 7x on the &lt;code&gt;Build Number&lt;/code&gt; found in your phone under &lt;code&gt;Settings &amp;gt; About Phone &amp;gt; Build Number&lt;/code&gt;. Once enabled, navigate to &lt;code&gt;Settings &amp;gt; Developer Options &amp;gt; USB debugging&lt;/code&gt; and ensure this is toggled to ON.&lt;/p&gt;
&lt;p&gt;b. You will now need to obtain the &lt;a href="https://dl.google.com/android/android-sdk_r24.4.1-macosx.zip"&gt;Android Software Development Kit to run commands on your phone from your computer terminal&lt;/a&gt;. This provides several tools you will use including &lt;a href="https://developer.android.com/studio/command-line/adb.html"&gt;Android Development Bridge (ADB)&lt;/a&gt; and &lt;a href="https://www.androidcentral.com/android-z-what-fastboot"&gt;Fastboot&lt;/a&gt;. Once downloaded, unzip and place the files in a place where you can find them. Then navigate to the folder and launch the Android SDK manager by double clicking on &lt;code&gt;android-sdk-macosx/tools/android&lt;/code&gt;. This will provide a GUI to install the tools needed as per the following screenshot.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://lukesingham.com/content/images/2017/07/Screen-Shot-2017-07-05-at-14-16-57.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now you are ready to run some commands:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Navigate to the tools&lt;/span&gt;&lt;br /&gt;$ &lt;span class="token builtin class-name"&gt;cd&lt;/span&gt; /android-sdk-macosx/platform-tools&lt;br /&gt;&lt;span class="token comment"&gt;# Check that your phone is connected properly&lt;/span&gt;&lt;br /&gt;$ adb devices&lt;br /&gt;List of devices attached&lt;br /&gt;fc031cd8 device&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Reboot phone into bootloader&lt;/span&gt;&lt;br /&gt;$ ./adb &lt;span class="token function"&gt;reboot&lt;/span&gt; bootloader&lt;br /&gt;&lt;span class="token comment"&gt;# Unlock the phone&lt;/span&gt;&lt;br /&gt;$ ./fastboot oem unlock&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last command will wipe your phone. Once complete you will then boot up the phone and need to repeat the process in step 1.a.&lt;/p&gt;
&lt;h2 id="2.-install-twrp-custom-recovery"&gt;2. Install TWRP Custom Recovery &lt;a class="direct-link" href="https://lukesingham.com/rooting-a-oneplus-3t-phone/#2.-install-twrp-custom-recovery"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I chose the open source &lt;a href="https://en.wikipedia.org/wiki/TWRP"&gt;TWRP recovery software&lt;/a&gt;. You can get a copy of TWRP &lt;a href="http://techerrata.com/browse/twrp2/bacon"&gt;here&lt;/a&gt;. Without the installation of TWRP, Step 3 will not be possible (I tried but the OnePlus recovery won't allow you to install SuperSu).&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;&lt;span class="token comment"&gt;# Check that your phone is connected properly&lt;/span&gt;&lt;br /&gt;$ adb devices&lt;br /&gt;List of devices attached&lt;br /&gt;fc031cd8 device&lt;br /&gt;&lt;br /&gt;$ ./fastboot flash recovery /YOUR/&lt;span class="token environment constant"&gt;PATH&lt;/span&gt;/TO/TWRP.img&lt;br /&gt;$ ./fastboot &lt;span class="token function"&gt;reboot&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="3.-root-via-flashing-supersu"&gt;3. Root Via Flashing SuperSU &lt;a class="direct-link" href="https://lukesingham.com/rooting-a-oneplus-3t-phone/#3.-root-via-flashing-supersu"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you haven't already &lt;a href="https://www.android.com/filetransfer/"&gt;download Android File Transfer&lt;/a&gt;. Transfer the &lt;a href="https://download.chainfire.eu/696/SuperSU/UPDATE-SuperSU-v2.46.zip"&gt;SuperSU zip&lt;/a&gt; into the root of your phone. Ensure &lt;code&gt;Settings &amp;gt; Developer Options &amp;gt; Advanced Reboot&lt;/code&gt; is toggled to on. Then press the power off button and select &lt;code&gt;Reboot &amp;gt; Recovery&lt;/code&gt;. From here you will have the new TWRP menu to select &lt;code&gt;Install&lt;/code&gt; and choose the SuperSu zip file. You will need to swipe right to confirm the Flash.&lt;/p&gt;
&lt;h3 id="one-small-hiccup"&gt;One Small Hiccup &lt;a class="direct-link" href="https://lukesingham.com/rooting-a-oneplus-3t-phone/#one-small-hiccup"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I encountered one issue in this process. SuperSu was not installing from the TWRP menu. I stopped the above process in between Step 2 and Step 3 as I had to go to bed for work the next day. On booting my phone for the day, I let my android install apps associated with my google account. Normally a great feature when signing into a new phone or one that has been formatted. However, the phone must be freshly wiped to be able to install SuperSu. So I had to separately wipe the phone again using the following commands found on this &lt;a href="https://stackoverflow.com/a/39357553/3691003"&gt;SO answer&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="language-bash"&gt;&lt;code class="language-bash"&gt;$ ./adb &lt;span class="token function"&gt;reboot&lt;/span&gt; bootloader&lt;br /&gt;&lt;span class="token comment"&gt;# Wait a few seconds...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Check the phone is in bootloader&lt;/span&gt;&lt;br /&gt;$ ./fastboot devices&lt;br /&gt;&lt;span class="token comment"&gt;# Wipe user data&lt;/span&gt;&lt;br /&gt;$ ./fastboot &lt;span class="token parameter variable"&gt;-w&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="useful-resources"&gt;Useful Resources &lt;a class="direct-link" href="https://lukesingham.com/rooting-a-oneplus-3t-phone/#useful-resources"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.androidexplained.com/oneplus-3t-root/"&gt;Android Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forums.oneplus.net/threads/guide-for-mac-how-to-unlock-bootloader-install-custom-recovery-root-macbook-pro.279125/"&gt;OnePlus Forums&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Luke Singham</author><pubDate>Wed, 05 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/rooting-a-oneplus-3t-phone/</guid></item><item><title>The Lizardman Constant by Scott Alexander</title><link>https://ho.dges.online/words/commonplace/the-lizardman-constant-by-scott-alexander/</link><description/><author>ho.dges.online</author><pubDate>Wed, 05 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/the-lizardman-constant-by-scott-alexander/</guid></item><item><title>How Hackers Steal Your Data</title><link>https://xavd.id/blog/post/how-hackers-steal-your-data/</link><description>The ins and outs of password security&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/how-hackers-steal-your-data/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Wed, 05 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/how-hackers-steal-your-data/</guid></item><item><title>awk driven IoT</title><link>https://anisse.astier.eu/awk-driven-iot.html</link><description>&lt;p&gt;With a Raspberry Pi or other modern single-board computers, you can make very simple toys. I started with the hello world of interactive apps: the &lt;a href="https://en.wikipedia.org/wiki/Soundboard_(computer_program)"&gt;soundboard&lt;/a&gt;. But even then, I was too ambitious.&lt;/p&gt;
&lt;h1&gt;The soundpad&lt;/h1&gt;
&lt;p&gt;Since the main target was kids. I wanted a simple, screen-less toy that would teach …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Wed, 05 Jul 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/awk-driven-iot.html</guid></item><item><title>Cross Culture Frustration</title><link>https://venam.net/blog/psychology/2017/07/05/culture-frustration.html</link><description>It's not uncommon to hear, from persons that relocated to a new country, discussions related to the dissatisfactions with the new land they've set upon or the land they've just left behind. Apart from the stifling reply, "they're just not used to it", what else is hiding behind this phenomenon.  Let's dissect this case.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Wed, 05 Jul 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2017/07/05/culture-frustration.html</guid></item><item><title>Introducing ZIP Foundation</title><link>https://thomas.zoechling.me/journal/2017/07/ZIPFoundation.html</link><description>&lt;div&gt;&lt;p&gt;The Cocoa developer community already provides several useful and well-maintained ZIP libraries. But while working on my next app, I realized that I have some requirements that were not met by the existing libraries I found. So I set out to create my own with the following design goals in mind:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;High performance&lt;/li&gt;
&lt;li&gt;Random access to specific entries within an archive&lt;/li&gt;
&lt;li&gt;Deterministic memory consumption&lt;/li&gt;
&lt;li&gt;Stream based API to &lt;em&gt;read from&lt;/em&gt; or &lt;em&gt;write to&lt;/em&gt; archives&lt;/li&gt;
&lt;li&gt;Low-maintainance package dependencies (ideally the ZIP library should not pull in any 3rd party code at all)&lt;/li&gt;
&lt;li&gt;Usable on the server (Linux)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I recently open sourced my results on GitHub. The project is called &lt;a href="https://github.com/weichsel/ZIPFoundation"&gt;ZIP Foundation&lt;/a&gt; and it is a Swift framework to create, read and update ZIP archive files. It uses &lt;a href="https://developer.apple.com/documentation/compression/data_compression"&gt;Apple's libcompression&lt;/a&gt; to handle de- and encoding of compressed archives.  &lt;/p&gt;&lt;p&gt;Unlike most other Cocoa ZIP framework authors, I decided against wrapping an existing C implementation (like the excellent &lt;a href="https://github.com/nmoinvaz/minizip"&gt;minizip&lt;/a&gt;) and implemented the &lt;a href="https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT"&gt;ZIP specification&lt;/a&gt; by myself. By doing that, I learned a lot about the format, which later allowed me to write a minimal and modern implementation of the specification. &lt;br /&gt;Writing everything from scratch also has the nice side effect that ZIP Foundation has no 3rd party dependencies and that it was relatively easy to port it to Linux. &lt;br /&gt;Another design goal was a modern, Swift-style API. The API should provide easy to use high-level methods on one hand and fine grained low-level access to ZIP entries on the other.  &lt;/p&gt;&lt;p&gt;The high level API is implemented as extension to &lt;code&gt;FileManager&lt;/code&gt; and only consists of two methods: &lt;code&gt;zipItem&lt;/code&gt; and &lt;code&gt;unzipItem&lt;/code&gt;. &lt;br /&gt;It allows you to zip and unzip files and directories with a single line of code: &lt;br /&gt;
&lt;code&gt;try fileManager.zipItem(at: sourceURL, to: destinationURL)&lt;/code&gt;  &lt;/p&gt;&lt;p&gt;and &lt;br /&gt;
&lt;code&gt;try fileManager.unzipItem(at: sourceURL, to: destinationURL)&lt;/code&gt;&lt;/p&gt;&lt;p&gt;To access individual entries, you can use the &lt;code&gt;Archive&lt;/code&gt; class. &lt;code&gt;Archive&lt;/code&gt; conforms to &lt;code&gt;Sequence&lt;/code&gt; and therefore supports subscripting. To access an arbitrary entry within an archive you can simply write: &lt;br /&gt;
&lt;code&gt;guard let entry = archive["file.txt"] else {
    return
}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;Archive&lt;/code&gt; also provides a closure-based API to access and modify ZIP files. This allows you to perform ZIP operations on-the-fly, without round trips to the file system. &lt;br /&gt;To learn more about that, please refer to the &lt;a href="https://github.com/weichsel/ZIPFoundation#usage"&gt;README on GitHub&lt;/a&gt; or the method documentation in Xcode.&lt;/p&gt;&lt;h2&gt;Performance&lt;/h2&gt;&lt;p&gt;High performance was very high on my requirements list and so I designed the framework for it right from the beginning. &lt;br /&gt;With macOS 10.11/iOS 9.0, Apple introduced a new compression library: libcompression. It comes with several compression encoders and decoders, including a highly optimized version of the zlib decoding algorithm. Zlib is available on virtually all platforms and its deflate implementation is the most common compression method used for ZIP archives. Besides its wide availability, zlib also provides a good balance between compression ratio and encoding/decoding speed. It is open source and has been constantly improved since its initial release in 1995. Apple somehow managed to speed-up the &lt;a href="https://developer.apple.com/videos/play/wwdc2015-712/?time=368"&gt;decoding part of zlib by 60%&lt;/a&gt; while still maintaining compatibility. Given that impressive decoding speed, using libcompression for ZIP Foundation was an obvious choice. The library is used on all Apple platforms (iOS 9.0+ / macOS 10.11+ / tvOS 9.0+ / watchOS 2.0+). On Linux, ZIP Foundation falls back to zlib.&lt;/p&gt;&lt;p&gt;For the following performance tests, I wrote a small command line utility that performs extract, add and remove operations with various entry sizes. The baseline performance is established by the default zip/unzip command line tools on macOS. Each operation is performed 10 times for each test entry size. The final result is the average of the ten runs in milliseconds. ZIP Foundation was compiled with &lt;code&gt;-Ofast&lt;/code&gt; and &lt;code&gt;-whole-module-optimization&lt;/code&gt;. The benchmark was executed on macOS Sierra 10.12.5. You can download the utility &lt;a href="https://thomas.zoechling.me/journal/2017/07/ZIPFoundation/zipbench.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;img alt="Drawing" src="https://thomas.zoechling.me/journal/2017/07/ZIPFoundation/extract@2x.png" style="width: 405px;" /&gt;&lt;/p&gt;&lt;figcaption&gt;ZIP entry extraction. Time in milliseconds. Lower is better.&lt;/figcaption&gt;&lt;p&gt;During extraction, ZIP Foundation heavily benefits from the fast zlib decoding in libcompression. When taking into account how common zlib decoding is in everyday computing (not only for ZIP files but also for ubiquitous formats like PNG), it soon becomes clear that Apple's engineers really helped us to save a lot of time and battery with that optimization.&lt;/p&gt;&lt;p&gt;&lt;img alt="Drawing" src="https://thomas.zoechling.me/journal/2017/07/ZIPFoundation/add@2x.png" style="width: 405px;" /&gt;&lt;/p&gt;&lt;figcaption&gt;ZIP entry addition. Time in milliseconds. Lower is better.&lt;/figcaption&gt;&lt;p&gt;&lt;img alt="Drawing" src="https://thomas.zoechling.me/journal/2017/07/ZIPFoundation/remove@2x.png" style="width: 405px;" /&gt;&lt;/p&gt;&lt;figcaption&gt;ZIP entry removal. Time in milliseconds. Lower is better.&lt;/figcaption&gt;&lt;p&gt;In &lt;a href="https://developer.apple.com/videos/play/wwdc2015/712"&gt;WWDC Session 712/2015&lt;/a&gt;, the libcompression engineers mention that they only optimized the decoding part of zlib. The graphs for &lt;em&gt;addition&lt;/em&gt; and &lt;em&gt;removal&lt;/em&gt; clearly show that. The small gains were all achieved by tweaking IO and compression buffer sizes.&lt;/p&gt;&lt;h2&gt;Code Quality&lt;/h2&gt;&lt;p&gt;As ZIP is often used as a container format for proprietary file formats, reliability and performance should be a high priority for every ZIP framework. ZIP Foundation is my first non-trivial project that is fully covered by unit and performance tests. &lt;br /&gt;I don't think that achieving 100% coverage will instantly guarantee a certain level of quality. However, I found that while aiming for it, I had to permanently question program flow, API design and type choices. That lead to a lot of refactoring which in the end made the framework more robust and easier to use. Another advantage of 100% coverage is, that it uncovers dead code. If certain code paths are not exercised after refactoring, they are either dead or the refactoring has introduced flawed logic. Both aspects are also noticeable in code bases with less than 100% coverage, but the root causes would not be as easy to spot. (To easily find uncovered code, it helps to have &lt;a href="https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/07-code_coverage.html#//apple_ref/doc/uid/TP40014132-CH15-SW4"&gt;Code Coverage Visualization turned on&lt;/a&gt;.)&lt;/p&gt;&lt;h2&gt;Non-Apple Platform Support&lt;/h2&gt;&lt;p&gt;When Apple open sourced Swift, they also made an initial push to bring the language to non-Apple platforms. As ZIP Foundation does not use any platform specific dependencies, I decided to support Linux right from the beginning. Apple provides a &lt;a href="https://github.com/apple/swift-corelibs-foundation"&gt;Swift implementation of Foundation&lt;/a&gt;, so it was possible to get a buildable framework with very little effort. I used Ole Begemann's excellent tips to get a &lt;a href="https://oleb.net/blog/2017/03/testing-swift-packages-on-linux/"&gt;Linux test environment for Swift projects&lt;/a&gt; using Docker. While getting the project into a compilable state was not too difficult, I soon ran into a wall when trying to execute the project's test suite. The main issues all stemmed from the fact that Apple's open source implementation of Foundation.framework is far from feature complete at the moment (The current Swift development version at the time of writing is 4.0). For instance fundamental methods like &lt;code&gt;FileManager replaceItem&lt;/code&gt; are missing. Another class that currently only  offers a subset of the &lt;em&gt;real&lt;/em&gt; Foundation.framework was (NS)URL, where things like retrieving file metadata via &lt;code&gt;resourceValues(forKeys keys: [URLResourceKey])&lt;/code&gt; is not possible. Luckily Swift has built-in interoperability with C APIs and so I was able to use POSIX counterparts of the aforementioned methods to work around most methods that threw &lt;code&gt;NSUnimplemented&lt;/code&gt;.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;ZIP Foundation was my first 100%-Swift project and I have learned a lot about ZIP, Swift and framework development along the road. &lt;br /&gt;I used Swift since its introduction, but mostly for high level UI code and app development. During the course of this project, it also turned out as good fit for lower level tasks such as large file processing and compression. &lt;/p&gt;
&lt;/div&gt;</description><author>Build and Run</author><pubDate>Tue, 04 Jul 2017 18:28:30 GMT</pubDate><guid isPermaLink="true">https://thomas.zoechling.me/journal/2017/07/ZIPFoundation.html</guid></item><item><title>RFC 1857 stabilizing Rust's drop order has been accepted!</title><link>https://ochagavia.nl/blog/rfc-1857-stabilizing-rusts-drop-order-has-been-accepted/</link><description>If you have been following my previous posts on Rust&amp;rsquo;s drop order, you may want to know how it all ended. In january, I summarized my research in an RFC and submitted it for consideration of the Rust community. Today, after six months of discussion (with around 80 replies), it has been finally accepted as RFC 1857!
Besides reading the RFC itself, you may want to check my previous posts to see the reasoning that led to it:</description><author>Consulting on Adolfo Ochagavía</author><pubDate>Tue, 04 Jul 2017 17:14:51 GMT</pubDate><guid isPermaLink="true">https://ochagavia.nl/blog/rfc-1857-stabilizing-rusts-drop-order-has-been-accepted/</guid></item><item><title>Why not field-level validations?</title><link>https://goshacmd.com/y-no-field-level-validations/</link><author>Gosha Spark</author><pubDate>Tue, 04 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/y-no-field-level-validations/</guid></item><item><title>YAC - Kotlin Wrapup</title><link>https://prashamhtrivedi.in/yac_kotlin_wrapup.html</link><description>Before starting to next series on firebase. I would like to wrapup things on kotlin and announce couple of new things.</description><author>Prasham H Trivedi</author><pubDate>Tue, 04 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/yac_kotlin_wrapup.html</guid></item><item><title>Forwarding spam with Gmail</title><link>https://cmetcalfe.ca/blog/forwarding-spam-with-gmail.html</link><description>&lt;p&gt;With multiple Gmail accounts, it's often easier to forward all emails to a single main account that
you actually check. This can be accomplished by setting up a forwarding account in Gmail's settings.&lt;/p&gt;
&lt;p&gt;However, something that isn't immediately obvious is that messages that are considered spam are
never forwarded. While Gmail's spam detection is extremely good, it's not perfect. There have been
times where emails that I actually wanted have ended up in the spam folder and weren't forwarded to
my main account.&lt;/p&gt;
&lt;p&gt;To fix this, we want to tell Gmail to not flag anything as spam so it will be forwarded along.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This will &lt;strong&gt;not&lt;/strong&gt; cause spam to appear in your inbox. It bypasses the spam filters so the email
is forwarded properly, but the account it's forwarded to will &lt;em&gt;also&lt;/em&gt; flag the email as spam. The
end result is that that the email will end up in the spam folder of your main account (where you
can actually look at it) instead of not being forwarded from the original account at all.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can do this with a filter that matches &lt;code&gt;is:spam&lt;/code&gt; and applies the option "Never send it to Spam".
Unfortunately, Gmail's interface makes this task much harder than it needs to be.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open Gmail and do a search for &lt;code&gt;is:spam&lt;/code&gt;. Notice that Gmail autocorrects it to &lt;code&gt;in:spam&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click the dropdown arrow on the right side of the search box to bring down the advanced options
   and click "Create filter with this search". Hit "OK" on the warning box that pops up. Notice that
   the filter has been autocorrected &lt;em&gt;again&lt;/em&gt; to &lt;code&gt;label:spam&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the URL you should see something like &lt;code&gt;#create-filter/has=label%3Aspam&lt;/code&gt;. Change &lt;code&gt;label&lt;/code&gt; to
   &lt;code&gt;is&lt;/code&gt; in the URL and hit enter. It should modify the text in the box without changing anything
   else.&lt;/li&gt;
&lt;li&gt;Check the "Never send it to Spam" checkbox and hit "Create filter". You'll see the text get
   autocorrected to &lt;code&gt;in:spam&lt;/code&gt; again, but if you check in Settings -&amp;gt; Filters and Blocked Addresses
   you should see the correct &lt;code&gt;is:spam&lt;/code&gt; filter.&lt;/li&gt;
&lt;/ol&gt;</description><author>Carey Metcalfe</author><pubDate>Mon, 03 Jul 2017 22:15:00 GMT</pubDate><guid isPermaLink="true">https://cmetcalfe.ca/blog/forwarding-spam-with-gmail.html</guid></item><item><title>Using cellular automata to generate maps</title><link>https://mbutler.org/using-cellular-automata-to-generate-maps/</link><description>This node app generates random json maps compatible with Tiled and Phaser.js. It uses a cellular automata algorithm to generate the background and then randomly places objects on the map. First set a birth and death rate as well as various spritesheet tiles for your background and objects then run app.js. The json output can [&amp;#8230;]</description><author>mbutler</author><pubDate>Mon, 03 Jul 2017 21:35:54 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/using-cellular-automata-to-generate-maps/</guid></item><item><title>Bank of Canada currency conversion rates in the terminal</title><link>https://cmetcalfe.ca/blog/bank-of-canada-conversion-rates-terminal.html</link><description>&lt;h1&gt;Preface&lt;/h1&gt;
&lt;p&gt;In this entry I'll use two command line tools (&lt;a href="https://curl.haxx.se/"&gt;&lt;code&gt;curl&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://stedolan.github.io/jq/"&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt;) to request currency
conversion rates from the &lt;a href="https://www.bankofcanada.ca"&gt;Bank of Canada&lt;/a&gt;. Now obviously getting the same data through the &lt;a href="https://www.bankofcanada.ca/rates/exchange/daily-exchange-rates-lookup/"&gt;normal
web interface&lt;/a&gt; is possible as well. However, doing it this way returns the data in a
machine-readable form, allowing it to be customized or used as input into other programs.&lt;/p&gt;
&lt;p&gt;The basic flow will be request the data using &lt;code&gt;curl&lt;/code&gt;, then pipe it to &lt;code&gt;jq&lt;/code&gt; for processing.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This article will request the USD/CAD exchange rate from 2017-01-01 to 2017-01-10. It should be
fairly obvious how to switch this for any other currencies or date ranges. See the
&lt;a href="#appendix"&gt;Appendix&lt;/a&gt; for more information and caveats with the dates and the conversion codes.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We'll go from seeing the raw data the server returns to something that we can more easily use. &lt;strong&gt;To
skip to the final result, click &lt;a href="#tldr"&gt;here&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="admonition update"&gt;
&lt;p class="admonition-title"&gt;Update&lt;/p&gt;
&lt;p&gt;The URLs for the data were originally reverse-engineered from the website. They have since been
turned into a supported API. See &lt;a href="https://www.bankofcanada.ca/valet/docs"&gt;the API documentation&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/div&gt;
&lt;h1&gt;Lets go!&lt;/h1&gt;
&lt;p&gt;Hitting the server without any processing will give the following result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://www.bankofcanada.ca/valet/observations/FXUSDCAD/json?start_date=2017-01-01&amp;amp;end_date=2017-01-10&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;terms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://www.bankofcanada.ca/terms/&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;seriesDetail&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;label&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;USD/CAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;US dollar to Canadian dollar daily exchange rate&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nt"&gt;&amp;quot;observations&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-02&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;e&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;-64&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-03&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.3435&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-04&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.3315&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-05&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.3244&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-06&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.3214&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-09&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.3240&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2017-01-10&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;FXUSDCAD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.3213&lt;/span&gt;&lt;span class="p"&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To get the information we want, we need to iterate over the elements in the &lt;code&gt;observations&lt;/code&gt; list and
map the date (&lt;code&gt;d&lt;/code&gt;) to the conversion rate (&lt;code&gt;FXUSDCAD.v&lt;/code&gt;). Since this will create a list of
single-element dictionaries, we'll also need to "add" (merge) them together.&lt;/p&gt;
&lt;p&gt;To do this with &lt;code&gt;jq&lt;/code&gt;, it looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://www.bankofcanada.ca/valet/observations/FXUSDCAD/json?start_date=2017-01-01&amp;amp;end_date=2017-01-10&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
jq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="s1"&gt;    [.observations[] | {(.d) : .FXUSDCAD.v}] | add&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;
&lt;span class="normal"&gt;8&lt;/span&gt;
&lt;span class="normal"&gt;9&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-02&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-03&amp;quot;&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.3435&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-04&amp;quot;&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.3315&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-05&amp;quot;&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.3244&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-06&amp;quot;&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.3214&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-09&amp;quot;&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.324&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-10&amp;quot;&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.3213&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That first &lt;code&gt;null&lt;/code&gt; entry where there was no data is going to cause problems later, so let's just
delete it using the &lt;code&gt;del&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://www.bankofcanada.ca/valet/observations/FXUSDCAD/json?start_date=2017-01-01&amp;amp;end_date=2017-01-10&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
jq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="s1"&gt;    [.observations[] | {(.d) : .FXUSDCAD.v}] | add | del(.[] | nulls)&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;
&lt;span class="normal"&gt;8&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-03&amp;quot;&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.3435&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-04&amp;quot;&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.3315&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-05&amp;quot;&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.3244&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-06&amp;quot;&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.3214&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-09&amp;quot;&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.324&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-10&amp;quot;&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.3213&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now this may be good enough for most purposes, but it would be useful to compute some other
statistics from this data. For example, we want to know the average exchange rate for the date
range. Now that we have the data in an easy to use format, computing an average with &lt;code&gt;jq&lt;/code&gt; is just a
matter of passing the values to an &lt;code&gt;add / length&lt;/code&gt; filter. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://www.bankofcanada.ca/valet/observations/FXUSDCAD/json?start_date=2017-01-01&amp;amp;end_date=2017-01-10&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
jq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="s1"&gt;    [.observations[] | {(.d) : .FXUSDCAD.v}] | add | del(.[] | nulls) | add / length&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;1.327683333333333&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="tldr"&gt;&lt;/a&gt;We can now construct an object that has both the average, as well as all the
data. Putting it all together we get:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;
&lt;span class="normal"&gt;8&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://www.bankofcanada.ca/valet/observations/FXUSDCAD/json?start_date=2017-01-01&amp;amp;end_date=2017-01-10&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
jq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="s1"&gt;    [.observations[] | {(.d) : .FXUSDCAD.v}] | add | del(.[] | nulls) |&lt;/span&gt;
&lt;span class="s1"&gt;    {&lt;/span&gt;
&lt;span class="s1"&gt;        &amp;quot;average&amp;quot;: (add / length),&lt;/span&gt;
&lt;span class="s1"&gt;        &amp;quot;values&amp;quot;: .&lt;/span&gt;
&lt;span class="s1"&gt;    }&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;average&amp;quot;&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.327683333333333&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;values&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="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-03&amp;quot;&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.3435&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-04&amp;quot;&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.3315&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-05&amp;quot;&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.3244&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-06&amp;quot;&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.3214&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-09&amp;quot;&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.324&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;2017-01-10&amp;quot;&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.3213&lt;/span&gt;
&lt;span class="w"&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And that's it! Hopefully you found this useful, if not for it's stated purpose of retrieving
exchange rates, then at least for getting more familiar with &lt;code&gt;jq&lt;/code&gt;. It's pretty much the best tool
out there when it comes to manipulating JSON on the command line.&lt;/p&gt;
&lt;h1&gt;Appendix&lt;a name="appendix"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h3&gt;Date ranges&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The server will only ever return data from &lt;code&gt;2017-01-03&lt;/code&gt; and onwards. If the start range is before
  that, it doesn't return an error, it just doesn't return any data for those dates.&lt;/li&gt;
&lt;li&gt;If the end date isn't specified, the server assumes the current date.&lt;/li&gt;
&lt;li&gt;There doesn't seem to be any limit on the amount of data retrieved&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Currency codes&lt;/h3&gt;
&lt;p&gt;A list of codes can be easily scraped from the lookup page. The command and its result are below for
reference.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://www.bankofcanada.ca/rates/exchange/daily-exchange-rates-lookup/&amp;quot;&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;grep&lt;span class="w"&gt; &lt;/span&gt;-Eo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;quot;FX......&amp;quot;.*&amp;lt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;quot;FXAUDCAD&amp;quot;&amp;gt;Australian dollar&amp;lt;
&amp;quot;FXBRLCAD&amp;quot;&amp;gt;Brazilian real&amp;lt;
&amp;quot;FXCNYCAD&amp;quot;&amp;gt;Chinese renminbi&amp;lt;
&amp;quot;FXEURCAD&amp;quot;&amp;gt;European euro&amp;lt;
&amp;quot;FXHKDCAD&amp;quot;&amp;gt;Hong Kong dollar&amp;lt;
&amp;quot;FXINRCAD&amp;quot;&amp;gt;Indian rupee&amp;lt;
&amp;quot;FXIDRCAD&amp;quot;&amp;gt;Indonesian rupiah&amp;lt;
&amp;quot;FXJPYCAD&amp;quot;&amp;gt;Japanese yen&amp;lt;
&amp;quot;FXMYRCAD&amp;quot;&amp;gt;Malaysian ringgit&amp;lt;
&amp;quot;FXMXNCAD&amp;quot;&amp;gt;Mexican peso&amp;lt;
&amp;quot;FXNZDCAD&amp;quot;&amp;gt;New Zealand dollar&amp;lt;
&amp;quot;FXNOKCAD&amp;quot;&amp;gt;Norwegian krone&amp;lt;
&amp;quot;FXPENCAD&amp;quot;&amp;gt;Peruvian new sol&amp;lt;
&amp;quot;FXRUBCAD&amp;quot;&amp;gt;Russian ruble&amp;lt;
&amp;quot;FXSARCAD&amp;quot;&amp;gt;Saudi riyal&amp;lt;
&amp;quot;FXSGDCAD&amp;quot;&amp;gt;Singapore dollar&amp;lt;
&amp;quot;FXZARCAD&amp;quot;&amp;gt;South African rand&amp;lt;
&amp;quot;FXKRWCAD&amp;quot;&amp;gt;South Korean won&amp;lt;
&amp;quot;FXSEKCAD&amp;quot;&amp;gt;Swedish krona&amp;lt;
&amp;quot;FXCHFCAD&amp;quot;&amp;gt;Swiss franc&amp;lt;
&amp;quot;FXTWDCAD&amp;quot;&amp;gt;Taiwanese dollar&amp;lt;
&amp;quot;FXTHBCAD&amp;quot;&amp;gt;Thai baht&amp;lt;
&amp;quot;FXTRYCAD&amp;quot;&amp;gt;Turkish lira&amp;lt;
&amp;quot;FXGBPCAD&amp;quot;&amp;gt;UK pound sterling&amp;lt;
&amp;quot;FXUSDCAD&amp;quot;&amp;gt;US dollar&amp;lt;
&amp;quot;FXVNDCAD&amp;quot;&amp;gt;Vietnamese dong&amp;lt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;</description><author>Carey Metcalfe</author><pubDate>Mon, 03 Jul 2017 04:43:00 GMT</pubDate><guid isPermaLink="true">https://cmetcalfe.ca/blog/bank-of-canada-conversion-rates-terminal.html</guid></item><item><title>Sending emails with Python: Sparkpost API</title><link>https://www.wints.org/notes/2017.07.03/</link><description>&lt;p&gt;&lt;a href="https://developers.sparkpost.com/api/"&gt;Sparkpost API Docs&lt;/a&gt;
&lt;a href="https://github.com/SparkPost/python-sparkpost"&gt;Sparkpost Python Git repo&lt;/a&gt;
&lt;a href="https://python-sparkpost.readthedocs.io/en/latest/"&gt;Sparkpost Python Client Library Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sparkpost.com"&gt;Sparkpost&lt;/a&gt; has a generous free email quota (100,000 per month as of this writing).
I&amp;rsquo;m using this to send notifications from the inventory system, which doesn&amp;rsquo;t have a notification system.&lt;/p&gt;
&lt;p&gt;First use case: Send weekly notification to show what shipments are still on the water i.e. in transit.
Currently the status of shipments can be obtained by going to each supplier invoice and seeing the shipment status and ETA.
There are also reports for On PO, In Transit and On Hold, but doesn&amp;rsquo;t show the relevant dates.
Deeper scraping is required for that.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 03 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.07.03/</guid></item><item><title>Links - July 2nd, 2017</title><link>https://faingezicht.com/links/2017/07/02/links/</link><description/><author>Avy Faingezicht</author><pubDate>Sun, 02 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/07/02/links/</guid></item><item><title>Flink Streaming SQL Example</title><link>/posts/2017-07-02-flink-streaming-sql-example/</link><description>Apache Flink has hit version 1.3 lately and the SQL support has been extended. You can find what is supported from the docs. In this blog post, I will be giving a small example for using Streming SQL a Tumbling Window.
Consider you are streaming room temperatures that are being read from many sensors. You want to find the average tempetarute in windows of 10 seconds and act upon it. You want to do it in SQL.</description><author>Mustafa Akın</author><pubDate>Sun, 02 Jul 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">/posts/2017-07-02-flink-streaming-sql-example/</guid></item><item><title>Postgres Open Silicon Valley line-up: First take</title><link>/2017/07/01/postgresopen-sv-line-up/</link><description>&lt;p&gt;This year Postgres open and PGConf SV have combined to great a bigger and better conference right in downtown San Francisco. &lt;em&gt;I&amp;rsquo;m obviously biased as I&amp;rsquo;m one of the co-chairs, and I know every conference organizer says picking the talks was hard, but I&amp;rsquo;m especially excited for the line-up this year&lt;/em&gt;. The hard part for me is going to be which talks do I miss out on because I&amp;rsquo;m sitting in the other session that&amp;rsquo;s ongoing. You can see the full list of &lt;a href="https://postgresql.us/events/sessions/pgopen2017/"&gt;talk and tutorial sessions&lt;/a&gt;, but I thought it&amp;rsquo;d be fun to do a rundown of some of my favorites.&lt;/p&gt;
&lt;h3 id="how-postgres-could-index-itselfhttpspostgresqluseventssessionspgopen2017session399-how-postgres-could-index-itself"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/399-how-postgres-could-index-itself/"&gt;How Postgres could index itself&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/399-how-postgres-could-index-itself/"&gt;Postgres indexing itself&lt;/a&gt; has long been on my wishlist. &lt;a href="https://www.twitter.com/akane"&gt;Andrew Kane&lt;/a&gt; from Instacart, and creator of &lt;a href="https://github.com/ankane/pghero/"&gt;PgHero&lt;/a&gt; has bottled up many learnings into a new tool: &lt;a href="https://medium.com/@ankane/introducing-dexter-the-automatic-indexer-for-postgres-5f8fa8b28f27"&gt;Dexter&lt;/a&gt;. I suspect we&amp;rsquo;ll get a look at all that went into this, how it works, and how you can leverage it to have a more automatically tuned database.&lt;/p&gt;
&lt;h3 id="scaling-a-saas-application-beyond-a-single-postgres-with-citushttpspostgresqluseventssessionspgopen2017session376-scaling-a-saas-application-beyond-a-single-postgres-with-citus"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/376-scaling-a-saas-application-beyond-a-single-postgres-with-citus/"&gt;Scaling a SaaS Application Beyond a Single Postgres with Citus&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Migration talks are all to common, from Postgres to MySQL from MySQL to Postgres, or from &lt;a href="https://containership.engineering/dynamodb-to-postgres-why-and-how-aa891681af4d"&gt;Dynamo to Postgres&lt;/a&gt;. But this one is a little different flavor from Postgres to sharded Postgres with &lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt;. Sharding into a distributed system of course brings new things to consider and think about, and &lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/376-scaling-a-saas-application-beyond-a-single-postgres-with-citus/"&gt;here you&amp;rsquo;ll learn about them&lt;/a&gt; from first hand experience so hopefully you can avoid mistakes yourself.&lt;/p&gt;
&lt;h3 id="concurrency-deep-divehttpspostgresqluseventssessionspgopen2017session374-concurrency-deep-dive"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/374-concurrency-deep-dive/"&gt;Concurrency Deep Dive&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/374-concurrency-deep-dive/"&gt;This one&lt;/a&gt; looks to be a great under the hood look as well as likely very practical. It&amp;rsquo;ll cover MVCC which is really at so much of the core of how Postgres works, but then bring it up to what it means for things like locks. Best of all, this one like so many others comes with lots of real world experience from Segment.&lt;/p&gt;
&lt;h3 id="postgres-window-magichttpspostgresqluseventssessionspgopen2017session364-postgres-window-magic"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/364-postgres-window-magic/"&gt;Postgres window magic&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;h3 id="running-postgresql--instagramhttpspostgresqluseventssessionspgopen2017session371-running-postgresql-instagram"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/371-running-postgresql-instagram/"&gt;Running PostgreSQL @ Instagram&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Instagram is well known as one of the largest apps in the world. They optimized and changed their setup multiple times and probably scaled in about every way possible. &lt;a href="https://postgresql.us/events/sessions/pgopen2017/session/371-running-postgresql-instagram/"&gt;Here we get to learn&lt;/a&gt; about all the various things you need in running at a truly astonishing scale.&lt;/p&gt;
&lt;h3 id="many-many-morehttpspostgresqluseventssessionspgopen2017"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/sessions/pgopen2017/"&gt;Many many more&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Of course there&amp;rsquo;s many more. Talks range from looks at new features, to how certain companies are using Postgres. We&amp;rsquo;ve got companies like Instacart and Instagram as mentioned giving talks, to Postgres core committers. Whether you want to learn about the inner workings of Postgres (which often hurts my brain) to how you can simply speed up your app you should find something you like, as long as you like Postgres that is. Take a look at the &lt;a href="https://postgresql.us/events/sessions/pgopen2017/"&gt;full list of sessions&lt;/a&gt; and we hope to see you there.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sat, 01 Jul 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/07/01/postgresopen-sv-line-up/</guid></item><item><title>Building A Better LinkedIn</title><link>https://blog.eutopian.io/building-a-better-linkedin/</link><description>1300 words, 4 and a half minutes. This will probably be the first and last time I write about social networking.
I&amp;rsquo;m an antisocial social networker. I had an expectation that part of the job of a networking platform (professional or social) would be to filter content or updates, both in terms of who was posting them and the individual significance or quality of the posts. Boy was I wrong. One person re-posts every single article they see, another &amp;ldquo;motivational&amp;rdquo; poster repeats blithe optimism without context at the end of every day (tellingly never the beginning).</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Sat, 01 Jul 2017 21:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/building-a-better-linkedin/</guid></item><item><title>Sandwich</title><link>https://rybakov.com/blog/sandwich/</link><description>&lt;audio controls="controls" preload="none" src="../audio/sandwich.mp3"&gt;  
&lt;p&gt;Christoph, teaching guinean kids the pronounciation of shandwish.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sat, 01 Jul 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/sandwich/</guid></item><item><title>Winning Systems &amp;amp; Security Practitioners 6. Final Remarks</title><link>https://blog.eutopian.io/winning-systems-security-practitioners-6.-final-remarks/</link><description>550 words, 2 minutes.
Final Remarks &amp;ldquo;All men can see the tactics whereby I conquer, but what none can see is the strategy out of which victory is evolved&amp;rdquo; - Sun Tzu.
This is the 6th and final post in a short series on winning systems for security practitioners. The first postfeels like a while ago already, about 6000 words or 25 minutes. Those minutes haven&amp;rsquo;t been wasted.
The Inevitable Car Analogy If you&amp;rsquo;ve come this far then you&amp;rsquo;ve already completed one whole lap around the circuit of winning systems.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 18:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/winning-systems-security-practitioners-6.-final-remarks/</guid></item><item><title>Winning Systems &amp;amp; Security Practitioners 5. Resilience</title><link>https://blog.eutopian.io/winning-systems-security-practitioners-5.-resilience/</link><description>1450 words, 5 1/2 minutes.
Resilience &amp;ldquo;In defeat: Defiance&amp;rdquo; - Winston S. Churchill.
This is part 5 of 6 in a short series of posts on winning systems for Information Security practitioners. It aims to plug the gap between policy and products and put you, the practitioner, back in the driving seat. After all if you don&amp;rsquo;t know what system you&amp;rsquo;re implementing, how can you decide what products or features are important to you?</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 17:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/winning-systems-security-practitioners-5.-resilience/</guid></item><item><title>Winning Systems &amp;amp; Security Practitioners 4. Robustness</title><link>https://blog.eutopian.io/winning-systems-security-practitioners-4.-robustness/</link><description>1200 words, 5 minutes.
Robustness &amp;ldquo;The first virtue in a soldier is endurance of fatigue.&amp;quot; - Napoleon Bonaparte.
This is part 4 of 6 in a short series of posts on winning systems for Information Security practitioners. It aims to plug the gap between policy and products and put you, the practitioner, back in the driving seat. After all if you don&amp;rsquo;t know what system you&amp;rsquo;re implementing, how can you decide what products or features are important to you?</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 16:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/winning-systems-security-practitioners-4.-robustness/</guid></item><item><title>Winning Systems &amp;amp; Security Practitioners 3. Responsiveness</title><link>https://blog.eutopian.io/winning-systems-security-practitioners-3.-responsiveness/</link><description>1100 words, 4 1/2 minutes.
Responsiveness &amp;ldquo;No battle plan ever survives contact with the enemy&amp;rdquo; - Helmuth von Moltke.
This is part 3 of 6 in a short series of posts on winning systems for Information Security practitioners. It aims to plug the gap between policy and products and put you, the practitioner, back in the driving seat. After all if you don&amp;rsquo;t know what system you&amp;rsquo;re implementing, how can you possibly decide what products or features are important to you?</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 15:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/winning-systems-security-practitioners-3.-responsiveness/</guid></item><item><title>Winning Systems &amp;amp; Security Practitioners 2. Preparation</title><link>https://blog.eutopian.io/winning-systems-security-practitioners-2.-preparation/</link><description>1100 words, 4 1/2 minutes.
Preparation &amp;ldquo;One of the best ways to keep peace is to be prepared for war&amp;rdquo; - Plato &amp;amp; others.
Today attacks come thick and fast. The chances are that all public IPv4 address space is regularly scanned. Time-to-compromise of an unpatched, non-firewalled, Microsoft Windows host is about 5 minutes. Systems are attacked not because they are valuable, but because they are vulnerable. Even an old cable-modem is a useful addition to a botnet.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 14:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/winning-systems-security-practitioners-2.-preparation/</guid></item><item><title>Winning Systems &amp;amp; Security Practitioners 1. Introduction</title><link>https://blog.eutopian.io/winning-systems-security-practitioners-1.-introduction/</link><description>1100 words, 4 1/2 minutes.
Introduction &amp;ldquo;Never tell people how to do things. Tell them what to do and they will surprise you with their ingenuity.&amp;quot; - George S. Patton
If you&amp;rsquo;ve read my previous postyou&amp;rsquo;ll know that to get beneficial, long lasting, low-maintenance results in Information Security, you need winning systems. Not skills. If you like grinding monotony punctuated by periods of extreme stress and being able to tell people how busy you constantly are, you can safely return to your to-do list.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 13:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/winning-systems-security-practitioners-1.-introduction/</guid></item><item><title>Forget Solving The Cyber Security Skills Shortage</title><link>https://blog.eutopian.io/forget-solving-the-cyber-security-skills-shortage/</link><description>1100 words, 4 minutes. This post is one of a short series on structural and systemic things the Information Security industry does wrong, and what we might do about them.
Disclaimer: I advocate lifelong learning, that includes professional training, product training, workshops, online or in-person courses, and academic study. The professional trainers I know who author and deliver their own material are among the most mentally agile people I&amp;rsquo;ve ever met.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Fri, 30 Jun 2017 12:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/forget-solving-the-cyber-security-skills-shortage/</guid></item><item><title>Why aren't you using Prettier?</title><link>https://medium.com/hexacta-engineering/why-arent-you-using-prettier-4fe0a77713e8</link><description>How Prettier made me a 10% happier programmer</description><author>Rodrigo Pombo</author><pubDate>Fri, 30 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/why-arent-you-using-prettier-4fe0a77713e8</guid></item><item><title>Why I gave up on giving up Twitter</title><link>https://faingezicht.com/articles/2017/06/29/twitter/</link><description>As some of you might have noticed, &lt;a href="https://www.twitter.com/avyfain"&gt;my Twitter account&lt;/a&gt; has been mostly dormant for the last month or two. This was an experiment; an attempt to regain some of my dead time and be as productive as I used to be. I had done something similar once before - in 2013, I deleted the Facebook app from my phone and regained hours of my life. It's been four years and I have not looked back. I figured Twitter could not be too different.

For me, Twitter is a relatively new hobby. I opened my account back in 2008, but I did not use it much until 2016. I started tweeting somewhat regularly, and I developed a bad habit of scrolling as if there was actually something worth my time awaiting at the bottom of the feed.

Slowly, I realized that I was reading way less - my other bad habits are Hacker News and Pocket - and that the signal to noise ratio of the content I was consuming had decreased. Reading one-off 140 character quips is fun, but even in my highly curated list, the lack of context, and the sheer volume made my time on Twitter wasteful. By repurposing the empty spaces in my day where I was using Twitter - waiting for BART, or standing in line at the grocery store - I could avoid the endless search for dopamine that is The Feed and focus on more important things. Sometimes it is tough to understand that a minute here and a minute there add up to hours. Here's Ben Thompson, in a slightly different context:

&gt; It is only when we’re doing something specific that we aren’t using our phones, and the empty spaces of our lives are far greater than anyone imagined.
&gt;
&gt;-Ben Thompson, &lt;a href="https://stratechery.com/2015/the-facebook-epoch/"&gt;The Facebook Epoch&lt;/a&gt;

But somehow, the empty spaces in my day did not become more valuable sans-Twitter. What made this so different from Facebook? Why couldn't I give it up?

The reason is that Twitter has an actual utility beyond the dopamine. Twitter is a networking tool, a self-promotion medium, and a direct channel to reach people who otherwise would have been inaccessible. I wanted those features. I wanted them badly enough that I put up with the noise and waste that came with the rest of the app. So I am back. (Just trying to scroll less.)

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: by me, previously posted on &lt;a href="/photos/2017/03/13/miscellanea/"&gt;Miscellanea&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Thu, 29 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/06/29/twitter/</guid></item><item><title>Fantastic DSLs and where to find them</title><link>https://serce.me/posts/2017-06-29-fantastic-dsls</link><description>The article discusses how Kotlin can create internal languages and how developers can use this feature to write powerful domain-specific languages for manipulating untyped data structures in a typed manner.</description><author>SerCe's blog</author><pubDate>Thu, 29 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serce.me/posts/2017-06-29-fantastic-dsls</guid></item><item><title>How to Learn a Programming Language in Record Time</title><link>/how-to-learn-programming/</link><description>&lt;p&gt;&lt;img alt="image" src="../../assets/images/1_8CZLKCJ926_bhBSmSJj2ww.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This article is aimed primarily at beginners who perhaps know a single language but are looking to start learning another.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When picking up a new programming language your first port of call might be the &lt;a href="https://developer.mozilla.org/bm/docs/Web/JavaScript"&gt;doc&lt;/a&gt;&lt;a href="http://php.net/docs.php"&gt;ument&lt;/a&gt;&lt;a href="http://guides.rubyonrails.org/"&gt;ation&lt;/a&gt;, maybe it’s reading through some code on a project you admire or perhaps you learn most effectively &lt;a href="https://github.com/karan/Projects"&gt;by building&lt;/a&gt;. Whatever the case, we can apply the &lt;a href="https://en.wikipedia.org/wiki/Pareto_principle"&gt;Pareto principle&lt;/a&gt; to &lt;strong&gt;learn 80% of the language from 20% of it’s features&lt;/strong&gt;. If you’re coming from a background where you know &lt;a href="https://en.wikipedia.org/wiki/Creational_pattern"&gt;design patterns&lt;/a&gt; and common programming features (&lt;a href="https://en.wikipedia.org/wiki/Control_flow"&gt;control flow&lt;/a&gt;, loops &lt;em&gt;et cetera&lt;/em&gt;) then this is more than possible.&lt;/p&gt;
&lt;p&gt;When I initially thought of this idea I didn’t think that it would be possible to boil down a language to such a degree. But then again, when was the last time you used &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32"&gt;clz32&lt;/a&gt; or &lt;a href="http://php.net/manual/en/function.bzflush.php"&gt;bzflush&lt;/a&gt;? Programming languages have grown over time to implement features that, in day to day development, you mostly won’t need. Learning a new programming language can therefore seems a daunting prospect — but it need not be.&lt;/p&gt;
&lt;p&gt;I applied this exact pattern of learning when trying to learn Java and it worked relatively well. There was things I didn’t know from this, such as exact patterns of inheritance but at a very basic level, I could hold my own — and that’s the purpose. As you dive deeper into your new programming language of choice, you will get to know the nuances, why and how it solves specific problems and what’s best practise. This will, at the very least, give you a good grounding in a language in an efficient manner.&lt;/p&gt;
&lt;p&gt;Here’s my list of things to prioritise so you can pick up a new language in record time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Variable creation&lt;/strong&gt; — if it’s a strongly or statically typed language, then this extends to how to declare variables of different types (integer, string, object, array). If the language has the feature then we can learn how to create a constant too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Loop ’n’ number of times&lt;/strong&gt; — In Javascript this would be achieved by — &lt;code&gt;for(var i = 0; i &amp;lt; n; i++) {}&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;**Loop over a key:value store **— &lt;em&gt;Key:value&lt;/em&gt; stores are called Objects in Javascript in other languages they are called Hashes (Ruby) or Dictionaries (Python). Nonetheless, they are all the same, and usually there is a particular method to iterating over them because they are referenced by “keys” and not index numbers (as with arrays).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Referencing items in array&lt;/strong&gt; — In javascript you can reference &lt;code&gt;arr[1]&lt;/code&gt; for the second item of an array. In addition to basic referencing, there may be special methods like &lt;code&gt;end()&lt;/code&gt; to get the final element of an array.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Functions&lt;/strong&gt; — How to create them, with or without arguments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add to an array&lt;/strong&gt; — How can we add an element to an array?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remove from an array&lt;/strong&gt; — Likewise, how can we remove a particular item (of index ’n’) from an array?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Class creation and constructors&lt;/strong&gt; — This is where I find languages differ wildly in particulars of the syntax. PHP, for example, has a special __construct function that you must use to construct the class.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;StdOut method&lt;/strong&gt; — In javascript this is &lt;code&gt;console.log&lt;/code&gt; in PHP it’s &lt;code&gt;print&lt;/code&gt;. This is probably my most used method when debugging.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Comparison operators&lt;/strong&gt; — How do you check if a variable is false or true? How do you compare a larger number against a smaller number?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Length of a string&lt;/strong&gt; — A must have for any language. I find myself using this all the time but a common use case is checking whether we should truncate a string before displaying it to a user.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Length of an array&lt;/strong&gt; — Crucial when working with loops as 99% of the time, you will be iterating over an array for however long the array is.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Public and Private methods&lt;/strong&gt; — All languages (especially those with classes) should have this, and is essential when you want to disallow access to functions outside the class.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Try…catch blocks&lt;/strong&gt; — I only ever use these when integrating Stripe payments but they can be handy other times, perhaps when you are testing for a bug and want to capture it for your bug tracking software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Returning from functions&lt;/strong&gt; — Not all languages use &lt;code&gt;return&lt;/code&gt;! (&lt;a href="https://rustbyexample.com/fn.html"&gt;See Rust&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that’s it! This will by no means teach you a language &lt;em&gt;per se&lt;/em&gt; but it will provide a good base level to become familiar with the syntax.&lt;/p&gt;
&lt;p&gt;This learning pattern relies on knowing concepts and design patterns; It goes to show how your learning can be transferred from one language to another!&lt;/p&gt;
&lt;p&gt;Remember the core concepts and features of a language are what matters.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Additional Reading/Resources&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tim.blog/2009/01/20/learning-language/"&gt;https://tim.blog/2009/01/20/learning-language/&lt;/a&gt; — The original article this is inspired by.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://learnxinyminutes.com/"&gt;https://learnxinyminutes.com/&lt;/a&gt;&lt;/p&gt;</description><author/><pubDate>Thu, 29 Jun 2017 01:12:03 GMT</pubDate><guid isPermaLink="true">/how-to-learn-programming/</guid></item><item><title>Before and After</title><link>https://rjp.is/blogging/posts/before-and-after-2/</link><description>In which we tighten up a weave.</description><author>infrequent oscillations</author><pubDate>Wed, 28 Jun 2017 18:33:57 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/before-and-after-2/</guid></item><item><title>Vimrc</title><link>https://www.anardil.net/2017/vimrc.html</link><description>&lt;p&gt;I've read through &lt;em&gt;a lot&lt;/em&gt; of vimrc's, borrowing a line here or there over the
past 5 years! The best nuggets and my own findings are all distilled here for
your perusal. What's the best way to use this? Skim through, find something
that sounds interesting and try it out …&lt;/p&gt;</description><author>Anardil</author><pubDate>Wed, 28 Jun 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2017/vimrc.html</guid></item><item><title>Pride '17</title><link>https://faingezicht.com/photos/2017/06/28/pride2017/</link><description>This year, my Pride weekend was very similar to &lt;a href="/photos/2016/06/27/pride/"&gt;last year's&lt;/a&gt;. Saturday at Dolores, Sunday at the Civic Center Plaza. However, it was colder, and people seemed to be in a different mood. It was much tamer, and there were fewer naked weirdos, but there were other weirdos, like me, asking strangers for their portraits.

Sometimes, I am sad that these people will never see the photos I took of them.</description><author>Avy Faingezicht</author><pubDate>Wed, 28 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/06/28/pride2017/</guid></item><item><title>Audio APIs, Part 2: Pulseaudio / Linux</title><link>https://bastibe.de/2017-06-27-audio-apis-pulseaudio.html</link><description>&lt;p&gt;This is part two of a three-part series on the native audio APIs for Windows, Linux, and macOS. This second part is about PulseAudio on Linux.&lt;/p&gt;
&lt;p&gt;It has long been a major frustration for my work that Python does not have a great package for playing and recording audio. My first step to improve this situation was a small contribution to &lt;a href="https://people.csail.mit.edu/hubert/pyaudio/"&gt;PyAudio&lt;/a&gt;, a CPython extension that exposes the C library &lt;a href="http://www.portaudio.com/"&gt;PortAudio&lt;/a&gt; to Python. However, I soon realized that PyAudio mirrors PortAudio a bit too closely for comfort. Thus, I set out to write &lt;a href="https://github.com/bastibe/PySoundCard"&gt;PySoundCard&lt;/a&gt;, which is a higher-level wrapper for PortAudio that tries to be more pythonic and uses NumPy arrays instead of untyped &lt;code&gt;bytes&lt;/code&gt; buffers for audio data. However, I then realized that PortAudio itself had some inherent problems that a wrapper would not be able to solve, and a truly great solution would need to do it the hard way:&lt;/p&gt;
&lt;p&gt;Instead of relying on PortAudio, I would have to use the native audio APIs of the three major platforms directly, and implement a simple, cross-platform, high-level, NumPy-aware Python API myself. This effort resulted in &lt;a href="https://github.com/bastibe/Python-Audio"&gt;PythonAudio&lt;/a&gt;, a new pure-Python package that uses &lt;a href="http://cffi.readthedocs.io/en/latest/"&gt;CFFI&lt;/a&gt; to talk to &lt;a href="https://www.freedesktop.org/wiki/Software/PulseAudio/"&gt;PulseAudio&lt;/a&gt; on Linux, &lt;a href="https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html"&gt;Core Audio&lt;/a&gt; on macOS, and &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455(v=vs.85"&gt;WASAPI&lt;/a&gt;.aspx)&lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt; on Windows.&lt;/p&gt;
&lt;p&gt;This series of blog posts summarizes my experiences with these three APIs and outlines the basic structure of how to use them. For reference, the singular use case in PythonAudio is block-wise playing/recording of &lt;code&gt;float&lt;/code&gt; data at arbitrary sampling rates and block sizes. All available sound cards should be listable and selectable, with correct detection of the system default sound cards (a feature that is very unreliable in PortAudio).&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;PulseAudio&lt;/h1&gt;
&lt;p&gt;PulseAudio is not the only audio API on Linux. There is the grandfather &lt;a href="https://en.wikipedia.org/wiki/Open_Sound_System"&gt;OSS&lt;/a&gt;, the more modern &lt;a href="https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture"&gt;ALSA&lt;/a&gt;, the more pro-focused &lt;a href="https://en.wikipedia.org/wiki/JACK_Audio_Connection_Kit"&gt;JACK&lt;/a&gt;, and the user-focused &lt;a href="https://en.wikipedia.org/wiki/PulseAudio"&gt;PulseAudio&lt;/a&gt;. Under the hood, PulseAudio uses ALSA for its actual audio input/output, but presents the user and applications with a much nicer API and UI.&lt;/p&gt;
&lt;p&gt;The very nice thing about PulseAudio is that it is a native C API. It provides several levels of abstraction, the highest of which takes only a handful of lines of C to get audio playing. For the purposes of PythonAudio however, I had to look at the more in-depth &lt;a href="https://freedesktop.org/software/pulseaudio/doxygen/async.html"&gt;asynchronous API&lt;/a&gt;. Still, the API itself is relatively simple, and compactly defined in one simple header file.&lt;/p&gt;
&lt;p&gt;It all starts with a &lt;code&gt;mainloop&lt;/code&gt; and an associated &lt;code&gt;context&lt;/code&gt;. While the &lt;code&gt;mainloop&lt;/code&gt; is running, you can query the &lt;code&gt;context&lt;/code&gt; for sources and sinks (aka microphones and speakers). The &lt;code&gt;context&lt;/code&gt; can also create a &lt;code&gt;stream&lt;/code&gt; that can be read or written (aka recorded or played). From a high level, this is all there is to it.&lt;/p&gt;
&lt;p&gt;Most PulseAudio functions are asynchronous: Function calls return immediately, and call user-provided callback functions when they are ready to return results. While this may be a good structure for high-performance multithreaded C-code, it is somewhat cumbersome in Python. For PythonAudio, I wrapped this structure in regular Python functions that wait for the callback and return its data as normal return values.&lt;/p&gt;
&lt;p&gt;Doing this shows just how old Python really is. Python is old-school in that it still thinks that concurrency is better solved with multiple, communicating processes, than with shared-memory threads. With such a mind set, there is a certain impedance mismatch to overcome when using PulseAudio. Every function call has to lock the main loop, and block while waiting for the callback to be called. After that, clean up by decrementing a reference count. This procedure is cumbersome, but not difficult.&lt;/p&gt;
&lt;p&gt;What is difficult however, is the documentation. The API documentation is fine, as far as it goes. It could go into more detail with regards to edge cases and error conditions; But it truly lacks high-level overviews and examples. It took an unnecessarily long time to figure out the code path for audio playback and recording, simply because there is no document anywhere that details the sequence of events needed to get there. In the end, I followed some marginally-related example on the internet to get to that point, because the &lt;em&gt;two&lt;/em&gt; examples provided by PulseAudio don't even use the asynchronous API.&lt;/p&gt;
&lt;p&gt;Perhaps I am missing something, but it strikes me as strange that an API meant for audio recording and playback would not include an example that plays back and records audio.&lt;/p&gt;
&lt;p&gt;On an application level, it can be problematic that PulseAudio seems to only value block sizes and latency requirements approximately. In particular, if computing resources become scarce, PulseAudio would rather increase latency/block sizes in the background than risk skipping. This might be convenient for a desktop application, but it is not ideal for signal processing, where latency can be crucial. It seems that I can work around these issues to an extent, but this is an inconvenience nontheless.&lt;/p&gt;
&lt;p&gt;In general, I found PulseAudio reasonably easy to use, though. The documentation could use some work, and I don't particularly &lt;em&gt;like&lt;/em&gt; the asynchronous programming style, but the API is simple and functional. Out of the three APIs of WASAPI/Windows, Core Audio/macOS, and PulseAudio/Linux, this one was probably the easiest to get working.&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;WASAPI is part of the Windows &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd370784(v=vs.85"&gt;Core Audio&lt;/a&gt;.aspx) APIs. To avoid confusion with the macOS API of the same name, I will always to refer to it as WASAPI.&lt;a class="footnote" href="#fnref-1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>bastibe.de</author><pubDate>Tue, 27 Jun 2017 17:12:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-06-27-audio-apis-pulseaudio.html</guid></item><item><title>Design for searchcode server</title><link>https://boyter.org/2017/06/design-searchcode-server/</link><description>&lt;p&gt;A very brief update about the progress of searchcode server. Currently I am in the middle of reworking how the index is built and maintained. The idea being I want to add zero downtime index rebuilds which requires a blue/green index strategy. It is still very much in flux but the current design is to merge the indexer and searcher which should allow this to happen. I have been playing around with using an iPad as a production device these days and produced the following document.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 27 Jun 2017 11:18:05 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/06/design-searchcode-server/</guid></item><item><title>HTTP API Design Part 4: API Standards</title><link>https://thomashunter.name/posts/2017-06-27-http-api-design-part-4-api-standards</link><author>Thomas Hunter II</author><pubDate>Tue, 27 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-06-27-http-api-design-part-4-api-standards</guid></item><item><title>How not to win</title><link>http://dimitarsimeonov.com/2017/06/27/how-not-to-win</link><description>&lt;p&gt;By trying to winning the things that don’t matter.&lt;/p&gt;

&lt;p&gt;You’re playing a poker game, but you’re not really good, and you can
really get tricked by the sharks. They’ll give you a few bites, and
whet your appetite. You come rushing and eager into their trap and
lose the skin off your back.&lt;/p&gt;

&lt;p&gt;You’re in a relationship, and inevitably end up arguing about
how you treat each other. You stand your ground and don’t
compromise. You hurt your partner and damage the trust, respect and
affection between you. It’s over.&lt;/p&gt;

&lt;p&gt;You see systemic problems with society and government. You become a
dissident and give hour-long speeches and interviews in which you
dissect the corruption. You can really explain the mechanism. But
you’re not a great communicator. Many people praise you and your
stance, yet your words don’t translate to action, and the status quo
persists.&lt;/p&gt;

&lt;p&gt;You’re smart and want to advance in your career.  You find a good job
and start climbing the ladder. You keep on climbing. And then some
more. You reach the glass ceiling. You’re stuck and it’s too late to
start on a different path. Even though you kept improving at a rate
that seemed fast to you, your peers have leap-frogged you by working
for themselves all these years.&lt;/p&gt;

&lt;p&gt;You’re competitive, and focus, and dedicated, and hard-working, and
smart, and persistent and really, really won. You achieved. You’re
revered. Your drive to win got you here. It was so strong that you
always looked for the next challenge to defeat. You never took a break
to appreciate all your achievements. You die, wondering what did you
miss.&lt;/p&gt;</description><author>D13V</author><pubDate>Tue, 27 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/06/27/how-not-to-win</guid></item><item><title>On Learning Elixir</title><link>https://denvaar.dev/posts/on_learning_elixir.html</link><description>Exploring a different way of approaching and solving problems with the cool functional language of Elixir.</description><author>denvaar's website</author><pubDate>Mon, 26 Jun 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/on_learning_elixir.html</guid></item><item><title>HTTP API Design Part 3: Bodies</title><link>https://thomashunter.name/posts/2017-06-26-http-api-design-part-3-bodies</link><author>Thomas Hunter II</author><pubDate>Mon, 26 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-06-26-http-api-design-part-3-bodies</guid></item><item><title>waifu2x super resolution image resizer</title><link>https://muffinman.io/blog/super-resolution-image-resizer/</link><description>&lt;article class="article"&gt;&lt;p&gt;I use the same wallpaper for a long time now.
But with high resolution displays, wallpaper started to look blurry and noisy, so I stopped using it.&lt;/p&gt;
&lt;p&gt;But recently, my girlfriend reminded me of &lt;a href="http://waifu2x.udp.jp/"&gt;this great website&lt;/a&gt; which super-scales images using magic. Ok, not magic, but it uses &amp;quot;Deep Convolutional Neural Networks&amp;quot;, which is pretty much the same thing. Results are amazing, try it yourself.&lt;/p&gt;
&lt;p&gt;The best thing, website is free to use and project is opensource. Code is available on &lt;a href="https://github.com/nagadomi/waifu2x"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It supports max scaling of 2x, so if you need more you&amp;#x27;ll need to process image multiple times. Or you can dig in the code and add option for arbitrary scaling.&lt;/p&gt;
&lt;small&gt;&lt;sup&gt;1&lt;/sup&gt; This is the resized image using waifu2x.&lt;/small&gt;
&lt;h3 id="example"&gt;Example &lt;a class="anchor-link" href="#example"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Original, 250x250px jpeg &lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Original 250x250px image" height="250" src="./rickmorty-250x250.jpg" width="250" /&gt;&lt;/figure&gt;
&lt;p&gt;Result, 500x500px png&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Resized 2x 500x500px image" height="500" src="./rickmorty-500x500.png" width="500" /&gt;&lt;/figure&gt;
&lt;p&gt;If you ask me, results are really impressive, kudos to nagadomi!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 26 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/super-resolution-image-resizer/</guid></item><item><title>Arduino solar aimer</title><link>https://jeroenpelgrims.com/arduino-solar-aimer/</link><description>&lt;p&gt;This is the first "more advanced" thing I did with an Arduino. Well, more advanced than just turning on and off some leds that is.
I wanted to build something that would aim solar panels towards the sun, increasing their efficiency.&lt;/p&gt;
&lt;p&gt;I did this in 3 iterations, each one extending the previous one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First a construction where I steer the servos by buttons myself&lt;/li&gt;
&lt;li&gt;Then a construction where the servos are steered by light resistors&lt;/li&gt;
&lt;li&gt;And finally a construction where I add a bigger frame so I can put solar panels on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="requirements"&gt;Requirements&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#requirements" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2 &lt;a href="http://s.click.aliexpress.com/e/2z3N3bA"&gt;Micro 9g servo motors&lt;/a&gt; (2x 1.2 USD)&lt;/li&gt;
&lt;li&gt;4 &lt;a href="http://s.click.aliexpress.com/e/EA27I2F"&gt;Light dependent resistors&lt;/a&gt; (0.54 USD)&lt;/li&gt;
&lt;li&gt;1 Cheap &lt;a href="http://s.click.aliexpress.com/e/iA66YzR"&gt;Arduino (nano)&lt;/a&gt; (1.64 USD)&lt;/li&gt;
&lt;li&gt;Some &lt;a href="http://s.click.aliexpress.com/e/u7UzRNn"&gt;dupont wires&lt;/a&gt; (2.64 USD)&lt;/li&gt;
&lt;li&gt;4 &lt;a href="http://s.click.aliexpress.com/e/jiyBQVF"&gt;10k resistors&lt;/a&gt; (0.76 USD)&lt;/li&gt;
&lt;li&gt;1 &lt;a href="http://s.click.aliexpress.com/e/iA2RfyB"&gt;breadboard&lt;/a&gt; (1.99 USD)&lt;/li&gt;
&lt;li&gt;4 &lt;a href="http://s.click.aliexpress.com/e/MzVZfEm"&gt;pushbuttons&lt;/a&gt; (0.99 USD) (Only for the first iteration)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So you can build this for &lt;strong&gt;less than 10 USD&lt;/strong&gt;. (Prices shown are at time of writing)&lt;/p&gt;
&lt;h2 id="iteration-1-manual-aiming"&gt;Iteration 1: Manual aiming&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#iteration-1-manual-aiming" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first iteration is being able to steer the servos manually.&lt;br /&gt;
When I press the right button the pointer should move right, when I press the forward button it should move forward et cetera.&lt;/p&gt;
&lt;p&gt;2 servos will be placed on top eachother. The bottom servo determines the movement on the horizontal plane and the top servo the vertical plane.&lt;br /&gt;
The top servo is attached to the bottom one by it's side.&lt;/p&gt;
&lt;h3 id="a-video-of-this-in-action"&gt;A video of this in action&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#a-video-of-this-in-action" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id="a-schematic-of-the-breadboard"&gt;A schematic of the breadboard:&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#a-schematic-of-the-breadboard" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://jeroenpelgrims.com/arduino-solar-aimer/./arduino-servos-buttons.png"&gt;&lt;img alt="Breadboard schematic" src="https://jeroenpelgrims.com/arduino-solar-aimer/./arduino-servos-buttons.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="the-code"&gt;The code&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#the-code" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The code can be found &lt;a href="https://gitlab.com/jeroenpelgrims/arduino-servos-buttons"&gt;on GitLab&lt;/a&gt;&lt;br /&gt;
This repo also includes a &lt;a href="http://fritzing.org"&gt;Fritzing&lt;/a&gt; file which includes the breadboard schematic.&lt;br /&gt;
If you change the &lt;code&gt;MOVE_STEP&lt;/code&gt; variable to for example 5, the servo will move more per tick.&lt;br /&gt;
You'll then get something that moves &lt;a href="https://youtu.be/wHwNu8AjMwI"&gt;like this&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="iteration-2-replacing-the-buttons-by-photoresistors"&gt;Iteration 2: Replacing the buttons by Photoresistors&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#iteration-2-replacing-the-buttons-by-photoresistors" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Instead of me manually directing where the pointer should aim we'll add some automation by using photoresistors. (Light dependent resistors)&lt;br /&gt;
Most of this is based on &lt;a href="http://www.instructables.com/id/Arduino-Solar-Tracker/"&gt;this&lt;/a&gt; Instructables post.&lt;/p&gt;
&lt;p&gt;The main idea is that you have 4 sensors which are partitioned into 4 quadrants (Top Right, Bottom Right, Bottom Left, Top Left).&lt;br /&gt;
A division is made by 4 flat pieces of wood so that the resistor is not influenced by the light from the other resistors' partitions.&lt;br /&gt;
In the code you will then determine which direction receives more light and instruct the servos to point the "stick" to that direction.&lt;/p&gt;
&lt;h3 id="video-of-this-in-action"&gt;Video of this in action&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#video-of-this-in-action" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id="a-schematic-of-the-breadboard-1"&gt;A schematic of the breadboard:&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#a-schematic-of-the-breadboard-1" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://jeroenpelgrims.com/arduino-solar-aimer/./arduino-solar-aimer.png"&gt;&lt;img alt="Breadboard schematic" src="https://jeroenpelgrims.com/arduino-solar-aimer/./arduino-solar-aimer.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="the-code-1"&gt;The code&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#the-code-1" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This can again be found &lt;a href="https://gitlab.com/jeroenpelgrims/arduino-solar-aimer"&gt;on GitLab&lt;/a&gt;&lt;br /&gt;
And includes another Fritzing file with the breadboard schematics.&lt;/p&gt;
&lt;h2 id="3rd-iteration-building-a-frame-for-the-solar-panels"&gt;3rd Iteration: Building a frame for the solar panels&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#3rd-iteration-building-a-frame-for-the-solar-panels" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Instead of taping the servos together I made something more permanent with wood and glue.&lt;br /&gt;
The wood sticks I also bought &lt;a href="http://s.click.aliexpress.com/e/7iMFAAM"&gt;from AliExpress&lt;/a&gt; :D.&lt;/p&gt;
&lt;h3 id="video"&gt;Video&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#video" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id="the-code-2"&gt;The code&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#the-code-2" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The only thing that changed is the construction. The actual aiming system is still the same.&lt;br /&gt;
We just want to point to where the most light is coming from, so the code is exactly the same as in Iteration 2.&lt;/p&gt;
&lt;h3 id="final-notes"&gt;Final Notes&lt;a class="zola-anchor" href="https://jeroenpelgrims.com/arduino-solar-aimer/#final-notes" title="Click here to get a direct link to this section in your browser's address bar."&gt;§&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As you can maybe see in the last video the construction is quite wobbly.&lt;br /&gt;
That's because all the weight is being beared by the thin axes of the servos and the thin ice cream wood sticks aren't the ideal construction material.&lt;br /&gt;
I'd like to try making a construction where I make use of gears or a belt transmission so the weight can be beared by the surface below it.&lt;/p&gt;
&lt;p&gt;But the next project will be actually mounting the &lt;a href="http://s.click.aliexpress.com/e/imA2vzJ"&gt;solar panels&lt;/a&gt; I ordered on the construction and powering the arduino setup with them!&lt;br /&gt;
But I need to wait a while for that because it takes a while to receive the goods from AliExpress.&lt;/p&gt;</description><author>Jeroen Pelgrims</author><pubDate>Sun, 25 Jun 2017 13:26:00 GMT</pubDate><guid isPermaLink="true">https://jeroenpelgrims.com/arduino-solar-aimer/</guid></item><item><title>Increase keyboard key repeat rate on MacOS</title><link>https://june.kim/key-repeat-for-mac/</link><author>june.kim</author><pubDate>Sun, 25 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/key-repeat-for-mac/</guid></item><item><title>HTTP API Design Part 2: Responses</title><link>https://thomashunter.name/posts/2017-06-24-http-api-design-part-2-responses</link><author>Thomas Hunter II</author><pubDate>Sat, 24 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-06-24-http-api-design-part-2-responses</guid></item><item><title>What programming language should I learn: or Why it doesn’t matter</title><link>/what-lang-to-learn/</link><description>&lt;p&gt;Searching &lt;a href="https://www.google.com/search?q=what%20programming%20language%20should%20I%20learn"&gt;‘What programming language should I learn’&lt;/a&gt; will return you over 7 million results. The first one says Javascript, the next PHP, another extols the virtues of Java and statically typed languages. What even is a statically typed language you might ask? I just want to make apps for my phone!&lt;/p&gt;
&lt;p&gt;This is the struggle of beginners learning to program — and even myself, when I was looking for a second language to learn. There is so much noise and no clear path. Now I’m not about to add to all those articles and recommend you &lt;em&gt;another&lt;/em&gt; language.&lt;/p&gt;
&lt;p&gt;I’m instead going to promote a new idea — &lt;strong&gt;IT DOESN’T MATTER.&lt;/strong&gt; No really! Here me out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There is no one programming language to rule them all.&lt;/strong&gt; Although there are many people who vouch that Javascript can be used anywhere and is therefore the best, with React Native for native applications on both mobile and desktop, Node JS on the server and regular plain ol’ Javascript baked right into the browser. It sounds a very compelling argument. And it certainly is. I think Javascript is a great language to learn for anyone. Having said all that however, let’s look at the history of programming languages and frameworks.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href="https://www.tiobe.com/tiobe-index/"&gt;TIOBE index&lt;/a&gt;, Java is by far, firmly positioned in the number 1 spot. Javascript is on track to eclipse that, but it wasn’t that long ago, that the coolest language on the market was &lt;a href="https://en.wikipedia.org/wiki/Perl"&gt;Perl&lt;/a&gt; or even &lt;a href="https://en.wikipedia.org/wiki/Fortran"&gt;Fortran&lt;/a&gt;. My point here is that, even though a language seems popular right now, technology is an extremely vicious landscape. Ever changing as preferences ebb and flow and new technologies are favoured for older ones.&lt;/p&gt;
&lt;p&gt;Even within the Javascript ecosystem specifically, only a year ago Angular was the thing. Then React came along, and everyone jumped ship. Angular 2 was later released with little interest — Angular 1’s usage continued to dwindle. It can flip in an instant. A number of people were rightfully aggravated that they had spent all this time learning a framework that was now as good as dead.&lt;/p&gt;
&lt;p&gt;My point here is this…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Languages and frameworks, come and go. Concepts are here to stay.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s take &lt;a href="https://facebook.github.io/react/docs/thinking-in-react.html"&gt;React&lt;/a&gt; as an example here. I am of the opinion that although React is not here to stay. The concepts and underlying principles behind React are definitely here to stay. The way React promotes a hierarchical component structure and flows data through that structure; The way it only re-renders the parts of the components that have had a state change, is all amazing.&lt;/p&gt;
&lt;p&gt;Now whether you chose to learn React or not is your choice, but the concepts behind it will soon be applied in other languages. And at that point, if you do understand React, you will be able to adopt that way of thinking when building your application in that languages version of React.&lt;/p&gt;
&lt;p&gt;In the wildly successful game &lt;a href="https://en.wikipedia.org/wiki/Portal_(video_game)"&gt;Portal&lt;/a&gt;, the narrator comments “&lt;a href="https://www.youtube.com/watch?v=TluRVBhmf8w"&gt;Now you’re thinking with Portals&lt;/a&gt;”. The idea of the saying is that now you’re thinking with the technology you have, in this case the Portal gun which the player users to create two ends of a portal that link between each other.&lt;/p&gt;
&lt;p&gt;We can apply this saying to the technology we work with. When you finally crack the concept of how data can travel from your models through to your views, you can say “Now I’m thinking with &lt;a href="https://medium.freecodecamp.com/model-view-controller-mvc-explained-through-ordering-drinks-at-the-bar-efcba6255053"&gt;MVC&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;&lt;img alt="You’re not a REAL programming if you’re not doing this #obvi (source: https://xkcd.com/378/)" src="https://cdn-images-1.medium.com/max/2000/1*6O2fiWWJy7Ban_oF5AJejg.png" /&gt;&lt;em&gt;You’re not a REAL programming if you’re not doing this #obvi (source: &lt;a href="https://xkcd.com/378/"&gt;https://xkcd.com/378/&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Trying to get into this space and become a developer can be a scary place, but fear not! Programming is about the problem solving skills you develop. Not about what shiny syntax you happen to use. Many people use a language that they never used before that job (myself included). When learning to program, you will naturally acquire these skills. It’s something I was told when I first started to learn to code, when I thought to get a job you had to be this NASA-level genius that had made 10 apps and half a dozen website (hint: you don’t need that — it certainly helps though!), I didn’t believe what they had to say. I simply couldn’t fathom this indescribable skill you just ‘acquired’ as if by some miasma. Well, it is true. Trust me.&lt;/p&gt;
&lt;p&gt;My piece of specific advise would be to &lt;strong&gt;start building things&lt;/strong&gt; as soon as possible. They don’t have to be amazing, they don’t have to be original. They just have to be something you’d like to try out. &lt;a href="https://www.freecodecamp.com/"&gt;Freecodecamp&lt;/a&gt; does this excellently in their curriculum. One of my first projects was a calculator. I came to that project because I know how calculators work and I know how add, subtract, divide and multiple work. From my learning of programming, I knew that to keep track of the buttons the user had pushed I could store it in a variable. I knew I would need to hook up the buttons to trigger a function that would do various things. I had almost no idea of the inner workings of the application. But &lt;strong&gt;overarchingly&lt;/strong&gt; I knew the concepts of how it should work. Apply this same principle to things you build and you’ll go far. It’s also great because you get to solve &lt;strong&gt;actual&lt;/strong&gt; problems as if you were on a job. And debugging, like you will in a job. 90% of programming is debugging what you’ve written — so get used to it! Further, doing a project yourself will give you an understanding of what the code does. Many tutorials adopt a “type this, do that” mentality, with little explanation given to what or how this thing works. Take the time to read documentation and truly understand what you are writing.&lt;strong&gt;If you don’t right away, that’s ok&lt;/strong&gt;. Take some time, chew on it, and come back to it later. That’s part of learning these concepts.&lt;/p&gt;
&lt;p&gt;As a bonus to all this project building, at the end, you get something cool you can show your Mum, Dad, Cat or beloved family member/pet.&lt;/p&gt;
&lt;p&gt;Keep learning. Don’t get discouraged. And have fun, make some cool stuff, programming is like digital wizardry, use your powers!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Additional reading&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/learnprogramming/wiki/faq#wiki_which_programming_language_should_i_start_with.3F"&gt;https://www.reddit.com/r/learnprogramming/wiki/faq#wiki_which_programming_language_should_i_start_with.3F&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author/><pubDate>Sat, 24 Jun 2017 01:12:03 GMT</pubDate><guid isPermaLink="true">/what-lang-to-learn/</guid></item><item><title>./gitconfig</title><link>https://june.kim/gitconfig/</link><author>june.kim</author><pubDate>Fri, 23 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/gitconfig/</guid></item><item><title>HTTP API Design Part 1: Requests</title><link>https://thomashunter.name/posts/2017-06-23-http-api-design-part-1-requests</link><author>Thomas Hunter II</author><pubDate>Fri, 23 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-06-23-http-api-design-part-1-requests</guid></item><item><title>Animate React component by calling 'setState' in 'componentDidMount'</title><link>https://muffinman.io/blog/react-rerender-in-component-did-mount/</link><description>&lt;article class="article"&gt;&lt;p&gt;On the frontend, we do a lot of animations. Most of the simple animations I create by using CSS transitions.
Either I will change class or inline style of the element, and define transitions in CSS file.&lt;/p&gt;
&lt;p&gt;Easiest way to do this in React is to render initial state, and then when it renders, change the state to apply class or style to animate. The easiest way to do it in React is to change state in &lt;code&gt;componentDidMount&lt;/code&gt;.
Setting state in &lt;code&gt;componentDidMount&lt;/code&gt; is considered to be anti-pattern, as it forces rerender and can lead to property/layout thrashing. But in our case, that is exactly what we want to do.&lt;/p&gt;
&lt;p&gt;When we do that, we hit the wall - only second state is rendered and there is no transition between two states. It happens because of browsers optimization - &lt;strong&gt;browsers are not rerendering stuff that changed in the same animation frame.&lt;/strong&gt; But they merge changes and render the end result.&lt;/p&gt;
&lt;p&gt;The problem I just described is not React exclusive, but browser related.
Same will happen if we try something like this:&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; element &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token dom variable"&gt;document&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;querySelector&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;.AnimateMe&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;element&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;style&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;height&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;50px&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;element&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;style&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;height&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;250px&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So let&amp;#x27;s start with example of the problem.&lt;/p&gt;
&lt;h2 id="animate-component-by-changing-state-in-componentdidmount-doesnt-work"&gt;Animate component by changing state in &lt;code&gt;componentDidMount&lt;/code&gt; doesn&amp;#x27;t work &lt;a class="anchor-link" href="#animate-component-by-changing-state-in-componentdidmount-doesnt-work"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The scenario I described above. Element height depends on &lt;code&gt;this.state.animation&lt;/code&gt; property.
It is initially set to &lt;code&gt;false&lt;/code&gt; and element height should be 50px.
In &lt;code&gt;componentDidMount&lt;/code&gt; we&amp;#x27;ll change the value of &lt;code&gt;this.props.animation&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;
and element height should be 250px. As we added transition, it should animate.&lt;/p&gt;
&lt;p&gt;But it doesn&amp;#x27;t as all of this happens really fast, and browser decides to merge changes
and render only the end result. This way our element immediately gets height of 250px.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;export&lt;/span&gt; &lt;span class="token keyword"&gt;default&lt;/span&gt; &lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;AnimateMe&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;constructor&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;props&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;super&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;props&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;state&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      animate&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;false&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;componentDidMount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setState&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; animate&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;true&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;        &lt;span class="token attr-name"&gt;style&lt;/span&gt;&lt;span class="token script language-javascript"&gt;&lt;span class="token script-punctuation punctuation"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;          background&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;#eee&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;          border&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;1px solid black&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;          height&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;state&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;animate&lt;/span&gt; &lt;span class="token operator"&gt;?&lt;/span&gt; &lt;span class="token number"&gt;250&lt;/span&gt; &lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;50&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;          margin&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;20&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;          padding&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;20&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;          transition&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;all 2s&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token script language-javascript"&gt;        &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;      &lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;        Animate my height
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;      &lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="solution-add-a-short-timeout"&gt;Solution, add a short timeout &lt;a class="anchor-link" href="#solution-add-a-short-timeout"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;#x27;ve run multiple times into this problem, but I was lazy to dig deeper and find the real reason why it is happening. My solution was to add a timeout, first I tried immediate timeout (&lt;code&gt;setTimeout(fn, 0)&lt;/code&gt;), but alas, it didn&amp;#x27;t work in some browsers (as it happened too fast again and browser did their optimizations). Then I increased it to the magical value 50 (&lt;code&gt;setTimeout(fn, 50)&lt;/code&gt;), and it worked in every browser.&lt;/p&gt;
&lt;p&gt;Now I get the reason why it works. Because 50ms is larger than animation frame (which is around 16ms to achieve 60fps).&lt;/p&gt;
&lt;small&gt;(I&amp;#x27;ll show you just the part of the code that is changed)&lt;/small&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token method function property-access"&gt;componentDidMount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Added timeout&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token constant"&gt;ANIMATION_TIMEOUT&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;50&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setTimeout&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setState&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; animate&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;true&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token constant"&gt;ANIMATION_TIMEOUT&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So this is cross browser solution, but I always cringe a little when I&amp;#x27;m forced to use timeouts like this. And I have been talking about animation frames a lot, so why don&amp;#x27;t we try that next?&lt;/p&gt;
&lt;h2 id="using-requestanimationframe-instead-on-timeout"&gt;Using &lt;code&gt;requestAnimationFrame&lt;/code&gt; instead on timeout &lt;a class="anchor-link" href="#using-requestanimationframe-instead-on-timeout"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&amp;#x27;ll just replace timeout with &lt;code&gt;requestAnimationFrame&lt;/code&gt; and it should work.
But not in Firefox :( to make things worse, sometimes it does, and sometimes doesn&amp;#x27;t.
My guess that sometimes it gets squeezed in to the same animation frame.&lt;/p&gt;
&lt;h3 id="update-october-2017"&gt;Update, October 2017 &lt;a class="anchor-link" href="#update-october-2017"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Hooray! Firefox fixed this one, in newer versions it works without two nested &lt;code&gt;requestAnimationFrame&lt;/code&gt;.
But you might want to stick with it for some time, to make sure all of your users upgraded their browsers.&lt;/p&gt;
&lt;small&gt;(Again just the part of the code that is changed)&lt;/small&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token method function property-access"&gt;componentDidMount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Added requestAnimationFrame&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setState&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; animate&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;true&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now we need to make sure our two states belong to different animation frames each.&lt;/p&gt;
&lt;h2 id="nested-requestanimationframe-to-the-rescue"&gt;Nested &lt;code&gt;requestAnimationFrame&lt;/code&gt; to the rescue &lt;a class="anchor-link" href="#nested-requestanimationframe-to-the-rescue"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Idea is to separate renders of two states to different animation frames.
As we are not going to wrap React&amp;#x27;s &lt;code&gt;render&lt;/code&gt; method into animation frame,
we need to nest them instead in &lt;code&gt;componentDidMount&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This way we guarantee first render won&amp;#x27;t be merged together with the second one.
Problem we had in Firefox is now gone.&lt;/p&gt;
&lt;p&gt;This looks hacky, but I think it is a legit solution. Instead of trying to get a &lt;em&gt;magic&lt;/em&gt;
value for timeout, just use native methods that browsers provide.&lt;/p&gt;
&lt;small&gt;(Again just the part of the code that is changed)&lt;/small&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token method function property-access"&gt;componentDidMount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Added two nested requestAnimationFrames&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token comment"&gt;// Firefox will sometimes merge changes that happened here&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token function"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setState&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; animate&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;true&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="finally-put-it-in-a-helper"&gt;Finally, put it in a helper &lt;a class="anchor-link" href="#finally-put-it-in-a-helper"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To make things a bit cleaner, I extract this to a helper function and then use whenever I need it.
This can be used in our React examples but also with any other framework or vanilla JavaScript.&lt;/p&gt;
&lt;p&gt;If you support browsers without &lt;code&gt;requestAnimationFrame&lt;/code&gt; be sure to polyfill it. Paul Irish has a great one  &lt;a href="https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Start animation helper using nested requestAnimationFrames&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;startAnimation&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;callback&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token function"&gt;callback&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;small&gt;(Our &lt;code&gt;componentDidMount&lt;/code&gt; code using helper)&lt;/small&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token method function property-access"&gt;componentDidMount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// You&amp;#x27;ll need to import startAnimation at the top of the file&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;startAnimation&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setState&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; animate&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token boolean"&gt;true&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token spread operator"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="at-the-end"&gt;At the end &lt;a class="anchor-link" href="#at-the-end"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hope you learned something, and I&amp;#x27;m interested to hear if somebody is using different approach to solve this problem. Cheers!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 23 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-rerender-in-component-did-mount/</guid></item><item><title>Bufferbloat?</title><link>https://www.mikekasberg.com/blog/2017/06/21/bufferbloat.html</link><description>&lt;p&gt;Have you ever noticed your internet connection get slower when uploading a large
file? I have, but I never put too much thought into it or realized I could do
anything about it… Until I stumbled upon
&lt;a href="https://medium.com/speedtest-by-ookla/engineer-maximizes-internet-speed-story-c3ec0e86f37a"&gt;this&lt;/a&gt;
blog post from a systems engineer at Ookla (the company behind
&lt;a href="https://www.speedtest.net/"&gt;speedtest.net&lt;/a&gt;). As it turns out, there’s a term for
this (bufferbloat), and this is an easily solvable problem.&lt;/p&gt;

&lt;h2 id="what-is-bufferbloat"&gt;What is Bufferbloat&lt;/h2&gt;

&lt;p&gt;As Brennen explains in his blog,
&lt;a href="https://en.wikipedia.org/wiki/Bufferbloat"&gt;bufferbloat&lt;/a&gt; is a problem that
occurs when a router’s buffers fill up due to a slow connection (like the slower
upload connection most ISPs provide). The rate of data going into the router is
faster than the rate of data going out, the buffers get full, and the whole
thing slows down. The solution is pretty simple - just send data in a little
slower than the fastest rate it can leave.&lt;/p&gt;

&lt;h2 id="do-i-have-bufferbloat"&gt;Do I Have Bufferbloat?&lt;/h2&gt;

&lt;p&gt;After stumbling across Brennen’s blog, I wanted to check if my own internet
connection was affected by this problem. As it turns out, this is easy to test:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ping google.com&lt;/code&gt; and leave it running.&lt;/li&gt;
  &lt;li&gt;Run &lt;a href="https://www.speedtest.net/"&gt;speedtest.net&lt;/a&gt; in a browser. Pay particular
attention to when the upload test starts.&lt;/li&gt;
  &lt;li&gt;Watch ping, and look for a spike in latency.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your response times go up during the upload, it’s bufferbloat! In my own
results, I saw a roughly 2,650% increase (\( \frac{330 - 12}{12} \)) in ping response time during upload.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Ping output" src="https://www.mikekasberg.com/images/bufferbloat/slow-ping.png" /&gt;&lt;/p&gt;

&lt;h2 id="fixing-bufferbloat"&gt;Fixing Bufferbloat&lt;/h2&gt;

&lt;p&gt;Brennen details how he fixed bufferbloat on his network, but I wanted to solve
the problem without shelling out for an expensive router if I could. Luckily, I
was already using a Linksys E900 wireless router with DD-WRT installed. DD-WRT
supports some basic QoS settings, so I went into the admin panel and set up QoS
to limit my WAN uploads to 4,720 kbps, or roughly 80% of what
&lt;a href="https://www.speedtest.net/"&gt;speedtest.net&lt;/a&gt; says my max upload speed is.&lt;/p&gt;

&lt;p&gt;&lt;img alt="DD-WRT settings" src="https://www.mikekasberg.com/images/bufferbloat/dd-wrt-settings.png" /&gt;&lt;/p&gt;

&lt;p&gt;After applying the QoS settings, I ran the ping test again and my results were
unaffected by the upload. Success! I checked the download speeds to, just to
confirm my settings changes did not make them significantly worse.&lt;/p&gt;

&lt;p&gt;So that’s it. A simple rate limit on my router fixed the problem. My upload rate
might be marginally slower due to my own artificial limit, &lt;em&gt;but my download
speed will not be impacted&lt;/em&gt;. That is, &lt;em&gt;I can continue browsing the internet with
normal, fast speeds even while uploading a large file&lt;/em&gt;. That’s a trade-off I’m
happy to make.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Thu, 22 Jun 2017 06:27:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/06/21/bufferbloat.html</guid></item><item><title>3D Rotation Design</title><link>https://mattkeeter.com/projects/rotation</link><description>An interactive explainer</description><author>Matt Keeter</author><pubDate>Thu, 22 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/rotation</guid></item><item><title>Why Refactoring Isn't Popular</title><link>https://cmdev.com/blog/2017-06-22-whynotrefactoring/</link><description>Refactoring is cleaning the kitchen while you cook.</description><author>The Cranky Developer on Crater Moon Development</author><pubDate>Thu, 22 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://cmdev.com/blog/2017-06-22-whynotrefactoring/</guid></item><item><title>Sharding the LRU node cache in CruzDB</title><link>https://makedist.com/posts/2017/06/20/sharding-the-lru-node-cache-in-cruzdb/</link><description>Improving read performance by sharding the LRU node cache.</description><author>Noah Watkins</author><pubDate>Tue, 20 Jun 2017 19:19:12 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2017/06/20/sharding-the-lru-node-cache-in-cruzdb/</guid></item><item><title>Diffie-Hellman Key Exchange</title><link>https://denvaar.dev/posts/diffie_hellman_key_exchange.html</link><description>An explanation of an important public key cryptography algorithm as well as some of the history behind it.</description><author>denvaar's website</author><pubDate>Tue, 20 Jun 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/diffie_hellman_key_exchange.html</guid></item><item><title>Why CI?</title><link>https://www.mikekasberg.com/blog/2017/06/19/why-ci.html</link><description>&lt;p&gt;In recent years (and in some cases, for many years), Continuous Integration (CI)
has been taking off. Almost any open source project you look at is using some
kind of CI tool like &lt;a href="https://jenkins.io/"&gt;Jenkins&lt;/a&gt;,
&lt;a href="https://travis-ci.org/"&gt;TravisCI&lt;/a&gt;, or &lt;a href="https://codeship.com/"&gt;CodeShip&lt;/a&gt;. In the
simplest cast, the CI server is just running unit tests. In more complex cases,
the CI server runs unit and integration tests, produces a build, and maybe even
deploys the software.&lt;/p&gt;

&lt;p&gt;Some people are quicker than others to add CI tooling to their own workflow. To
see the value in CI tools like these, you need to understand the problem they
are solving. Fundamentally, CI tools are solutions for &lt;em&gt;risk management&lt;/em&gt;. That
is, they help engineers reduce the risk associated with developing and deploying
code.&lt;/p&gt;

&lt;p&gt;There are several different approaches to risk management. Perhaps the most
basic is, “if it ain’t broken, don’t fix it.” In other words, if the code is
stable and you don’t change it, you don’t need to take on any additional risk.
And in that case, you probably don’t need CI either since you won’t be changing
the code very often.  This methodology works pretty well… Until it doesn’t.
Essentially, it will continue to work well as long as the software doesn’t need
to change (too much). Unfortunately, it breaks down when the software &lt;em&gt;does&lt;/em&gt;
need to change. And in the world of modern web applications, the software
&lt;em&gt;always&lt;/em&gt; needs to change. There’s always more traffic coming, APIs changing, or
a competitor who’s innovating. Thus, avoiding change in order to avoid risk is
not a viable strategy. In fact, after avoiding change for too long you start
&lt;em&gt;adding&lt;/em&gt; risk as the software “falls behind”, and changes become more difficult
and complex.&lt;/p&gt;

&lt;p&gt;Continuous Integration, essentially, is the solution to this problem. A CI
pipeline is designed to enable rapid changes in the safest way possible. It does
this by preventing code from being merged without passing unit tests. It does
this by producing a deployable build in a repeatable manner. It does this by
testing a build and ensuring that there are no regressions in functionality. And
it does this by deploying the build to production in a safe and repeatable
manner. A CI pipeline provides a pathway for developers to get their code into
production in the safest manner possible. In doing so, it provides developers a
way to quickly deploy changes to a code base with a minimal amount of risk.&lt;/p&gt;

&lt;p&gt;When developers are afraid to make changes to a codebase, the
code rots. Rotten code is more difficult, time-consuming, and risky to work
with. Good CI prevents code rot by reducing the risk associated with any code
change, which allows developers to make improvements and add features to a
codebase with minimal risk, and therefore minimal fear. This is incredibly
valuable, both to open source projects and to organizations.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Tue, 20 Jun 2017 05:42:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/06/19/why-ci.html</guid></item><item><title>How to Install TensorFlow on Ubuntu 16.04 with GPU Support</title><link>https://www.hallada.net/2017/06/20/how-to-install-tensorflow-on-ubuntu-16-04.html</link><description>&lt;p&gt;I found the &lt;a href="https://www.tensorflow.org/install/install_linux"&gt;tensorflow
documentation&lt;/a&gt; rather lacking
for installation instructions, especially in regards to getting GPU support.
I’m going to write down my notes from wrangling with the installation here for
future reference and hopefully this helps someone else too.
&lt;!--excerpt--&gt;&lt;/p&gt;

&lt;p&gt;This will invariably go out-of-date at some point, so be mindful of the publish
date of this post. Make sure to cross-reference other documentation that has
more up-to-date information.&lt;/p&gt;

&lt;h2 id="assumptions"&gt;Assumptions&lt;/h2&gt;

&lt;p&gt;These instructions are very specific to my environment, so this is what I am
assuming:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You are running Ubuntu 16.04. (I have 16.04.1)
    &lt;ul&gt;
      &lt;li&gt;You can check this in the output of &lt;code class="language-plaintext highlighter-rouge"&gt;uname -a&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have a 64 bit machine.
    &lt;ul&gt;
      &lt;li&gt;You can check this with &lt;code class="language-plaintext highlighter-rouge"&gt;uname -m&lt;/code&gt;. (should say &lt;code class="language-plaintext highlighter-rouge"&gt;x86_64&lt;/code&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have an NVIDIA GPU that has CUDA Compute Capability 3.0 or higher.
&lt;a href="https://developer.nvidia.com/cuda-gpus"&gt;NVIDIA documentation&lt;/a&gt; has a full table
of cards and their Compute Capabilities.  (I have a GeForce GTX 980 Ti)
    &lt;ul&gt;
      &lt;li&gt;You can check what card you have in Settings &amp;gt; Details under the label
“Graphics”&lt;/li&gt;
      &lt;li&gt;You can also check by verifying there is any output when you run &lt;code class="language-plaintext highlighter-rouge"&gt;lspci |
grep -i nvidia&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have a linux kernel version 4.4.0 or higher. (I have 4.8.0)
    &lt;ul&gt;
      &lt;li&gt;You can check this by running &lt;code class="language-plaintext highlighter-rouge"&gt;uname -r&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have gcc version 5.3.1 or higher installed. (I have 5.4.0)
    &lt;ul&gt;
      &lt;li&gt;You can check this by running &lt;code class="language-plaintext highlighter-rouge"&gt;gcc --version&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have the latest &lt;a href="https://i.imgur.com/8osspXj.jpg"&gt;proprietary&lt;/a&gt; NVIDIA
drivers installed.
    &lt;ul&gt;
      &lt;li&gt;You can check this and install it if you haven’t in the “Additional
Drivers” tab in the “Software &amp;amp; Updates” application (&lt;code class="language-plaintext highlighter-rouge"&gt;update-manager&lt;/code&gt;).
(I have version 375.66 installed)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have the kernel headers installed.
    &lt;ul&gt;
      &lt;li&gt;Just run &lt;code class="language-plaintext highlighter-rouge"&gt;sudo apt-get install linux-headers-$(uname -r)&lt;/code&gt; to install them
if you don’t have them installed already.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You have Python installed. The exact version shouldn’t matter, but for the
rest of this post I’m going to assume you have &lt;code class="language-plaintext highlighter-rouge"&gt;python3&lt;/code&gt; installed.
    &lt;ul&gt;
      &lt;li&gt;You can install &lt;code class="language-plaintext highlighter-rouge"&gt;python3&lt;/code&gt; by running &lt;code class="language-plaintext highlighter-rouge"&gt;sudo apt-get install python3&lt;/code&gt;. This
will install Python 3.5.&lt;/li&gt;
      &lt;li&gt;Bonus points: you can install Python 3.6 by following &lt;a href="https://askubuntu.com/a/865569"&gt;this
answer&lt;/a&gt;, but Python 3.5 should be fine.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="install-the-cuda-toolkit-80"&gt;Install the CUDA Toolkit 8.0&lt;/h2&gt;

&lt;p&gt;NVIDIA has &lt;a href="http://docs.nvidia.com/cuda/cuda-installation-guide-linux/"&gt;a big scary documentation
page&lt;/a&gt; on this, but I
will summarize the only the parts you need to know here.&lt;/p&gt;

&lt;p&gt;Go to the &lt;a href="https://developer.nvidia.com/cuda-downloads"&gt;CUDA Toolkit Download&lt;/a&gt;
page. Click Linux &amp;gt; x86_64 &amp;gt; Ubuntu &amp;gt; 16.04 &amp;gt; deb (network).&lt;/p&gt;

&lt;p&gt;Click download and then follow the instructions, copied here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;sudo dpkg -i cuda-repo-ubuntu1604_8.0.61-1_amd64.deb&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;sudo apt-get update&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;sudo apt-get install cuda&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will install CUDA 8.0. It installed it to the directory
&lt;code class="language-plaintext highlighter-rouge"&gt;/usr/local/cuda-8.0/&lt;/code&gt; on my machine.&lt;/p&gt;

&lt;p&gt;There are some &lt;a href="http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#post-installation-actions"&gt;post-install
actions&lt;/a&gt;
we must follow:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Edit your &lt;code class="language-plaintext highlighter-rouge"&gt;~/.bashrc&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Use your favorite editor &lt;code class="language-plaintext highlighter-rouge"&gt;gedit ~/.bashrc&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;nano ~/.bashrc&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;vim
~/.bashrc&lt;/code&gt;, whatever.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Add the following lines to the end of the file:
    &lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c"&gt;# CUDA 8.0 (nvidia) paths&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CUDA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/cuda-8.0
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/cuda-8.0/bin&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;:+:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/cuda-8.0/lib64&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;:+:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Save and exit.&lt;/li&gt;
  &lt;li&gt;Run &lt;code class="language-plaintext highlighter-rouge"&gt;source ~/.bashrc&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Install writable samples by running the script &lt;code class="language-plaintext highlighter-rouge"&gt;cuda-install-samples-8.0.sh
~/&lt;/code&gt;.
    &lt;ul&gt;
      &lt;li&gt;If the script cannot be found, the above steps didn’t work :(&lt;/li&gt;
      &lt;li&gt;I don’t actually know if the samples are absolutely required for what I’m
using CUDA for, but it’s recommended according to NVIDIA, and compiling
them will output a nifty &lt;code class="language-plaintext highlighter-rouge"&gt;deviceQuery&lt;/code&gt; binary which can be ran to test if
everything is working properly.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Make sure &lt;code class="language-plaintext highlighter-rouge"&gt;nvcc -V&lt;/code&gt; outputs something.
    &lt;ul&gt;
      &lt;li&gt;If an error, the above steps 1-4 didn’t work :(&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cd ~/NVIDIA_CUDA-8.0_Samples&lt;/code&gt;, cross your fingers, and run &lt;code class="language-plaintext highlighter-rouge"&gt;make&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;The compile will take a while&lt;/li&gt;
      &lt;li&gt;My compile actually errored near the end with an error about &lt;code class="language-plaintext highlighter-rouge"&gt;/usr/bin/ld:
cannot find -lnvcuvid&lt;/code&gt; I &lt;em&gt;think&lt;/em&gt; that doesn’t really matter because the
binary files were still output.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Try running &lt;code class="language-plaintext highlighter-rouge"&gt;~/NVIDIA_CUDA-8.0_Samples/bin/x86_64/linux/release/deviceQuery&lt;/code&gt;
to see if you get any output. Hopefully you will see your GPU listed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="install-cudnn-v51"&gt;Install cuDNN v5.1&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://askubuntu.com/a/767270"&gt;This AskUbuntu answer&lt;/a&gt; has good instructions.
Here are the instructions specific to this set-up:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Visit the &lt;a href="https://developer.nvidia.com/cudnn"&gt;NVIDIA cuDNN page&lt;/a&gt; and click
“Download”.&lt;/li&gt;
  &lt;li&gt;Join the program and fill out the survey.&lt;/li&gt;
  &lt;li&gt;Agree to the terms of service.&lt;/li&gt;
  &lt;li&gt;Click the link for “Download cuDNN v5.1 (Jan 20, 2017), for CUDA 8.0”&lt;/li&gt;
  &lt;li&gt;Download the “cuDNN v5.1 Library for Linux” (3rd link from the top).&lt;/li&gt;
  &lt;li&gt;Untar the downloaded file. E.g.:
    &lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Downloads
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; cudnn-8.0-linux-x64-v5.1.tgz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Install the cuDNN files to the CUDA folder:
    &lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;cuda
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; include/&lt;span class="k"&gt;*&lt;/span&gt; /usr/local/cuda-8.0/include/
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; lib64/&lt;span class="k"&gt;*&lt;/span&gt; /usr/local/cuda-8.0/lib64/
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /usr/local/cuda-8.0/lib64/libcudnn&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="install-libcupti-dev"&gt;Install libcupti-dev&lt;/h2&gt;

&lt;p&gt;This one is simple. Just run:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libcupti-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="create-a-virtualenv"&gt;Create a Virtualenv&lt;/h2&gt;

&lt;p&gt;I recommend using
&lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/index.html"&gt;virtualenvwrapper&lt;/a&gt;
to create the tensorflow virtualenv, but the TensorFlow docs still have
&lt;a href="https://www.tensorflow.org/install/install_linux#InstallingVirtualenv"&gt;instructions to create the virtualenv
manually&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/install.html"&gt;Install
virtualenvwrapper&lt;/a&gt;.
Make sure to add &lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/install.html#shell-startup-file"&gt;the required
lines&lt;/a&gt;
to your &lt;code class="language-plaintext highlighter-rouge"&gt;~/.bashrc&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Create the virtualenv:
    &lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mkvirtualenv &lt;span class="nt"&gt;--python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;python3 tensorflow
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="install-the-tensorflow-with-gpu-support"&gt;Install the TensorFlow with GPU support&lt;/h2&gt;

&lt;p&gt;If you just run &lt;code class="language-plaintext highlighter-rouge"&gt;pip install tensorflow&lt;/code&gt; you will not get GPU support. To
install the correct version you will have to install from a &lt;a href="https://www.tensorflow.org/install/install_linux#python_35"&gt;particular
url&lt;/a&gt;. Here is the
install command you will have to run to install TensorFlow 1.2 for Python 3.5
with GPU support:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.2.0-cp35-cp35m-linux_x86_64.whl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you need a different version of TensorFlow, you can edit the version number
in the URL. Same with the Python version (change &lt;code class="language-plaintext highlighter-rouge"&gt;cp35&lt;/code&gt; to &lt;code class="language-plaintext highlighter-rouge"&gt;cp36&lt;/code&gt; to install for
Python 3.6 instead, for example).&lt;/p&gt;

&lt;h2 id="test-that-the-installation-worked"&gt;Test that the installation worked&lt;/h2&gt;

&lt;p&gt;Save this script from &lt;a href="https://www.tensorflow.org/tutorials/using_gpu#logging_device_placement"&gt;the TensorFlow
tutorials&lt;/a&gt;
to a file called &lt;code class="language-plaintext highlighter-rouge"&gt;test_gpu.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Creates a graph.
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/cpu:0'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&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="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;)&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;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matmul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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="c1"&gt;# Creates a session with log_device_placement set to True.
&lt;/span&gt;&lt;span class="n"&gt;sess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigProto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_device_placement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# Runs the op.
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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;And then run it:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;python test_gpu.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should see your GPU card listed under “Device mapping:” and that each task
in the compute graph is assigned to &lt;code class="language-plaintext highlighter-rouge"&gt;gpu:0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you see “Device mapping: no known devices” then something went wrong and
TensorFlow cannot access your GPU.&lt;/p&gt;</description><author>Tyler Hallada - Blog</author><pubDate>Tue, 20 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hallada.net/2017/06/20/how-to-install-tensorflow-on-ubuntu-16-04.html</guid></item><item><title>Git Rebase by Example</title><link>https://blog.tracefunc.com/2017/06/20/git-rebase-by-example-html/</link><description>&lt;p&gt;Today at work, I determined that my current work in progress branch was going to want to be merged into production ahead of our next scheduled merge/deploy of master. To make it easier to merge into our production branch for a hot-fix deploy, I want to have the branch based off production instead of master.&lt;/p&gt;

&lt;!-- EXCERPT --&gt;

&lt;p&gt;So, I could do this manually:&lt;/p&gt;

&lt;div class="highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;table class="rouge-table"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="rouge-gutter gl"&gt;&lt;pre class="lineno"&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class="rouge-code"&gt;&lt;pre&gt;$ git reset HEAD~ # move HEAD commit back to staging
$ git stash save # move uncommited changes to stash
# repeat until all my changes are in stash
$ git checkout production
$ git stash pop
$ git commit ...
# again, repeat until complete
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, this is a pain in the neck because it’s all manual, and it loses the commit metadata (timestamps, but also author info if you’re moving commits from multiple people). Also, because I prefer small merges to big merges, I’ve merged master into my branch a few times, and that means deciding to commit or wipe commits.&lt;/p&gt;

&lt;p&gt;Instead, let’s git do all the work, and use &lt;code class="highlighter-rouge"&gt;git rebase&lt;/code&gt; to move my commits to their new home, and also filter out those merges.&lt;/p&gt;

&lt;p&gt;Before getting started, we should backup my branch, by just doing a &lt;code class="highlighter-rouge"&gt;git checkout -b wip-rebase&lt;/code&gt;. Then, to confirm exactly what my changes were we can run &lt;code class="highlighter-rouge"&gt;git cherry -v origin/master&lt;/code&gt;. This will list all the commits on the current branch that are not on the specified branch.&lt;/p&gt;

&lt;p&gt;Then, I want to start by getting rid of all my extra merges, and filter the branch to just these outbound changes. For this we’ll do an interactive rebase: &lt;code class="highlighter-rouge"&gt;git rebase -i acfad~&lt;/code&gt;, where acfad is the commit hash at the top of my change list (you can also just use a visual git browser or whatever to find the base commit for your changes). This will pop open an editor, and let me decide exactly how I want to handle each commit.&lt;/p&gt;

&lt;p&gt;This is a powerful tool, and all its options are beyond the scope of this article, but it will let you do anything from editing a commit message, to combining or reordering commits, to executing shell commands between specific commits.&lt;/p&gt;

&lt;p&gt;Here, we’re just dropping commits, so we can scroll down the editor here and any commit that wasn’t listed in our &lt;code class="highlighter-rouge"&gt;git cherry&lt;/code&gt; output we can change the &lt;code class="highlighter-rouge"&gt;pick&lt;/code&gt; to &lt;code class="highlighter-rouge"&gt;drop&lt;/code&gt;. Or, even easier, delete the line.&lt;/p&gt;

&lt;p&gt;Now save and quit the editor, and git will do its job. We can verify with another &lt;code class="highlighter-rouge"&gt;git cherry -v origin/master&lt;/code&gt; and compare output now with earlier output. Note that our oldest commits are unchanged, but the commit hash for the newer ones is changed. This is because the hash of a commit depends on the hashes of its parents, and by deleting merged commits from our history we are of course unable to use them as parents anymore. Also, looking directly at the &lt;code class="highlighter-rouge"&gt;git log&lt;/code&gt; we can see that deleting all commits from one branch of a merge commit will also delete the merge itself. For our purposes, as long as the commit messages in both &lt;code class="highlighter-rouge"&gt;git cherry&lt;/code&gt; outputs are the same, then we’re doing fine.&lt;/p&gt;

&lt;p&gt;Now that the busy work is behind us, we can get to the actual goal of moving the commits. The command for this will be &lt;code class="highlighter-rouge"&gt;git rebase --onto origin/production acfad~&lt;/code&gt; – again we’re referring to the parent of the first commit in our branch.&lt;/p&gt;

&lt;p&gt;This is the part that works exactly as I described above, git is “rewinding head to replay your work on top of it”. As with any merge (applying a commit in a changed context) you can expect to see some conflicts and can resolve them as usual. However when done, instead of commiting we’ll move on with &lt;code class="highlighter-rouge"&gt;git rebase --continue&lt;/code&gt;. If at any time things get confused and you make a mistake, &lt;code class="highlighter-rouge"&gt;git rebase --abort&lt;/code&gt; will roll you back to your branch as it was before rebasing.&lt;/p&gt;

&lt;p&gt;Once you’re done with the conflicts, &lt;code class="highlighter-rouge"&gt;git&lt;/code&gt; will finalize the rebase behind the scenes, and leave you back at your current branch having updated the root parent, and touched all the commits on the way down. We can confirm this with a final &lt;code class="highlighter-rouge"&gt;git cherry -v origin/master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now is a good time to run specs (or let CI work that for you) and do whatever other testing you need to confirm everything functions as it should.&lt;/p&gt;</description><author>set_trace_func</author><pubDate>Tue, 20 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tracefunc.com/2017/06/20/git-rebase-by-example-html/</guid></item><item><title>Fitbit Surge vs. Garmin Forerunner 35</title><link>https://www.mikekasberg.com/blog/2017/06/18/fitbit-surge-vs-garmin-forerunner-35.html</link><description>&lt;p&gt;I was recently shopping around for a new GPS running watch, and I tried both the
&lt;strong&gt;Fitbit Surge&lt;/strong&gt; and the &lt;strong&gt;Garmin Forerunner 35&lt;/strong&gt;. These devices are both good GPS
watches with a similar feature set, so I thought it would be worthwhile to see
how they stack up against each other.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;2020 Update:&lt;/strong&gt; 3 years after writing this blog post, I think both these
watches are &lt;em&gt;a little&lt;/em&gt; dated. I still think the Forerunner 35 is a great watch
if you can find one somewhere (even used) - in fact, &lt;strong&gt;you can probably get this
watch very cheaply today&lt;/strong&gt;, and it’s really still a great watch! If you’re
looking for something a little more modern, try the Forerunner 45. It’s similar
to the Forerunner 35, but newer. And if you want something with a lot more
features, check out the Garmin fēnix series. I have a new fēnix 5s and I love
it!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id="fitbit-surge"&gt;Fitbit Surge&lt;/h2&gt;

&lt;p&gt;&lt;img alt="Fitbit Surge" src="https://www.mikekasberg.com/images/fitbit-vs-garmin/fitbit.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;The Fitbit Surge is a solid choice for a GPS watch. As I write this, its MSRP is
$249, but you can find it for about $150, new, on sites like eBay. At that price
point, it is really competitive.&lt;/p&gt;

&lt;p&gt;The Surge comes with all the features you’d expect on a GPS watch. It tracks
your distance for a variety of activities including running, cycling, and
hiking. It also tracks heart rate, and I found both GPS distance and heart rate
to be reasonably accurate.&lt;/p&gt;

&lt;p&gt;Now, Fitbit (the company) grew up making all-day activity tracking devices, and
that heritage shows in the Fitbit Surge. The device can track your activity all
day, and excels at syncing this information to the Fitbit app on your phone.
This is where the Fitbit really shines - the app is easy to use and navigate.
It’s polished.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Good&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li class="list-image-plus"&gt;Syncs to Fitbit app &amp;amp; website.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;Fitbit app &amp;amp; website look nice and are easy to use.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;In run mode, you can see total distance, total time, and current pace. Scroll
   to see heart rate, average pace, etc.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;Phone notifications for texts and calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Bad&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li class="list-image-minus"&gt;Missing more advanced running features like intervals or lap recall.&lt;/li&gt;
  &lt;li class="list-image-minus"&gt;Does not support notifications other than text and calls. (No calendar
   notifications.)&lt;/li&gt;
  &lt;li class="list-image-minus"&gt;Can't go back to look at recent notifications.&lt;/li&gt;
  &lt;li class="list-image-minus"&gt;Can't go back to look at recent runs (on the watch).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="garmin-forerunner-35"&gt;Garmin Forerunner 35&lt;/h2&gt;

&lt;p&gt;&lt;img alt="Garmin Forerunner 35" src="https://www.mikekasberg.com/images/fitbit-vs-garmin/garmin.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;The Forerunner 35 is definitely a competitor for the Fitbit Surge. Officially priced (as I
write this) at $199, it can be found for about $170 (new). The Forerunner 35
lacks some of the features of the Surge, but also brings some additional
features that make it stand out.&lt;/p&gt;

&lt;p&gt;While Fitbit grew up making activity trackers, Garmin grew up making GPS
devices. Garmin has been making GPS devices for runners for a lot longer than
Fitbit has, and that shows in the Forerunner. For example, the Forerunner 35
lets you customize the screens you see during your activity with any of roughly
a dozen different stats. Things like distance, pace, average pace, time, etc.
The Forerunner does a better job managing things like interval workouts -
largely due to the fact that it has a better interface in run-mode that provides
more information than the Surge does. You can even let the watch run your
workout for you, as described
&lt;a href="https://www.mikekasberg.com/blog/2020/06/13/how-to-use-garmin-workouts.html"&gt;here&lt;/a&gt;
(although on the Forerunner 35 you need to set it up on the watch instead of the
app). The Forerunner 35 is also a smaller device than the surge, and was
therefore more comfortable to wear.&lt;/p&gt;

&lt;p&gt;The Forerunner 35 is a runner’s GPS, and with my background as a college runner,
I appreciated all of the features it offered. Still, it has room for
improvement. The Garmin phone app did not feel quite as polished as the Fitbit
app. Garmin Connect (the phone app and web interface) provides more data
than Fitbit but (as a result?) feels clunkier and harder to use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Good&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li class="list-image-plus"&gt;Syncs to Garmin Connect app &amp;amp; website.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;Customizable screens in run mode - see any stat wherever you want.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;Support for interval training.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;Supports most phone notifications (text, call, calendar, etc).&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;Small, comfortable, lightweight.&lt;/li&gt;
  &lt;li class="list-image-plus"&gt;You can go back to look at run history on the watch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Bad&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li class="list-image-minus"&gt;Garmin Connect app &amp;amp; website are not as easy to use as Fitbit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Both the Surge and the Forerunner 35 are good devices. I’d give both of them 4/5
stars. If you want a device that has a really clean phone app, a more
user-friendly interface, or all-day activity tracking, the Surge is definitely
the way to go. On the other hand, if you’d prefer to have a more customizable
run-mode interface, or if you want more advanced running features like
customizable workouts, you’ll be happier with the Forerunner once you figure out
how to navigate the app. It’s also worth mentioning that both of these devices
support syncing to &lt;a href="https://www.strava.com"&gt;Strava&lt;/a&gt;. This is an important
feature for me and is a huge plus for both of them.&lt;/p&gt;

&lt;p&gt;(Update/Full disclosure: I’m now employed by Strava, although I wasn’t at the
time I originally wrote this blog. Opinions in this blog are my own.)&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Mon, 19 Jun 2017 06:40:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/06/18/fitbit-surge-vs-garmin-forerunner-35.html</guid></item><item><title>Advanced Microservices</title><link>https://thomashunter.name/posts/2017-06-19-advanced-microservices</link><author>Thomas Hunter II</author><pubDate>Mon, 19 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-06-19-advanced-microservices</guid></item><item><title>Death</title><link>https://www.wints.org/notes/2017.06.19/</link><description>&lt;p&gt;I always imagined death to be a very uniquely individual experience. I always imagined how &lt;em&gt;I&lt;/em&gt; would cope with the death of a loved one, how &lt;em&gt;I&lt;/em&gt; would deal with my grief, how &lt;em&gt;I&lt;/em&gt; would find peace and regain normalcy.&lt;/p&gt;
&lt;p&gt;Although it seems obvious now, in all those hypotheticals, I never accounted for all the others going through the same thing.&lt;/p&gt;
&lt;p&gt;Like a black hole in the space-time continuum, death has a ripply, sucky effect, affecting everything near it.
I&amp;rsquo;m just one of the objects near it.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 19 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.19/</guid></item><item><link>http://michaelhoney.com/writing/2017/6/19/957mnakmrjb2s0crsyzijs9j2rleyu</link><description>&lt;figure class="
              sqs-block-image-figure
              intrinsic
            "&gt;
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                &lt;img alt="" height="1280" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1497830221878-F8973SY8PDTCTZ2LRMPL/image-asset.jpeg?format=1000w" width="1270" /&gt;

            
          
        
          
        

        
      
        &lt;/figure&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Mon, 19 Jun 2017 02:57:35 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2017/6/19/957mnakmrjb2s0crsyzijs9j2rleyu</guid></item><item><title>gutenberg init blog</title><link>https://tuckersiemens.com/posts/gutenberg-init-blog/</link><description>&lt;p&gt;When I first created this site I wanted to get it live as quickly as possible.
&lt;a href="https://hexo.io/"&gt;Hexo&lt;/a&gt;, a blogging framework written in Node.js, seemed like the perfect
tool. At the time I was rather interested in Node.js, so it seemed natural to
use a framework rooted in that community.&lt;/p&gt;
&lt;p&gt;By the time of my last post I'd become increasingly disinterested in Node.js
and much more interested in Rust and its community. It was mostly
procrastination, but I convinced myself that using a tool written in a language
I didn't use often directly contributed to the paucity of posts here, so I
finally decided to ditch Hexo.&lt;/p&gt;</description><author>Reilly Tucker Siemens</author><pubDate>Mon, 19 Jun 2017 02:17:00 GMT</pubDate><guid isPermaLink="true">https://tuckersiemens.com/posts/gutenberg-init-blog/</guid></item><item><title>Benchmarking the Performance of R Code</title><link>https://lukesingham.com/benchmarking-the-performance-of-r-code/</link><description>&lt;p&gt;To assess the performance of R code there's a great little package called &lt;a href="https://cran.r-project.org/web/packages/microbenchmark/index.html"&gt;microbenchmark&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;install.packages&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;'microbenchmark'&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;library&lt;span class="token punctuation"&gt;(&lt;/span&gt;microbenchmark&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was particularly interested in the performance increase of a &lt;a href="https://shiny.rstudio.com/"&gt;shiny application&lt;/a&gt; that reads in a bunch of &lt;code&gt;.csv&lt;/code&gt; data. To test the performance increase I ran the following code:&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token comment"&gt;# For all *.csv files in "data" directory&lt;/span&gt;&lt;br /&gt;csv.files &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; list.files&lt;span class="token punctuation"&gt;(&lt;/span&gt;path &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;"data"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; pattern &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;"*.csv"&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; full.names &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;TRUE&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# How many csvs are there?&lt;/span&gt;&lt;br /&gt;length&lt;span class="token punctuation"&gt;(&lt;/span&gt;csv.files&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;#[1] 13&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="token comment"&gt;# Benchmark&lt;/span&gt;&lt;br /&gt;results &lt;span class="token operator"&gt;&amp;lt;-&lt;/span&gt; microbenchmark&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;br /&gt;  read.csv2.test &lt;span class="token operator"&gt;=&lt;/span&gt; lapply&lt;span class="token punctuation"&gt;(&lt;/span&gt;csv.files&lt;span class="token punctuation"&gt;,&lt;/span&gt; read.csv2&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  read_csv.test  &lt;span class="token operator"&gt;=&lt;/span&gt; lapply&lt;span class="token punctuation"&gt;(&lt;/span&gt;csv.files&lt;span class="token punctuation"&gt;,&lt;/span&gt; read_csv&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;&lt;br /&gt;  times &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;50&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So that's 50 iterations of reading 13 files, or 650 reads for each function. Now to have a look at the results:&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;&lt;span class="token operator"&gt;&gt;&lt;/span&gt; results&lt;br /&gt;Unit&lt;span class="token operator"&gt;:&lt;/span&gt; milliseconds&lt;br /&gt;           expr       min        lq      mean    median        uq      max neval&lt;br /&gt; read.csv2.test &lt;span class="token number"&gt;111.18612&lt;/span&gt; &lt;span class="token number"&gt;118.28930&lt;/span&gt; &lt;span class="token number"&gt;124.71949&lt;/span&gt; &lt;span class="token number"&gt;123.38192&lt;/span&gt; &lt;span class="token number"&gt;131.20016&lt;/span&gt; &lt;span class="token number"&gt;144.3691&lt;/span&gt;    &lt;span class="token number"&gt;50&lt;/span&gt;&lt;br /&gt;  read_csv.test  &lt;span class="token number"&gt;67.56371&lt;/span&gt;  &lt;span class="token number"&gt;71.28666&lt;/span&gt;  &lt;span class="token number"&gt;76.22763&lt;/span&gt;  &lt;span class="token number"&gt;74.19215&lt;/span&gt;  &lt;span class="token number"&gt;78.06555&lt;/span&gt; &lt;span class="token number"&gt;105.8433&lt;/span&gt;    &lt;span class="token number"&gt;50&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not the most impressive gain from the &lt;code&gt;readr&lt;/code&gt; package, where the &lt;a href="https://readr.tidyverse.org/"&gt;documentation purports up to 10x faster reads&lt;/a&gt;, but still substantial and worth implementing. For a simple guide on UX and the implications of lag check out this &lt;a href="https://ux.stackexchange.com/a/3836/78865"&gt;stackexchange answer&lt;/a&gt;. And if you want even faster read/write operations have a look at &lt;a href="https://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.html"&gt;data.table&lt;/a&gt;'s &lt;code&gt;fread()&lt;/code&gt; function.&lt;/p&gt;
&lt;h2 id="examine-the-distribution-of-evaluations"&gt;Examine the Distribution of Evaluations &lt;a class="direct-link" href="https://lukesingham.com/benchmarking-the-performance-of-r-code/#examine-the-distribution-of-evaluations"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://cran.r-project.org/web/packages/microbenchmark/index.html"&gt;microbenchmark&lt;/a&gt; package includes a &lt;code&gt;boxplot()&lt;/code&gt; function which is a really good idea to look at prior to implementing a particular change in your code base. Here's an example of a comparison between a custom function and the same function compiled using the &lt;code&gt;compiler::cmpfun()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Here's a print out of the results:&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;print&lt;span class="token punctuation"&gt;(&lt;/span&gt;results&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;## Unit: microseconds&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##      expr    min      lq      mean  median      uq       max neval&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##     plain 87.550 90.5355 227.71949 91.8995 94.5685 13308.578   100&lt;/span&gt;&lt;br /&gt;&lt;span class="token comment"&gt;##  compiled 87.254 90.9845  95.71651 92.4605 96.1630   194.724   100&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I only compared the mean of the two functions, then I would expect to get a considerable 58% speed increase.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Microbenchmark Boxplot" src="https://lukesingham.com/content/images/2017/08/microbenchmark_compiled_function.png" /&gt;&lt;/p&gt;
&lt;p&gt;However, the boxplot of the results &lt;code&gt;boxplot(results)&lt;/code&gt; quickly reveals an outlier in the 100 evaluations performed that heavily impacts the mean. In this case, the median actually shows a negligible difference between the function and the byte compiled function.&lt;/p&gt;
&lt;p&gt;If you prefer a fancier looking plot, microbenchmark has included a &lt;a href="http://ggplot2.org/"&gt;ggplot2&lt;/a&gt; based &lt;code&gt;autoplot()&lt;/code&gt; function.&lt;/p&gt;
&lt;pre class="language-r"&gt;&lt;code class="language-r"&gt;library&lt;span class="token punctuation"&gt;(&lt;/span&gt;ggplot2&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;br /&gt;autoplot&lt;span class="token punctuation"&gt;(&lt;/span&gt;results&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="Microbenchmark Autoplot" src="https://lukesingham.com/content/images/2017/08/microbenchmark_autoplot.png" /&gt;&lt;/p&gt;
&lt;h1 id="when-should-you-use-microbenchmarking%3F"&gt;When Should You Use Microbenchmarking? &lt;a class="direct-link" href="https://lukesingham.com/benchmarking-the-performance-of-r-code/#when-should-you-use-microbenchmarking%3F"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I use the microbenchmark package whenever I am concerned about speeding up an application. Old hands know the obligatory computer science mantra and the Knuth quote that must go along with this microbenchmarking blog post.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Make it work, make it right, make it fast.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;-- Kent Beck&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;... premature optimization is the root of all evil...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;-- Donald Knuth&lt;/p&gt;
&lt;p&gt;Knuth goes on to say in &lt;a href="http://web.archive.org/web/20130731202547/http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf"&gt;his paper&lt;/a&gt;,&lt;em&gt;'It is often a mistake to make a priori judgments about what parts of a program are really critical'&lt;/em&gt;. Which is why you should first profile your code to identify where your efforts are best spent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Postscript&lt;/strong&gt; - &lt;a href="https://m.signalvnoise.com/cant-crack-that-programming-problem-go-to-sleep-or-take-a-walk-930c767e1119"&gt;After a few nights of sleep I realised&lt;/a&gt; why the compiled vs. non-compiled functions had the distributions they did. &lt;a href="https://stat.ethz.ch/pipermail/r-announce/2017/000612.html"&gt;Version 3.4 of R&lt;/a&gt; has &lt;a href="https://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;Just-In-Time (JIT) compiling&lt;/a&gt; at level 3 by default. The function I was comparing contains a &lt;code&gt;for&lt;/code&gt; loop. Therefore, the plots show the difference between the new &lt;code&gt;JIT(3)&lt;/code&gt; speed of R vs pre-compiling your functions that contain for loops. The first run of the non-compiled function is not byte-compiled, however all subsequent runs are byte-compiled. Hence one outlier but otherwise very similar distributions.&lt;/p&gt;</description><author>Luke Singham</author><pubDate>Sun, 18 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://lukesingham.com/benchmarking-the-performance-of-r-code/</guid></item><item><title>The Age Of Invisible Disasters</title><link>https://blog.eutopian.io/the-age-of-invisible-disasters/</link><description>1400 words, 5 minutes. The Tay Bridge disaster occurred during a violent storm on 28th December 1879 when the first Tay Rail Bridge collapsed while a train was passing over it from Wormit to Dundee, killing all 70 people aboard.
It is widely accepted by engineers that disasters teach us more than successes. Said another way, we don&amp;rsquo;t learn from the bridge that stays standing. After the Tay Bridge disaster there was an investigation.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Sun, 18 Jun 2017 00:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/the-age-of-invisible-disasters/</guid></item><item><title>Audio APIs, Part 1: Core Audio / macOS</title><link>https://bastibe.de/2017-06-17-audio-apis-coreaudio.html</link><description>&lt;p&gt;This is part one of a three-part series on the native audio APIs for Windows, Linux, and macOS. This first part is about Core Audio on macOS.&lt;/p&gt;
&lt;p&gt;It has long been a major frustration for my work that Python does not have a great package for playing and recording audio. My first step to improve this situation were a small contribution to &lt;a href="https://people.csail.mit.edu/hubert/pyaudio/"&gt;PyAudio&lt;/a&gt;, a CPython extension that exposes the C library &lt;a href="http://www.portaudio.com/"&gt;PortAudio&lt;/a&gt; to Python. However, I soon realized that PyAudio mirrors PortAudio a bit too closely for comfort. Thus, I set out to write &lt;a href="https://github.com/bastibe/PySoundCard"&gt;PySoundCard&lt;/a&gt;, which is a higher-level wrapper for PortAudio that tries to be more pythonic and uses NumPy arrays instead of untyped &lt;code&gt;bytes&lt;/code&gt; buffers for audio data. However, I then realized that PortAudio itself had some inherent problems that a wrapper would not be able to solve, and a truly great solution would need to do it the hard way:&lt;/p&gt;
&lt;p&gt;Instead of relying on PortAudio, I would have to use the native audio APIs of the three major platforms directly, and implement a simple, cross-platform, high-level, NumPy-aware Python API myself. This effort resulted in &lt;a href="https://github.com/bastibe/Python-Audio"&gt;PythonAudio&lt;/a&gt;, a new pure-Python package that uses &lt;a href="http://cffi.readthedocs.io/en/latest/"&gt;CFFI&lt;/a&gt; to talk to &lt;a href="https://www.freedesktop.org/wiki/Software/PulseAudio/"&gt;PulseAudio&lt;/a&gt; on Linux, &lt;a href="https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html"&gt;Core Audio&lt;/a&gt; on macOS, and &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455(v=vs.85"&gt;WASAPI&lt;/a&gt;.aspx)&lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt; on Windows.&lt;/p&gt;
&lt;p&gt;This series of blog posts summarizes my experiences with these three APIs and outlines the basic structure of how to use them. For reference, the singular use case in PythonAudio is playing/recording of short blocks of &lt;code&gt;float&lt;/code&gt; data at arbitrary sampling rates and block sizes. All connected sound cards should be listable and selectable, with correct detection of the system default sound card (a feature that is very unreliable in PortAudio).&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;CoreAudio, or the Mac's best kept secret&lt;/h2&gt;
&lt;p&gt;CoreAudio is the native audio library for macOS. It is known for its high performance, low latency, and horrible documentation. After having used the native audio APIs on all three platforms, CoreAudio was &lt;em&gt;by far&lt;/em&gt; the hardest one to use. The main problem is lack of documentation and lack of feedback, and plain missing or broken features. Let's get started.&lt;/p&gt;
&lt;p&gt;The basic unit of any CoreAudio program is the audio unit. An audio unit can be a source (aka microphone), a sink (aka speaker) or an audio processor (both sink and source). Each audio unit can have several input &lt;em&gt;buses&lt;/em&gt;, and several output &lt;em&gt;buses&lt;/em&gt;, each of which can have several &lt;em&gt;channels&lt;/em&gt;. The meaning of these buses varies wildly and is often underdocumented. Furthermore, every audio unit has several &lt;em&gt;properties&lt;/em&gt;, such as a sample rate, block sizes, and a data format, and &lt;em&gt;parameters&lt;/em&gt;, which are like properties, but presumably different in some undocumented way.&lt;/p&gt;
&lt;p&gt;In order to use an audio unit, you create an &lt;code&gt;AudioComponentDescription&lt;/code&gt; that describes whether you want a source or sink unit, or an effect unit, and what kind of effect you want (AudioComponent is an alternative name for audio unit). With the description, you can create an &lt;code&gt;AudioComponentInstance&lt;/code&gt;, which is then an opaque struct pointer to your newly created audio unit. So far so good.&lt;/p&gt;
&lt;p&gt;The next step is then to configure the audio unit using &lt;code&gt;AudioUnitGetProperty&lt;/code&gt; and &lt;code&gt;AudioUnitSetProperty&lt;/code&gt;. This is surprisingly hard, since every property can be configured for every bus (sometimes called element) of every input or output of every unit, and the documentation is extremely terse on which of these combinations are valid. Some invalid combinations return error codes, while others only lead to errors during playback/recording. Furthermore, the definition of what constitutes an input or output is interpreted quite differently in different places: One place calls a microphone an &lt;em&gt;input&lt;/em&gt;, since it records audio; another place will call it an &lt;em&gt;output&lt;/em&gt;, since it outputs audio data to the system. In one crazy example, you have to configure a microphone unit by disabling its output bus 0, and enabling its input bus 1, but then read audio data from its ostensibly disabled output bus 0.&lt;/p&gt;
&lt;p&gt;The property interface is untyped, meaning that every property has to be given an identifier, a void pointer that points to a matching data structure, and the size of that data structure. Sometimes the setter allocates additional memory, in which case the documentation does not contain any information on who should free this memory. Most objects are passed around as opaque struct pointers with dedicated constructor and destructor functions. All of this does not strike me as particularly C-like, even though CoreAudio is supposedly a native C library.&lt;/p&gt;
&lt;p&gt;Once your audio unit is configured, you set a render callback function, and start the audio unit. All important interaction now happens within that callback function. In a strange reversal of typical control flow, input data to the callback function needs to be fetched by calling &lt;code&gt;AudioUnitRender&lt;/code&gt; (evoked on the unit itself) from within the callback, while output is written to memory provided as callback function arguments. Many times during development, &lt;code&gt;AudioUnitRender&lt;/code&gt; would return error codes because of an invalid property setting during initialization. Of course, it won't tell &lt;em&gt;which&lt;/em&gt; property is actually at fault, just that it can't fulfill the render request at the moment.&lt;/p&gt;
&lt;p&gt;Error codes in general are a difficult topic in CoreAudio. Most functions return an error code as an &lt;code&gt;OSStatus&lt;/code&gt; value (aka &lt;code&gt;uint32&lt;/code&gt;), and the header files usually contain a definition of some, but not all, possible error codes. Sometimes these error codes are descriptive and nice, but often they are way too general. My favorite is the frequent &lt;code&gt;kAudioUnitErr_CannotDoInCurrentContext&lt;/code&gt;, which is just about as useless an error description as possible. Worse, some error codes are not defined as numeric constants, but as &lt;code&gt;int err = 'abcd'&lt;/code&gt;, which makes them un-searchable in the source file. Luckily, this madness can be averted using &lt;img alt="https://osstatus" src="https://osstatus.com/" /&gt;, which is a dedicated database for &lt;code&gt;OSStatus&lt;/code&gt; error codes.&lt;/p&gt;
&lt;p&gt;By far the worst part of the CoreAudio API is that some properties are silently ignored. For example, you can set the sample rate or priming information on a microphone unit, and it will accept that property change and it will report that property as changed, but it will still use its default value when recording (aka &amp;quot;rendering&amp;quot; in CoreAudio). A speaker unit, in contrast, will honor the sample rate property, and resample as necessary. If you still need to resample your microphone recordings, you have to use a separate &lt;code&gt;AudioConverter&lt;/code&gt; unit, which is its own bag of fun (and only documented in &lt;a href="https://developer.apple.com/library/content/technotes/tn2091/_index.html#//apple_ref/doc/uid/DTS10003118-CH1-FORMATS"&gt;a remark&lt;/a&gt; in one overview document).&lt;/p&gt;
&lt;p&gt;Lastly, all the online documentation is written for Swift and Objective-C, while the implementation is C. Worse, the C headers contain vastly more information than the online documentation, and the online documentation often does not even reference the C header file name. Of course header files are spread into the CoreAudio framework, the AudioToolkit framework, and the AudioUnit framework, which makes even grepping a joy.&lt;/p&gt;
&lt;p&gt;All of that said, once you know what to do and how to do it, the resulting code is relatively compact and readable. The API does contain inconsistencies and questionable design choices, but the real problem is the documentation. I spent way too much time reading the header files over and over again, and searching through (often outdated or misleading) &lt;a href="https://developer.apple.com/library/content/samplecode/AVCaptureToAudioUnitOSX/Listings/CaptureSessionController_mm.html#//apple_ref/doc/uid/DTS40012879-CaptureSessionController_mm-DontLinkElementID_4"&gt;example projects&lt;/a&gt; and &lt;a href="https://developer.apple.com/library/content/technotes/tn2091/_index.html#//apple_ref/doc/uid/DTS10003118-CH1-FORMATS"&gt;vague&lt;/a&gt; &lt;a href="https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/AudioUnitDevelopmentFundamentals/AudioUnitDevelopmentFundamentals.html#//apple_ref/doc/uid/TP40003278-CH7-SW12"&gt;high-level&lt;/a&gt; &lt;a href="https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40003278-CH1-SW2"&gt;overviews&lt;/a&gt; for clues on how to interpret error messages and API documentation. I had somewhat better luck with a few &lt;a href="http://kaniini.dereferenced.org/2014/08/31/CoreAudio-sucks.html"&gt;blog&lt;/a&gt; &lt;a href="http://subfurther.com/blog/2009/04/28/an-iphone-core-audio-brain-dump/"&gt;posts&lt;/a&gt; on the subject, but the general consensus seems to be that the main concepts of CoreAudio are woefully under-explained, and documentation about edge cases is almost nonexistent. Needless to say, I did not enjoy my experience with CoreAudio.&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;WASAPI is part of the Windows &lt;a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd370784(v=vs.85"&gt;Core Audio&lt;/a&gt;.aspx) APIs. To avoid confusion with the macOS API of the same name, I will always to refer to it as WASAPI.&lt;a class="footnote" href="#fnref-1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>bastibe.de</author><pubDate>Sat, 17 Jun 2017 17:45:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-06-17-audio-apis-coreaudio.html</guid></item><item><title>Resume-i</title><link>https://june.kim/resume-i/</link><author>june.kim</author><pubDate>Sat, 17 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/resume-i/</guid></item><item><title>Resume-r</title><link>https://june.kim/resume-r/</link><author>june.kim</author><pubDate>Sat, 17 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/resume-r/</guid></item><item><title>Resume-rn</title><link>https://june.kim/resume-rn/</link><author>june.kim</author><pubDate>Sat, 17 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/resume-rn/</guid></item><item><title>Network Upgrade</title><link>https://www.wints.org/notes/2017.06.17/</link><description>&lt;p&gt;&lt;a href="http://www.cisco.com/c/dam/en/us/td/docs/routers/csbr/rv130w/admin_guide/en/rv130w_admin_en.pdf"&gt;Cisco RV130 Router Manual (PDF)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt;
I set up a network - a router, two access points, a few switches and ~ 15 to 20 devices. Issues that need to be resolved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I want to be able to access the network from the outside.&lt;/li&gt;
&lt;li&gt;I want to give priority to VOIP devices.&lt;/li&gt;
&lt;li&gt;Privacy errors when trying to access Google sites (google.com, youtube.com, gmail.com).&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="access-network-from-the-outside"&gt;Access Network from the outside &lt;a href="#access-network-from-the-outside"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Now the network looks like this:&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Sat, 17 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.17/</guid></item><item><title>Elephants Out, Donkeys In</title><link>https://98.codes/elephants-out-donkeys-in/</link><description>&lt;!--kg-card-begin: markdown--&gt;&lt;p class="featurecaption"&gt;Photo by &lt;a href="https://flic.kr/p/eL5jpe?ref=98.codes" target="_blank"&gt;Toshihiro Oimatsu&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;In case you&amp;apos;ve been wondering what the people that dwell in Layers 3 &amp;amp; 4 of the Internet have been up to lately, here&amp;apos;s a taste:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Jon Postel&amp;apos;s famous statement in &lt;a href="https://tools.ietf.org/html/rfc1122?ref=98.codes"&gt;RFC 1122&lt;/a&gt; of &amp;quot;Be liberal in what you&lt;/p&gt;&lt;/blockquote&gt;</description><author>Text(Greg);</author><pubDate>Fri, 16 Jun 2017 18:46:20 GMT</pubDate><guid isPermaLink="true">https://98.codes/elephants-out-donkeys-in/</guid></item><item><title>Ethereum is to Bitcoin as the US is to Gold</title><link>https://olshansky.info/posts/2017-06-16-ethereum-bitcoin-us-gold/</link><description>This post was originally written as a follow up email to this tweet where one of the hosts of The Investor's Podcast ran a poll regarding people's thoughts on Bitcoin.</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 16 Jun 2017 05:45:36 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-06-16-ethereum-bitcoin-us-gold/</guid></item><item><title>Back in Chicago</title><link>https://faingezicht.com/photos/2017/06/16/chicago/</link><description>There are always good reasons to keep going back to Chicago. This time, it was for Hannah's cousin's wedding.</description><author>Avy Faingezicht</author><pubDate>Fri, 16 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/06/16/chicago/</guid></item><item><title>Laravel Dashboards</title><link>https://yasha.solutions/laravel-dashboards/</link><description>1. LaraAdmin GitHub : https://github.com/dwijitsolutions/laraadmin
Website: http://laraadmin.com/
2. Backpack https://backpackforlaravel.com/
3. Voyager https://github.com/the-control-group/voyager
Website: https://laravelvoyager.com/
4. CRUD Booster http://crudbooster.com/
5. Quick Admin https://github.com/LaravelDaily/quickadmin
6. Z-Song https://github.com/z-song/laravel-admin
7. appzcoder https://github.com/appzcoder/crud-generator
8. SleepingOwlAdmin https://github.com/LaravelRUS/SleepingOwlAdmin
 On Code Canyon – Paid stuff https://codecanyon.net/item/laravel-crud-cms-sximo-5-lts/11893533?ref=ericbarnes
https://codecanyon.net/item/josh-laravel-admin-template-front-end-crud/8754542?ref=ericbarnes
https://codecanyon.net/item/admin-architect-administration-framework-for-laravel/13528564?ref=ericbarnes
https://codecanyon.net/item/plmb-powerful-laravel-crud-generator-package-builder-dynamic-report-builder-admin-template/17314714</description><author>Yasha Solutions</author><pubDate>Fri, 16 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/laravel-dashboards/</guid></item><item><title>Bad Tools are Insidious</title><link>https://blog.harterrt.com/bad-tools.html</link><description>&lt;p&gt;This is my first job making data tools that other people use.
In the past, I've always been a data scientist -
a consumer of these tools.
I'm learning a lot.&lt;/p&gt;
&lt;p&gt;Last quarter, I learned that bad tools are often hard to spot even when they're damaging productivity.
I sum this …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 15 Jun 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/bad-tools.html</guid></item><item><title>Notes from Pycon 2017</title><link>https://faingezicht.com/articles/2017/06/15/pycon/</link><description>This year I finally got to attend Pycon. Having only attended a way smaller conference before (PyBay 2016) it was awesome to see the insanity that comes with cramming 3000+ pythonistas (!) into one convention center. I made an effort to branch out from just going to the talks, and spend some time talking to people and making connections. It was totally worth it.

As I expected, there was a lot of talk about Python 2 vs. Python 3 (there was even a guy walking around with a shirt that only said "2.8" on it) but the overall feeling I got was that people are moving away from 2.7. Those who are working on a (mostly) 2.7 codebase (like me) are doing so due to the existing legacy code, and inertia, not due to a lack of desire to upgrade. Python 3 is the shiny new thing, after all. Between the asynchronous story, and all the features that focus on making it easier to write less error-prone code, it seems like the community is coalescing around the 3.6 release, and looking towards a bright future.

Below, I've summarized some of the better talks that I attended. For a less technical view of my trip to PyCon, check out my &lt;a href="/photos/2017/05/22/pdx/"&gt;other Portland post&lt;/a&gt;, which has a bunch of photos, too. Anyway, talks:

* **Grok the GIL: Write Fast And Thread-Safe Python - A. Jesse Jiryu Davis**
    * In this talk, Davis discussed the &lt;a href="https://github.com/python/cpython/blob/e62a694fee53ba7fc16d6afbaa53b373c878f300/Python/ceval.c#L238"&gt;Global Interpreter Lock&lt;/a&gt;, what it is, and why it is necessary. In short, in CPython only one thread can run Python code at once, while others sleep or wait. The GIL is the mechanism through which a Python process handles the cooperative and preemptive multitasking that decides which thread runs the show, and studying the inner workings of the beast can help us avoid the bugs that come from running multi threaded Python. I definitely recommend watching the talk, but if not, at least take a look at &lt;a href="https://emptysqua.re/blog/grok-the-gil-fast-thread-safe-python/"&gt;Davis' write-up&lt;/a&gt;. To see these kind of bugs in action, you can also run &lt;a href="https://gist.github.com/avyfain/4d3ffaf476cfb2341dec080047d54d62"&gt;this quick demo&lt;/a&gt; I wrote.
    * &lt;a href="https://us.pycon.org/2017/schedule/presentation/320/"&gt;Presentation&lt;/a&gt;
    * &lt;a href="https://www.youtube.com/watch?v=7SSYhuk5hmc"&gt;Video&lt;/a&gt;

* **The Dictionary Even Mightier - Brandon Rhodes**
    * A rehash of Brandon's &lt;a href="https://www.youtube.com/watch?v=rWdF7oW6z18"&gt;old 2010 talk&lt;/a&gt;, revamped for Python 3 in 2017. It is odd how having started coding in Python in the 2.7 era means that I take so many of these features, including a few backports, totally for granted. Since python is &lt;a href="https://www.buzzfeed.com/andrewkelleher/deep-exploration-into-python-lets-review-the-dict-module"&gt;`dicts` all the way down&lt;/a&gt;, the effects of the whole laundry list of dictionary features and gotchas was pretty interesting. My favorite section was the demo on &lt;a href="https://medium.com/@robertgrosse/generating-64-bit-hash-collisions-to-dos-python-5b21404a5306"&gt;hash collisions/complexity attacks&lt;/a&gt;, where Rhodes had a great visual explanation of why bad hash functions are bad. Another highlight was the explanation of the new &lt;a href="https://www.python.org/dev/peps/pep-0509/"&gt;private dictionary version&lt;/a&gt; that shows up in 3.6. Jake VanderPlas' has a &lt;a href="https://jakevdp.github.io/blog/2017/05/26/exposing-private-dict-version/"&gt;good post&lt;/a&gt; on how to expose this private version, although he doesn't go deep into the use cases, the most important of which will be optimizing fast checks on whether a dict has changed.
    * &lt;a href="https://us.pycon.org/2017/schedule/presentation/520/"&gt;Presentation&lt;/a&gt;
    * &lt;a href="https://www.youtube.com/watch?v=66P5FMkWoVU"&gt;Video&lt;/a&gt;

* **Requests Under The Hood - Cory Benfield**
    * The point of this talk was simple: *Even the “best python codebases” have warts*. This is partially due to the nature of open source, and partially due to the complexity of managing large systems. Paraphrasing:
    &gt; "`$foo` would have been the right way to do this, but instead we did `$bar`. It mostly worked and people stopped complaining. So, the emergent behavior of `$bar`, even if wrong, became what users expected and now need, so we can't change it... because there are no tests.”

    This sounds like a nightmare I've had before. In all seriousness though, it is humbling to see that even super successful projects run into these issues.

    * &lt;a href="https://us.pycon.org/2017/schedule/presentation/71/"&gt;Presentation&lt;/a&gt;
    * &lt;a href="https://www.youtube.com/watch?v=ptbCIvve6-k"&gt;Video&lt;/a&gt;

* **async/await and asyncio in Python 3.6 and beyond - Yuri Selivanov**
    * I'll go ahead and say that a lot of this went over my head. While I understand the ideas behind `asyncio`, I have not played with it enough to fully get the added value of some of the potential new things coming in 3.7. However, this new model will provide the building blocks for other frameworks and libraries that are already in the pipe - looking at you &lt;a href="https://github.com/dabeaz/curio"&gt;curio&lt;/a&gt; and &lt;a href="https://github.com/python-trio/trio"&gt;trio&lt;/a&gt;! For a more beginner's friendly version of it, take a look at &lt;a href="https://www.youtube.com/watch?v=iG6fr81xHKA"&gt;Miguel Grinberg's presentation&lt;/a&gt;.

    * &lt;a href="https://us.pycon.org/2017/schedule/presentation/511/"&gt;Presentation&lt;/a&gt;
    * &lt;a href="https://www.youtube.com/watch?v=2ZFFv-wZ8_g"&gt;Video&lt;/a&gt;

* **Bonus: Modern Python Dictionaries A confluence of a Dozen Great Ideas - Raymond Hettinger**
    * It is kind of unfair to list this talk along the other ones, since I didn't actually go, but having seen &lt;a href="https://www.youtube.com/watch?v=p33CVV29OG8"&gt;a previous version&lt;/a&gt; of the same talk, I know it is good. The optimizations discussed in this session are one of the main reasons why Python 3's underlying `dict` objects are so lightweight compared to their 2 counterparts.
    * &lt;a href="https://us.pycon.org/2017/schedule/presentation/18/"&gt;Presentation&lt;/a&gt;
    * &lt;a href="https://www.youtube.com/watch?v=npw4s1QTmPg"&gt;Video&lt;/a&gt;

The rest of the talks can be found &lt;a href="https://us.pycon.org/2017/schedule/talks/"&gt;here&lt;/a&gt;, and the recorded videos in this &lt;a href="https://www.youtube.com/channel/UCrJhliKNQ8g0qoE_zvL8eVg"&gt;YouTube Channel&lt;/a&gt;. I definitely recommend you take a look, and for some more inspiration you can always check out my &lt;a href="https://github.com/avyfain/resources"&gt;resources repo&lt;/a&gt;, which is full of talks and articles worth watching.

Conferences are worth it for the networking, and for the learning, but most of all, for the motivation that comes from seeing awesome people showcase their projects. After my trip, I came back with a whole lot of things to try, and a ton of energy to burn through. Python is as strong as ever. See you next year!

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: by me, also posted on &lt;a href="/photos/2017/05/22/pdx/"&gt;Portlanding&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Thu, 15 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/06/15/pycon/</guid></item><item><title>Another Great Link Dump - June 2017</title><link>https://faingezicht.com/links/2017/06/15/another-link-dump/</link><description>Ha. And here I was thinking I'd post links more often... My stats say that while I used to read roughly 10-12 articles a day, these days I am barely hitting 5. My yearly rolling average peaked in mid-2016.

To be honest, I am not sure what to make of it.

This round-up is full of Apple stuff, so not too many comments on my end, but sharing some interesting perspectives. There's also a ton on cryptocurrencies, because that's the latest craze in tech, and I have also been following along.</description><author>Avy Faingezicht</author><pubDate>Thu, 15 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/06/15/another-link-dump/</guid></item><item><title>Another Great (Podcast) Link Dump - June 2017</title><link>https://faingezicht.com/links/2017/06/15/linkdump-podcast-edition/</link><description/><author>Avy Faingezicht</author><pubDate>Thu, 15 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/06/15/linkdump-podcast-edition/</guid></item><item><title>Debuting the performance of CruzDB</title><link>https://makedist.com/posts/2017/06/14/debuting-the-performance-of-cruzdb/</link><description>Hot of the press performance results show plenty of room to improve.</description><author>Noah Watkins</author><pubDate>Wed, 14 Jun 2017 20:54:39 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2017/06/14/debuting-the-performance-of-cruzdb/</guid></item><item><title>Ufora: Generating a Population of Commoners</title><link>https://mbutler.org/ufora-generating-a-population-of-commoners/</link><description>Recently, I&amp;#8217;ve become interested in the so-called &amp;#8220;funnel method&amp;#8221; of character creation in the RPG Dungeon Crawl Classics. The funnel is a process of deriving your 1st-level character by running a handful of 0-level commoners through a dungeon and seeing who comes out the other side alive. A group of players would need to funnel [&amp;#8230;]</description><author>mbutler</author><pubDate>Wed, 14 Jun 2017 19:34:03 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/ufora-generating-a-population-of-commoners/</guid></item><item><title>Implementing malloc and free</title><link>https://andrestc.com/post/implementing-malloc-and-free/</link><description>&lt;hr /&gt;
&lt;p&gt;Chapter 7 of “The Linux Programming Interface” is about memory allocation. One of the exercises, marked as advanced, asks the reader to implement &lt;a href="https://linux.die.net/man/3/malloc"&gt;malloc&lt;/a&gt;. I’ve decided to give it a shot. My full implementation is available on &lt;a href="https://github.com/andrestc/linux-prog/blob/master/ch7/malloc.c"&gt;Github&lt;/a&gt;. I will try to break down some of my reasoning on the next sections and include some snippets from the code.&lt;/p&gt;
&lt;h2 id="memory-layout-of-aprocess"&gt;Memory layout of a Process&lt;/h2&gt;
&lt;p&gt;The memory allocated to each process is composed of multiple segments, as can be seen on the following image:
&lt;img alt="process layout" src="https://github.com/shichao-an/notes/blob/master/docs/tlpi/figure_6-1.png?raw=true" /&gt;
We are particularly interested on the heap (also known as the data segment), an area from which memory can be dynamically allocated at run time. The top end of the heap is called the &lt;strong&gt;program break&lt;/strong&gt;.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Wed, 14 Jun 2017 16:00:00 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/implementing-malloc-and-free/</guid></item><item><title>All new and shiny!</title><link>https://98.codes/all-new-and-shiny/</link><description>New effort, new URL, why not a new paint job?</description><author>Text(Greg);</author><pubDate>Wed, 14 Jun 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://98.codes/all-new-and-shiny/</guid></item><item><title>Home Battery Systems – You may de-rate system capacity</title><link>https://boyter.org/2017/06/home-battery-systems-de-rate-system-capacity/</link><description>&lt;p&gt;A quick post. I was looking at the prices to install a home battery system the other day. During the sales process I was informed that for a modular system such as the one provided by Ampetus that if you don&amp;rsquo;t buy 2 or more batteries that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;you may de rate system capacity&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sound&amp;rsquo;s impressively scary! Slightly worried I asked that it means. Thankfully what it actually means is that instead of getting 3kW delivery using two batteries that one battery matched with the inverter may only deliver 1.5kW. This is not a problem if you are still connected to the grid but it can mean that your inverter isn&amp;rsquo;t working at its full potential. So in short nothing to worry about.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Wed, 14 Jun 2017 11:06:12 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/06/home-battery-systems-de-rate-system-capacity/</guid></item><item><title>What I'm Using</title><link>https://98.codes/uses/</link><description>&lt;!--kg-card-begin: markdown--&gt;&lt;p&gt;Every now and then I get asked or need to explain to people what my setup is, and in the grand tradition of straight &lt;a href="https://wesbos.com/uses/?ref=98.codes"&gt;copying&lt;/a&gt; &lt;a href="https://jonsuh.com/uses/?ref=98.codes"&gt;others&lt;/a&gt;, I thought I&amp;apos;d do the same. So, without further ado...&lt;br /&gt;
&lt;/p&gt;
&lt;h2 id="editors"&gt;Editors&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/?ref=98.codes"&gt;Visual Studio Code&lt;/a&gt; (Canary/Nightly/&amp;quot;Insider&amp;quot; Edition)&lt;/li&gt;
&lt;li&gt;Extensions: I&amp;&lt;/li&gt;&lt;/ul&gt;</description><author>Text(Greg);</author><pubDate>Tue, 13 Jun 2017 19:51:00 GMT</pubDate><guid isPermaLink="true">https://98.codes/uses/</guid></item><item><title>Great Writing</title><link>https://www.dannyguo.com/blog/great-writing</link><author>Danny Guo</author><pubDate>Tue, 13 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/great-writing</guid></item><item><title>Sparse files</title><link>https://andrestc.com/post/sparse-files/</link><description>&lt;p&gt;Following my read of “The Linux Programming Interface”, I came across the concept of “file with holes” or “sparse files”. Those are files that try to use the file system more effectively by preventing it from using disk space when sections of the file are empty. The disk storage is only actually used when needed. Sparse files are really useful for backup utilities, disk images, database snapshots etc.&lt;/p&gt;
&lt;p&gt;One way to create a sparse file is by using &lt;strong&gt;truncate&lt;/strong&gt;:&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Tue, 13 Jun 2017 02:16:49 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/sparse-files/</guid></item><item><title>100 days of content: Day 0</title><link>https://98.codes/100-days-of-content-day-0/</link><description>&lt;!--kg-card-begin: markdown--&gt;&lt;p class="featurecaption"&gt;Picture via &lt;a href="https://www.flickr.com/photos/lorenkerns/14544328432/?ref=98.codes" target="_blank"&gt;Loren Kerns&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://100daysofcode.com/?ref=98.codes"&gt;100 Days of Code&lt;/a&gt; is a thing that I&amp;apos;ve been thinking about doing... it&amp;apos;s a way to be accountable, to myself and others... but I want to do more than code. After all, coding is my day-in and day-out&lt;/p&gt;</description><author>Text(Greg);</author><pubDate>Tue, 13 Jun 2017 00:13:00 GMT</pubDate><guid isPermaLink="true">https://98.codes/100-days-of-content-day-0/</guid></item><item><title>Big-O Explained and Why You Will Never Beat a Pigeon</title><link>https://lucasfcosta.com/blog/Big-O-Explained-And-Why-You-Will-Never-Beat-a-Pigeon/</link><description>In this blog post I will prove you will never be able to write an algorithm that scales better than a pigeon and also teach you some basic concepts when it comes to Big O notation.

Big O is often ...</description><author>Lucas F. Costa - Blog</author><pubDate>Mon, 12 Jun 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Big-O-Explained-And-Why-You-Will-Never-Beat-a-Pigeon/</guid></item><item><title>I like the price ceiling and floor approach but see two issues with it.</title><link>https://olshansky.info/posts/2017-06-11-i-like-the-price-ceiling-and-floor-approach-but-see-two-issues-with-it/</link><description>If we’re selling a DAO token with equal voting rights, and a majority is required to make some decision, then someone could come in and…</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 12 Jun 2017 09:00:15 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-06-11-i-like-the-price-ceiling-and-floor-approach-but-see-two-issues-with-it/</guid></item><item><title>Thinking in emoji</title><link>http://dimitarsimeonov.com/2017/06/12/thinking-in-emoji</link><description>&lt;p&gt;Would you say that you think in emoji? No. You think in words, in
English. At least consciously that is. Whenever you’re conscious,
words show up in your brain and travel the neural pathways to the
hands. The fingers are typing on the keyboard and a characters are
appearing on the screen. The characters on the screen are each one of
the small set we call alphabet.&lt;/p&gt;

&lt;p&gt;Every thought we want to convey in writing, we have to pipe through
this alphabet. Even if the thought was momentary, it might take
multiple sentences to convey in text. The text unfolds and unfolds
like a string of proteins, a ball of wool. It is a labyrinth, which we
need to navigate every time we try to express that thought.&lt;/p&gt;

&lt;p&gt;We need to not only get ourselves through the labyrinth, we need to
drag with us our audience. When the labyrinth is large and complex, we
might lose our audience due to fatigue. They are only willing to
follow us up to a degree.&lt;/p&gt;

&lt;p&gt;They will also abandon us if we lead them the wrong way. When we reach
a dead end, a lot of our credibility evaporates, and our audience will
give us the finger.&lt;/p&gt;

&lt;p&gt;We will also fail on getting them across if go too close to a
Minotaur. The monster will catch them and kill them, and they will
never get to exit.&lt;/p&gt;

&lt;p&gt;We only have one chance to get them across.&lt;/p&gt;

&lt;p&gt;And we need emoji. Bear with me.&lt;/p&gt;

&lt;p&gt;Whenever we can take a shortcut and break through a wall of the
labyrinth, we increase our chance of getting our followers
through. Because we can then find a faster and simpler path, and avoid
dangerous Minotaurs which will lead our audience to a different
conclusion.&lt;/p&gt;

&lt;p&gt;Whenever we can convey an idea, an emotion, or a feeling in a more
compact way, we arm ourselves with a sledgehammer that can bulldoze
though the walls of the labyrinth. And whenever we use emoji right, we
can get our ideas more compactly.&lt;/p&gt;

&lt;p&gt;As we are piercing though the walls of the labyrinth’s of complexity
and emotion, we develop a new, more direct way to traverse it. A new
way of thinking. The way of thinking in emoji, is the way babies
think. Natural and unburdened by artificial constructs.&lt;/p&gt;

&lt;p&gt;As emoji are becoming more and more prominent everywhere our brains
become more and more 🔥&lt;/p&gt;</description><author>D13V</author><pubDate>Mon, 12 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/06/12/thinking-in-emoji</guid></item><item><title>Network Architecture: Switches</title><link>https://www.wints.org/notes/2017.06.12/</link><description>&lt;p&gt;Working at client&amp;rsquo;s space today, setting up their internal network from the ground up.
Learned a few things today:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ideally have:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wall &amp;ndash;&amp;gt; Router &amp;ndash;&amp;gt; Managed Switch &amp;ndash;&amp;gt; Unmanaged Switches (subnets) &amp;ndash;&amp;gt; End Users&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Difference between unmanaged and managed switches:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Managed:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;- can control individual ports
- set static/dynamic ips
- sniff traffic
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Also learned about a new (for me) community:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://0x00sec.org/"&gt;https://0x00sec.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Similar to &lt;a href="https://news.ycombinator.com"&gt;HN&lt;/a&gt; but more for security and reverse engineering.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 12 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.12/</guid></item><item><title/><link>https://rybakov.com/blog/blueshorts/</link><description>&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/_RYB4560_cut.jpg" /&gt;




&lt;/figure&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 11 Jun 2017 23:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/blueshorts/</guid></item><item><title>knetstat: checking socket options on Linux</title><link>https://blog.separateconcerns.com/2017-06-11-knetstat.html</link><description>&lt;p&gt;A few weeks ago I was debugging network code, and I needed to check if some
sockets were bound with &lt;code&gt;SO_REUSEADDR&lt;/code&gt; and/or &lt;code&gt;SO_REUSEPORT&lt;/code&gt;. I researched how
I could inspect that, and was surprised to find out that the Linux kernel did
not expose those options to userland.&lt;/p&gt;
&lt;p&gt;Thankfully, there is
&lt;a href="https://github.com/veithen/knetstat"&gt;a kernel module called knetstat&lt;/a&gt;
which lets you do this very easily by adding new files into &lt;code&gt;procfs&lt;/code&gt;. When I
found it it only supported TCP, but I needed the information for UDP as well so
I &lt;a href="https://github.com/veithen/knetstat/pull/11"&gt;contributed the code&lt;/a&gt; to
support it.&lt;/p&gt;
&lt;p&gt;If you write networking code on Linux or just run servers, I encourage you to
check it out. It is a nice little tool that can come very handy in some
situations, including when you need to check options like &lt;code&gt;SO_{RCV,SND}BUF&lt;/code&gt;.&lt;/p&gt;</description><author>Separate Concerns</author><pubDate>Sun, 11 Jun 2017 20:10:00 GMT</pubDate><guid isPermaLink="true">https://blog.separateconcerns.com/2017-06-11-knetstat.html</guid></item><item><title>Studying Mathematics with Anki and MathJax</title><link>https://korz.dev/2017/06/studying-mathematics-with-anki-and-mathjax/</link><description>&lt;p&gt;In this tutorial, we will learn how to effectively use &lt;a href="http://www.ankisrs.net/"&gt;Anki&lt;/a&gt; flashcards for learning mathematics. For this, we are going add a little bit of magic to our cards by using &lt;a href="https://www.mathjax.org/"&gt;MathJax&lt;/a&gt; and &lt;a href="https://en.wikibooks.org/wiki/LaTeX/Mathematics"&gt;LaTeX&lt;/a&gt;.&lt;/p&gt;</description><author>Niklas Korz</author><pubDate>Sun, 11 Jun 2017 14:20:00 GMT</pubDate><guid isPermaLink="true">https://korz.dev/2017/06/studying-mathematics-with-anki-and-mathjax/</guid></item><item><title>Silicon Valley: Season 4</title><link>https://olshansky.info/tv/silicon_valley_season_4/</link><description>Olshansky's review of Silicon Valley: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 10 Jun 2017 04:07:27 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/silicon_valley_season_4/</guid></item><item><title>Currency Wars: The Making of the Next Global Crisis</title><link>https://olshansky.info/book/currency_wars/</link><description>Olshansky's review of Currency Wars: The Making of the Next Global Crisis by James Rickards</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 10 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/currency_wars/</guid></item><item><title>Working with time in Postgres</title><link>/2017/06/08/working-with-time-in-postgres/</link><description>&lt;p&gt;A massive amount of reporting queries, whether really intensive data analysis, or just basic insights into your business involving looking at data over a certain time period. Postgres has really rich support for dealing with time out of the box, something that&amp;rsquo;s often very underweighted when dealing with a database. Sure, if you have a time-series database it&amp;rsquo;s implied, but even then how flexible and friendly is it from a query perspective? With Postgres there&amp;rsquo;s a lot of key items available to you, let&amp;rsquo;s dig in at the things that make your life easier when querying.&lt;/p&gt;
&lt;h3 id="date-math"&gt;
&lt;div&gt;
Date math
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The most common thing I find myself doing is looking at users that have done something within some specific time window. If I&amp;rsquo;m executing this all from my app I can easily inject specific dates, but Postgres makes this really easy for you. Within Postgres you have a type called an interval that is some window of time. And fortunately Postgres takes care of the heavy lifting of how might something translate to or from hours/seconds/milliseconds/etc. Here&amp;rsquo;s just a few examples of things you could do with interals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;lsquo;1 day&amp;rsquo;::interval&lt;/li&gt;
&lt;li&gt;&amp;lsquo;5 days&amp;rsquo;::interval&lt;/li&gt;
&lt;li&gt;&amp;lsquo;1 week&amp;rsquo;::interval&lt;/li&gt;
&lt;li&gt;&amp;lsquo;30 days&amp;rsquo;::interval&lt;/li&gt;
&lt;li&gt;&amp;lsquo;1 month&amp;rsquo;::interval&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;A note that if you&amp;rsquo;re looking to remove something like a full month, you actually want to use 1 month instead of trying to calculate yourself.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With a given interval you can easily shift some window of time, such as finding all users that have signed up for your service within the past week:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #f92672;"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; users
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;WHERE&lt;/span&gt; created_at &lt;span style="color: #f92672;"&gt;&amp;gt;=&lt;/span&gt; now() &lt;span style="color: #f92672;"&gt;-&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;'1 week'&lt;/span&gt;::interval
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="date-functions"&gt;
&lt;div&gt;
Date functions
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Date math makes it pretty easy for you to go and find some specific set of data that applies, but what do you do when you want a broader report around time? There&amp;rsquo;s a few options here. One is to leverage the built-in Postgres functions that help you work with dates and times. &lt;code&gt;date_trunc&lt;/code&gt; is one of the most used ones that will truncate a date down to some interval level. Here you can use the same general values as the above, but simply pass in the type of interval it will be. So if we wanted to find the count of users that signed up per week:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT date_trunc('week', created_at),
count(*)
FROM users
GROUP BY 1
ORDER BY 1 DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This gives us a nice roll-up of how many users signed up each week. What&amp;rsquo;s missing here though is if you have a week that has no users. In that case because no users signed up there is no count of 0, it just simply doesn&amp;rsquo;t exist. If you did want something like this you could generate some range of time and then do a cross join with it against users to see which week they fell into. To do this first you&amp;rsquo;d generate a series of dates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; generate_series(&lt;span style="color: #e6db74;"&gt;'2017-01-01'&lt;/span&gt;::date, now()::date, &lt;span style="color: #e6db74;"&gt;'1 week'&lt;/span&gt;::interval) weeks
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we&amp;rsquo;re going to join this against the actual users table and check that the &lt;code&gt;created_at&lt;/code&gt; falls within the right range.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;with weeks as (
select week
from generate_series('2017-01-01'::date, now()::date, '1 week'::interval) week
)
SELECT weeks.week,
count(*)
FROM weeks,
users
WHERE users.created_at &amp;gt; weeks.week
AND users.created_at &amp;lt;= (weeks.week - '1 week'::interval)
GROUP BY 1
ORDER BY 1 DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="timestamp-vs-timestamptz"&gt;
&lt;div&gt;
Timestamp vs. Timestamptz
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;What about storing the times themselves? Postgres has two types of timestamps. It has a generic timestamp and one with timezone embedded in it. In most cases you should generally opt for timestamptz. Why not timestamp? What happens if you move a server, or your server somehow swaps its configuration. Or perhaps more practically what about daylight savings time? In general you might think that you can simply just put in the time as you see it, but when different countries around the world observe things like daylight savings time differently it introduces complexities into your application.&lt;/p&gt;
&lt;p&gt;With timestamptz it&amp;rsquo;ll be aware of the extra parts of your timezone as it comes in. Then when you query from one timezone that accounts for daylights savings you&amp;rsquo;re all covered. There&amp;rsquo;s a &lt;a href="http://phili.pe/posts/timestamps-and-time-zones-in-postgresql/"&gt;number of articles&lt;/a&gt; that cover a bit more in depth on the logic between timestamp and timestamp with timezone, so if you&amp;rsquo;re curious I encourage you to check them out, but by default you mostly just need to use timestamptz.&lt;/p&gt;
&lt;h3 id="more"&gt;
&lt;div&gt;
More
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a number of other functions and capabilities when it comes to dealing with time in Postrges. You can &lt;code&gt;extract&lt;/code&gt; various parts of a timesetamp or interval such as hour of the day or the month. You can grab the day of the week with &lt;code&gt;dow&lt;/code&gt;. And one of my favorites which is when we celebrate happy hour at Citus, there&amp;rsquo;s a literal for UTC 00:00:00 00:00:00 which is &lt;a href="https://www.postgresql.org/message-id/20050124200645.GA6126%40winnie.fuhr.org"&gt;&lt;code&gt;allballs()&lt;/code&gt;&lt;/a&gt;. If you need to work with dates and times in Postgres I encourage you to check out the &lt;a href="https://www.postgresql.org/docs/current/static/functions-datetime.html"&gt;docs&lt;/a&gt; before you try to re-write something of your own, chances are what you need may already be there.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 08 Jun 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/06/08/working-with-time-in-postgres/</guid></item><item><title>Using Graylog for logging on Amazon ECS</title><link>https://tricht.eu/post/using-graylog-for-logging-on-amazon-ecs/</link><description>&lt;p&gt;At work we use &lt;a href="https://aws.amazon.com/ecs/" target="_blank"&gt;AWS ECS&lt;/a&gt; (Amazon EC2 Container Service) for orchestrating our docker containers. We have a rather small
number of containers running (26~) which all log to &lt;a href="https://aws.amazon.com/cloudwatch/" target="_blank"&gt;CloudWatch&lt;/a&gt;. Being unsatisfied by the features such as alerting we started looking for a better logging solution.&lt;/p&gt;</description><author>Michael van Tricht</author><pubDate>Thu, 08 Jun 2017 22:29:34 GMT</pubDate><guid isPermaLink="true">https://tricht.eu/post/using-graylog-for-logging-on-amazon-ecs/</guid></item><item><title>How to use Snapcraft v2 on Trusty</title><link>https://kyrofa.com/posts/how-to-use-snapcraft-v2-on-trusty/</link><description>As of this writing there are two major versions of Snapcraft: v1 and v2. Snapcraft v1 creates snaps that target Ubuntu Core 15, and Snapcraft v2 creates snaps that target Ubuntu Core 16. Series 16 snaps are much more widely used, being supported not only in Ubuntu Core 16 but also classic Ubuntu Xenial (desktop and server) and more recently even Trusty! It&amp;rsquo;s also supported across a range of other Linux distributions.</description><author>kyrofa's blog</author><pubDate>Thu, 08 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/how-to-use-snapcraft-v2-on-trusty/</guid></item><item><title>Spaced Out - CS148 Ray tracing Project</title><link>https://blog.varunramesh.net/posts/spaced-out-cs148-raytracing-project/</link><description>A write-up for my CS 148 ray tracing image.</description><author>Varun Ramesh's Blog</author><pubDate>Wed, 07 Jun 2017 08:40:00 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/spaced-out-cs148-raytracing-project/</guid></item><item><title>Anki and Memorization with Spaced Repetition Software</title><link>https://josh.works/anki-spaced-repetition-system</link><description>&lt;p&gt;&lt;em&gt;This is not meant to be read in isolation. Memorization is almost useless without doing work ahead of time to grasp the material. For the full context, start with &lt;a href="/learning-how-to-learn"&gt;Learning how to Learn&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ve not been able to find any comprehensive guides to using Anki to learn &lt;em&gt;programming&lt;/em&gt;, so this article is a deep-dive on just that topic, from installation and configuration to building good programming-related flashcards.&lt;/p&gt;

&lt;p&gt;We’ll cover a few pieces:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="#anki-srs"&gt;What is Anki, and Spaced Repetition Software?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#two-primary-benefits"&gt;Why would you use it?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#getting-started-your-first-card"&gt;Getting started: Your first card&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#configure-anki-on-your-phone"&gt;Configure Anki on your phone&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#markdown-and-anki"&gt;Markdown and Anki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#install-markdown-package"&gt;Install Markdown Package&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#using-the-markdown-package"&gt;Using the Markdown package&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#building-programming-related-flashcards"&gt;Building a good first programming-related flashcard&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id="anki-spaced-repetition-software"&gt;Anki Spaced Repetition Software&lt;/h1&gt;

&lt;p&gt;Anki has been one of my favorite tools I’ve encountered in the last few years. I started using it initially for learning Spanish vocabulary, but as I started learning programming, it really started to shine.&lt;/p&gt;

&lt;p&gt;Anki is a flashcard application that attacks the issue of “memory decay” to retain and strengthen recall of anything you want.&lt;/p&gt;

&lt;h3 id="spaced-repetition-software"&gt;Spaced Repetition Software&lt;/h3&gt;

&lt;p&gt;If you learn something today, you might remember it tomorrow, but will probably forget it in three or four days. However, if you review it before you forget it, it’ll “stick” in your head for a bit longer than it did the first time you learned it. This “forgetting curve” can be bent exponentially in your favor.&lt;/p&gt;

&lt;p&gt;Here’s how remembering (and forgetting) over time tends to play out:&lt;/p&gt;

&lt;p&gt;&lt;img alt="the famous forgetting curve, from Wired Magazine" src="/images/ff_wozniak_graph_f.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;The goal here is to create relevant, well-formatted bits of knowledge, and then get them in Anki and review it the minimum amount of times to ensure that we’ll remember it for a very, very long time. (I.E. so long I can never forget it, so several years, at least)&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img alt="Anki's unassuming UI" src="/images/17-05-16-anki.jpg" title="Anki's unassuming user interface" /&gt;&lt;/p&gt;

&lt;p&gt;On first blush, Anki has an unassuming user interface.&lt;/p&gt;

&lt;p&gt;Continuing the example from &lt;a href="/learning-how-to-learn"&gt;learning how to learn&lt;/a&gt;, here’s the ‘front’ of one of my flashcards:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Anki card for using OmniAuth to manage user session" src="/images/17-05-16-anki_1.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This card looks complicated, but it’s actually easy&lt;/em&gt;. You’ll notice that I basically gave myself the answer in the question setup. I’m simply training myself to recognize how I set up the &lt;code class="language-plaintext highlighter-rouge"&gt;User&lt;/code&gt; class, and that it has a class method &lt;code class="language-plaintext highlighter-rouge"&gt;from_omniauth&lt;/code&gt;, and building a mental model of how I use &lt;code class="language-plaintext highlighter-rouge"&gt;request.env["omniauth.auth"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;the answer is:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;if user = User.from_omniauth(request.env["omniauth.auth"])&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And I prefer easy flashcards (more work to make, less difficult to recall) than difficult flashcards.&lt;/p&gt;

&lt;p&gt;For Anki’s basics, go check out this excellent guide: &lt;a href="https://www.fluentin3months.com/spaced-repetition/"&gt;Spaced Repetition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I put all sorts of information in Anki. At the moment I have about &lt;strike&gt;850&lt;/strike&gt; 1200+ programming-related cards, which covers &lt;em&gt;many&lt;/em&gt; topics related to software development.&lt;/p&gt;

&lt;p&gt;I’ve got cards related to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ruby and Rails&lt;/li&gt;
  &lt;li&gt;Linux terminal commands and their options, like &lt;code class="language-plaintext highlighter-rouge"&gt;grep&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;xargs&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Git/Github&lt;/li&gt;
  &lt;li&gt;JavaScript&lt;/li&gt;
  &lt;li&gt;HTML/CSS&lt;/li&gt;
  &lt;li&gt;SQL&lt;/li&gt;
  &lt;li&gt;Regular Expressions&lt;/li&gt;
  &lt;li&gt;iTerm &amp;amp; Atom keyboard shortcuts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am confident that I have &lt;em&gt;not&lt;/em&gt; found the ideal workflow around creating and memorizing Anki cards. I’m still trying to improve this process, but the benefit of using Anki far outweighs for me any cost of having less-than-perfect cards.&lt;/p&gt;

&lt;p&gt;My Anki workflow has two steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make the Anki cards on my laptop&lt;/li&gt;
  &lt;li&gt;Review the Anki cards on my phone&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I can review my Anki cards anywhere. In line at the grocery store, in the bathroom (yes), on a train, while I’m waiting for my food to microwave, etc.&lt;/p&gt;

&lt;p&gt;I normally hate to be the person staring at his phone all day, but since I’m usually on Anki, I now embrace it.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://play.google.com/store/apps/details?id=pt.aguiar.phoneusage"&gt;PhoneUsage&lt;/a&gt; I spend between 30 and 45 minutes on Anki review per day, and it’s all in little snippets of time grabbed here and there. (&lt;a href="/growth/2016/07/04/three-android-apps-i-use-every-day-and-maybe-youll-use-them-too/"&gt;a bit about how I manage my phone usage every day here&lt;/a&gt;)&lt;/p&gt;

&lt;h2 id="two-primary-benefits"&gt;Two primary benefits&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Cool, Josh, all this sounds nice, but it is a lot of work, especially to spend 30 minutes or an hour every day building and reviewing note cards. I’m busy, and if I’m learning programming, I’ll be even more busy than I am now.&lt;/p&gt;

  &lt;p&gt;Why is Anki better than just studying a topic more?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="1-the-process-of-recalling-answers-from-memory-solidifies-subtle-but-important-details"&gt;1. The process of recalling answers from memory solidifies subtle-but-important details&lt;/h3&gt;

&lt;p&gt;There are lots of small-but-meaningful details we encounter when trying to make computers do our bidding.&lt;/p&gt;

&lt;p&gt;The presence of a comma in a list of arguments, or if a method is a class or instance method, or if that &lt;code class="language-plaintext highlighter-rouge"&gt;git reset&lt;/code&gt; command uses &lt;code class="language-plaintext highlighter-rouge"&gt;--HARD&lt;/code&gt; as an argument - these all can introduce tiny bits of friction in our goals. I see a lot of what I am memorizing as not necessarily just learning &lt;em&gt;new&lt;/em&gt; things, but making sure that the things I &lt;em&gt;have&lt;/em&gt; learned, I know very well.&lt;/p&gt;

&lt;p&gt;For example, if you’re not sure how the params of a &lt;code class="language-plaintext highlighter-rouge"&gt;post&lt;/code&gt; request are formatted, once you’ve built and memorized a few cards related to this formatting, you can better access elements in that hash because you already know the basic structure to expect.&lt;/p&gt;

&lt;p&gt;Alternatively, are you 100% sure of the format for building a &lt;code class="language-plaintext highlighter-rouge"&gt;.reduce&lt;/code&gt; iterator? What’s the difference between &lt;code class="language-plaintext highlighter-rouge"&gt;[].reduce() do |result, item|&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;[].reduce({}) do |result, item|&lt;/code&gt;? With a few note cards on building/using the &lt;code class="language-plaintext highlighter-rouge"&gt;reduce&lt;/code&gt; method, you’ll spot the difference immediately, and know how to reason about it.&lt;/p&gt;

&lt;p&gt;These are &lt;em&gt;subtle but important details&lt;/em&gt;. Remember - computers are not that smart, they’re just extremely literal. Details make or break everything you build.&lt;/p&gt;

&lt;h3 id="2-this-memorization-functions-as-a-progress-capture-device-for-new-things-you-learn"&gt;2. This memorization functions as a progress-capture device for new things you learn&lt;/h3&gt;

&lt;p&gt;How often do you use a new method, or try to implement a basic feature, and you are &lt;em&gt;positive&lt;/em&gt; you’ve encountered the topic before, but cannot remember what you actually did?&lt;/p&gt;

&lt;p&gt;You’re off to the docs, or looking at previous projects, until you refresh your memory.&lt;/p&gt;

&lt;p&gt;This is fine, and even with Anki you’ll be regularly referencing documentation and prior code, but you’ll do it much less, because so much of what you’ve seen before you’ve memorized. It’s just sitting in your brain, ready to be used again.&lt;/p&gt;

&lt;p&gt;Sometimes, even though I’ve memorized cards, I cannot quite reproduce the whole chunk of knowledge from scratch, so I just open up the Anki and find the card that relates to the thing I’m trying to do. It’s a bit like keeping detailed notes and always knowing exactly where to find the relevant information for what you’re looking for.&lt;/p&gt;

&lt;p&gt;Or, that one time I had to rename a branch in Git - what was the exact syntax for pushing the deleted branch? Did I actually &lt;em&gt;rename&lt;/em&gt; the branch, or did I use the &lt;code class="language-plaintext highlighter-rouge"&gt;git branch -m&lt;/code&gt; command to create a &lt;em&gt;new&lt;/em&gt; branch? (hint - the next step is &lt;code class="language-plaintext highlighter-rouge"&gt;git push origin :old_branch_name&lt;/code&gt;, then push the new one with &lt;code class="language-plaintext highlighter-rouge"&gt;git push origin --set-upstream origin new_branch&lt;/code&gt;. I just opened up Anki to check the steps. Super simple.)&lt;/p&gt;

&lt;h1 id="installing-anki"&gt;Installing Anki&lt;/h1&gt;

&lt;p&gt;Download the desktop app at &lt;a href="https://apps.ankiweb.net/#download"&gt;https://apps.ankiweb.net&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Download it, install it, and open it up.&lt;/p&gt;

&lt;h1 id="getting-started-your-first-card"&gt;Getting started: Your first card&lt;/h1&gt;

&lt;p&gt;Make a new deck. Call it “programming” or “test deck” or whatever. Now click the “new card” button.&lt;/p&gt;

&lt;p&gt;Lets create a sample card. Don’t worry, you’re doing to delete this card in a minute, so it doesn’t matter if it’s “good” or whatever.&lt;/p&gt;

&lt;p&gt;In the box labeled “front”, put “what is my name”. On the “back” put your actual name. Or perhaps a more relevant question, like:&lt;/p&gt;

&lt;p&gt;Front:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Who writes the most long-winded and rambling blog posts in the world, and embarrassingly refers to himself in the third person every now and again?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Back:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Josh Thompson&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Make two or three cards. It will be easiest to see how Anki works with more than one card in the deck.&lt;/p&gt;

&lt;p&gt;Now, lets review your cards. Hit the “Study now” button, and think hard about the answer to the first card.&lt;/p&gt;

&lt;p&gt;For purposes of explanation, lets say you cannot remember either your name or my name. Admit defeat, and click the “show answer” button.&lt;/p&gt;

&lt;p&gt;Since you couldn’t remember, click the left-most button on the bottom, that says &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;10m, Again&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This button is how you signal to Anki that you didn’t know the answer, and the card will immediately be re-queued for you to study within the next ten minutes.&lt;/p&gt;

&lt;p&gt;Once you click the button, the next card will show up. Lets say you &lt;em&gt;do&lt;/em&gt; know the answer to this question. Click “show answer”, and then click the button labeled “good”.&lt;/p&gt;

&lt;p&gt;You’ve got three options when you’ve recalled the right answer. They are labeled “hard”, “good”, and “easy”. Depending on which one you click, the time that will elapse between now and when you see the card again will change.&lt;/p&gt;

&lt;p&gt;If the answer was hard for you, you want to see the card again soon. If it was easy, you’d like it to be a longer period of time before seeing it again.&lt;/p&gt;

&lt;p&gt;Depending on how many times you’ve reviewed the card, the time intervals associated with the card will change.&lt;/p&gt;

&lt;p&gt;Here’s the intervals I am seeing on some of the cards I’ve reviewed today:&lt;/p&gt;

&lt;p&gt;&lt;img alt="forty day range" src="/images/2018-06-28_memorizing_programming_01.jpg" title="a range of a month" /&gt;&lt;/p&gt;

&lt;p&gt;If I click the “Hard” button, I’ll see it again in 12 days. If I click easy, I’ll see it in almost 29 days.&lt;/p&gt;

&lt;p&gt;I tend to click the default “good” button, and thats what I did with this one.&lt;/p&gt;

&lt;p&gt;Here’s another, older card, where I can decide if I want to see it again in six months, 11 months, or 14 months:&lt;/p&gt;

&lt;p&gt;&lt;img alt="seven month range" src="/images/2018-06-27_memorizing_programming_03.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;You’ll get a feel for how this works, and what are the best answers for you, as you go.&lt;/p&gt;

&lt;p&gt;The next step is to hook up Anki and your phone&lt;/p&gt;

&lt;h2 id="configure-anki-on-your-phone"&gt;Configure Anki on your phone&lt;/h2&gt;

&lt;p&gt;Since you’ll be &lt;em&gt;building&lt;/em&gt; cards on your computer, but most likely &lt;em&gt;reviewing&lt;/em&gt; them on your phone, we’ll go ahead and get Anki working on your phone.&lt;/p&gt;

&lt;p&gt;Download the phone app:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.ichi2.anki&amp;amp;hl=en"&gt;Anki for Android&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://itunes.apple.com/us/app/ankimobile-flashcards/id373493387?mt=8&amp;amp;ign-mpt=uo%3D4"&gt;Anki for iPhone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;The iPhone app costs $25. The Android app is free, the iPhone app is not. $25 seems like a lot. The author explains this price &lt;a href="https://anki.tenderapp.com/kb/anki-ecosystem/why-does-ankimobile-cost-more-than-a-typical-mobile-app"&gt;here&lt;/a&gt;. According to my phone’s stats, I’ve spent 96 hours of active flashcard review time with Anki at the time of this writing, which boils down to $0.25/hr. I consider this to be an extremely good use of my time and money. Look for the value, not the cost.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id="createsign-in-to-your-ankiweb-account"&gt;Create/sign in to your AnkiWeb account&lt;/h3&gt;

&lt;h4 id="1-sign-up-for-a-new-ankiweb-account"&gt;1. &lt;a href="https://ankiweb.net/account/register"&gt;Sign up for a new AnkiWeb account&lt;/a&gt;&lt;/h4&gt;

&lt;h4 id="2-sign-into-your-ankiweb-account-on-the-desktop-anki-application"&gt;2. Sign into your AnkiWeb account on the desktop Anki application&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;get screenshot of what it looks like not signed in to an account&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the desktop application, hit the “sync” button:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Sync Desktop app with AnkiWeb" src="/images/2018-06-27_memorizing_programming_04.jpg" title="sync desktop with Anki Web" /&gt;&lt;/p&gt;

&lt;h4 id="3-sign-in-on-the-phone-application"&gt;3. Sign in on the phone application.&lt;/h4&gt;

&lt;p&gt;For Android, you’ll the following, in this order:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tap the hamburger menu&lt;/li&gt;
  &lt;li&gt;Tap “Settings”&lt;/li&gt;
  &lt;li&gt;Tap “AnkiDroid general settings”&lt;/li&gt;
  &lt;li&gt;Tap “Sign In to account”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;lt;sign in, need pictures from different account&amp;gt;&lt;/p&gt;

&lt;p&gt;Now hit the “Sync” button on your phone:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;phone screenshot here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And you should see the info from your desktop showing up on your phone!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Take a deep breath. This is a big accomplishment, and you’re most of the way done with getting configured on Anki!&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="markdown-and-anki"&gt;Markdown and Anki&lt;/h2&gt;

&lt;p&gt;Since we’re doing &lt;em&gt;programming&lt;/em&gt; related flash cards, and one of the first rules of formulating knowledge is “specificity”, we want code snippets in Anki to look like code snippets on our computer.&lt;/p&gt;

&lt;p&gt;Lets say you want to make an Anki flashcard related to the placement of this &lt;code class="language-plaintext highlighter-rouge"&gt;begin&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;rescue&lt;/code&gt; in this chunk of code:&lt;/p&gt;

&lt;p&gt;&lt;img alt="code snippet" src="/images/2018-06-03_memorizing_programming_01.jpg" title="a picture of some code" /&gt;&lt;/p&gt;

&lt;p&gt;Which of these cards do you think would be more effective for learning?&lt;/p&gt;

&lt;p&gt;Option one:&lt;/p&gt;

&lt;p&gt;&lt;img alt="ineffective card" src="/images/2018-06-03_memorizing_programming_02.jpg" title="a less-effective format" /&gt;&lt;/p&gt;

&lt;p&gt;Option two:&lt;/p&gt;

&lt;p&gt;&lt;img alt="more effective code" src="/images/2018-06-03_memorizing_programming_03.jpg" title="a more-effective format" /&gt;&lt;/p&gt;

&lt;p&gt;The second option is much, much more readable and understandable.&lt;/p&gt;

&lt;p&gt;To format your code like this, you’ll need to install (and use) a Markdown package.&lt;/p&gt;

&lt;h2 id="install-markdown-package"&gt;Install Markdown Package&lt;/h2&gt;

&lt;p&gt;We will be using the &lt;a href="https://ankiweb.net/shared/info/1030875226"&gt;Auto Markdown&lt;/a&gt; package.&lt;/p&gt;

&lt;h4 id="1-add-the-markdown-package-to-anki"&gt;1. Add the Markdown package to Anki&lt;/h4&gt;

&lt;p&gt;Navigate through the following menu, and entering the number &lt;code class="language-plaintext highlighter-rouge"&gt;1030875226&lt;/code&gt; when it’s requested. (The number is the end of the URL of the package we want.)&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Desktop &amp;gt; Tools &amp;gt; Add-ons &amp;gt; browse and install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="How to add packages" src="/images/2018-06-28_memorizing_programming_02.jpg" title="How to add packages" /&gt;&lt;/p&gt;

&lt;p&gt;When you click the &lt;code class="language-plaintext highlighter-rouge"&gt;Browse &amp;amp; Install&lt;/code&gt; button, just enter &lt;code class="language-plaintext highlighter-rouge"&gt;1030875226&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="adding the markdown add-on" src="/images/2020-04-28_memorizing_programming_03.jpg" title="adding the markdown add-on" /&gt;&lt;/p&gt;

&lt;h4 id="2-restart-anki-per-the-instructions"&gt;2. Restart Anki, per the instructions&lt;/h4&gt;

&lt;h4 id="3-enable-the-new-markdown-package-in-basic-card-types"&gt;3. Enable the new Markdown package in &lt;code class="language-plaintext highlighter-rouge"&gt;Basic&lt;/code&gt; card types&lt;/h4&gt;

&lt;p&gt;Check the “Enable Markdown” button. (It’s very buried):&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Anki &amp;gt; Tools &amp;gt; Manage Note Types &amp;gt; Basic&lt;/code&gt; and click &lt;code class="language-plaintext highlighter-rouge"&gt;Fields&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="configure fields" src="/images/anki_edit_fields.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Next, for both the front and the back of the card, check the &lt;code class="language-plaintext highlighter-rouge"&gt;Convert to/from markdown automatically&lt;/code&gt; box:&lt;/p&gt;

&lt;p&gt;&lt;img alt="enable automarkdown" src="/images/2020-04-28-enable_auto_markdown.jpg" /&gt;&lt;/p&gt;

&lt;h4 id="4-restart-anki-again"&gt;4. Restart Anki again&lt;/h4&gt;

&lt;h2 id="using-the-markdown-package"&gt;Using the Markdown package&lt;/h2&gt;

&lt;p&gt;Markdown is great. I use it constantly. In fact, this entire post is composed in Markdown - all of my text formatting, code blocks, links, and images are written in Markdown.&lt;/p&gt;

&lt;p&gt;If you don’t know Markdown, &lt;em&gt;you can ease into using Anki by learning to use Markdown&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start with something basic - using fixed-width color offset to draw attention to technical language.&lt;/p&gt;

&lt;h3 id="backticks-to-make-text-formatted-and-fixed-width"&gt;Backticks to make text &lt;code class="language-plaintext highlighter-rouge"&gt;formatted and fixed-width&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;“Visual hierarchy” is a huge way to help the human eye differentiate the important from the unimportant, or between things of different types.&lt;/p&gt;

&lt;p&gt;Here’s two was to write the same question. This is a question I asked someone on my team recently:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;what value do you use for SIDEKIQ_PORT in config/application.yml?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compare that with:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;what value do you use for &lt;code class="language-plaintext highlighter-rouge"&gt;SIDEKIQ_PORT&lt;/code&gt; in &lt;code class="language-plaintext highlighter-rouge"&gt;config/application.yml&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The one with the text formatting is easier to understand. Lets extend this principle to building programming-related flashcards.&lt;/p&gt;

&lt;p&gt;Imagine an Anki card that says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;what does array.sort do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can draw a little more attention to the specifics of the question (it’s about an Array, and it’s an instance method!) by using:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What does Array#sort do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that doesn’t catch the eye nearly as well as:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What does &lt;code class="language-plaintext highlighter-rouge"&gt;Array#sort&lt;/code&gt; do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, to off-set text like that, you just “wrap” it in backticks, the key to the left of the &lt;code class="language-plaintext highlighter-rouge"&gt;1&lt;/code&gt; on your keyboard.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is what text that’s been &lt;code class="language-plaintext highlighter-rouge"&gt;wrapped in backticks&lt;/code&gt; looks like&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Important note: This markdown package has a super annoying bug in it. I couldn’t figure out the fix at the code level for everyone, but if you have your mac in “dark mode”, the markdown formatting will look HORRIBLE! &lt;a href="https://github.com/gregorrr/anki-auto-markdown/issues/14#issuecomment-613490187"&gt;here’s an open github issue and the fix&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, make a card like this in Anki:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Anki card to learn some markdown" src="/images/2020-04-28-anki-monospaced.gif" /&gt;&lt;/p&gt;

&lt;p&gt;What makes text &lt;code class="language-plaintext highlighter-rouge"&gt;monospaced&lt;/code&gt;? backticks!&lt;/p&gt;

&lt;p&gt;Make a few more cards. For example, figure out how to make a large block of pre-formatted text, or give a block of code language-specific syntax highlighting.&lt;/p&gt;

&lt;p&gt;(You can use &lt;code class="language-plaintext highlighter-rouge"&gt;ruby&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;javascript&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;html&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;css&lt;/code&gt;, pretty much any language name and get appropriate syntax highlighting)&lt;/p&gt;

&lt;p&gt;&lt;img alt="language-specific syntax highlighting" src="/images/2020-04-28-anki-syntax-highlighting.gif" /&gt;&lt;/p&gt;

&lt;h1 id="building-programming-related-flashcards"&gt;Building programming-related flashcards!&lt;/h1&gt;

&lt;p&gt;Wahoo! You’ve almost made it! The end goal is in sight!&lt;/p&gt;

&lt;p&gt;I’d recommend keeping two points in mind before proceeding:&lt;/p&gt;

&lt;h4 id="1-go-slow"&gt;1. Go slow&lt;/h4&gt;

&lt;p&gt;I have a cap for ten new cards a day, even if I make twenty flashcards. Experiment with what works for you, but swamping yourself with cards makes it less likely that you’ll stick with the tool.&lt;/p&gt;

&lt;p&gt;Here’s how to set the maximum number of new cards a day. I would set it to about seven:&lt;/p&gt;

&lt;p&gt;&lt;img alt="seven new cards/day" src="/images/anki_set_new_card_limit.gif" /&gt;&lt;/p&gt;

&lt;h4 id="2-build-multiple-cards-around-each-discrete-piece-of-knowledge-you-want-to-acquire"&gt;2. Build multiple cards around each discrete piece of knowledge you want to acquire.&lt;/h4&gt;

&lt;p&gt;If you want to remind yourself of how to use &lt;code class="language-plaintext highlighter-rouge"&gt;.map&lt;/code&gt; in Anki, make three or five different flashcards, testing it from different directions.&lt;/p&gt;

&lt;p&gt;For example, card 1 might be:&lt;/p&gt;

&lt;p&gt;Front:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;What method can I call on an array to iterate through each item, 
and it returns the mutated array?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Back:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Array.map
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Card 2:&lt;/p&gt;

&lt;p&gt;front:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;what do I call to add 1 to each number?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&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="mi"&gt;3&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="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;back:&lt;/p&gt;
&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;=&amp;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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;Card 3:&lt;/p&gt;

&lt;p&gt;Front:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;letters = ['lkj', 'kwidk', 'wwid888']

What's a one-liner to make all above letters capitalized, so that:

big_letters = ["LKJ", "KWIDK", "WWID888"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Back:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;big_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LKJ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"KWIDK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"WWID888"&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;Next, read a bunch of these articles below, and go forth and prosper!&lt;/p&gt;

&lt;p&gt;Oh, and if you’re like me and love using &lt;em&gt;screenshots&lt;/em&gt; in Anki, go for it! I use &lt;a href="https://itunes.apple.com/us/app/annotate-capture-and-share/id918207447?mt=12"&gt;Annotate.app&lt;/a&gt;, but any tool will work. Make your screenshot, and drag it into Anki, and it’ll be ready to use.&lt;/p&gt;

&lt;h3 id="resources-on-memorization"&gt;Resources on Memorization&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.supermemo.com/en/articles/20rules"&gt;Effective learning: Twenty rules of formulating knowledge&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.fluentin3months.com/spaced-repetition/"&gt;Spaced repetition: Never forget vocabulary ever again (in the context of language learning, but perfectly applicable to programming)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://sivers.org/srs"&gt;Memorizing a programming language using spaced repetition software&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.jackkinsella.ie/articles/janki-method"&gt;JANKI METHOD: Using spaced repetition systems to learn and retain technical knowledge.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://ankiweb.net/shared/info/162313389"&gt;Markdown code formatting in Anki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.gwern.net/Spaced%20repetition"&gt;Spaced Repetition&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://rs.io/anki-tips/"&gt;Anki tips&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.wired.com/2008/04/ff-wozniak/"&gt;Wired Magazine: Want to Remember Everything You’ll Ever Learn? Surrender to This Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Tue, 06 Jun 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/anki-spaced-repetition-system</guid></item><item><title>Acquired taste</title><link>http://dimitarsimeonov.com/2017/06/06/acquired-taste</link><description>&lt;p&gt;Do you think of yourself as a self-inflicted masochist? I doubt it.
Yet, I bet you are quite often acting as a such.  Give me a few
minutes and I’ll find a few things that hurt you, but you keep on
doing.  You might be drinking alcohol or caffeine, or taking other
drugs, mindlessly shopping, getting really stressed about things you
can’t change, or smearing hot sauce all over your take-out food which
you don’t like.&lt;/p&gt;

&lt;p&gt;We all do such things. But they are not natural. Have you heard of a
teenager who, when they first tried alcohol liked the taste?
Nope. That’s because it is an acquired taste. It actually tastes bad,
but our minds play tricks on us and convince us over time that it is a
precursor to fun times, and we keep on having it.&lt;/p&gt;

&lt;p&gt;It’s quite easy to get addicted to such masochistic habits. Take
Sriracha, or other hot sauces for example. Even if you claim that
alcohol might have some delayed pleasure, hot sauce does
not. Capsaicin, the active ingredient in chilli peppers, just burns
our mouths and cause pain. Yet, people use it all the time.&lt;/p&gt;

&lt;p&gt;It’s an acquired taste. It might only give pain, but that pain is
able, even for a moment, to disconnect you the rest of your life, and
the other unhappy things in it. That’s why. It’s not the amount of
pain, it’s the variety in pain. A little bit of variety in pain makes
it easier to bear. So our minds learn to associate that chilli with
feeling better, but after a while it doesn’t actually help us feel
better. It just becomes a normalized part of our other pain.&lt;/p&gt;

&lt;p&gt;That’s how we get tricked into acquiring new tastes. We experience
some benefit, and get addicted. But then the benefit goes away, and
the addiction remains. We are so fucking gullible.&lt;/p&gt;

&lt;p&gt;Of course, society doesn’t mind our gullibility. Why should it. As
others take advantage of our naivete, they get to profit. That drives
society and keeps money around. Advertising and promotion play a large
role in planting those new acquired tastes in our minds, and it’s just
so easy. Have you ever seen an advertisement of a tasty sandwitch on
the TV, or nice picture of Tiramisu in the restaurant menu and thought
“Dang, I could take a bite of this now, even though I’m full”. Then
you know what I’m talking about.&lt;/p&gt;

&lt;p&gt;Once we acquire a taste, it is harder to not act as a baloon, swayed
easily by the lightest of winds. If your willpower and self-confidence
are lighter than air, then you become a pawn to the rest of
society. The rest of society will use you for their own benefit, and
it’s all your fault. Because you’re the baloon.&lt;/p&gt;

&lt;p&gt;The opposite of a baloon is the air-bender. A good air-bender will
shape their environment in a way that doesn’t push them in an unwanted
direction. That can get them protected from society’s craze, but could
also get them isolated in the long run. A really powerful air-bender
will be able to shift the direction of society, and cause a wind of
change.&lt;/p&gt;</description><author>D13V</author><pubDate>Tue, 06 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/06/06/acquired-taste</guid></item><item><title>SQLAlchemy: Mapping &amp;amp; Reflection</title><link>https://www.wints.org/notes/2017.06.06/</link><description>&lt;p&gt;&lt;a href="https://www.reddit.com/r/Python/comments/45spup/using_sqlalchemy_and_pandas_to_create_a_database/"&gt;Using Pandas and SQLAlchemy to create a database for your Flask App&lt;/a&gt;
&lt;a href="https://jeffknupp.com/blog/2015/07/12/flask-and-sqlalchemy-magic/"&gt;Flask and SQLAlchemy Magic&lt;/a&gt;
&lt;a href="https://gist.github.com/scaryguy/6269293"&gt;Change Primary Key&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dug deeper into pushing a pandas dataframe into a postgres database via sqlalchemy.&lt;/p&gt;
&lt;p&gt;The main situation I&amp;rsquo;m running into is that a postgres table created from a pandas dataframe using the &lt;em&gt;to_sql&lt;/em&gt; method &lt;strong&gt;does not&lt;/strong&gt; specifiy a Primary Key.
There is no way to specify a primary key using that method, as of now.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Tue, 06 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.06/</guid></item><item><title>On Learning</title><link>https://josh.works/learning-how-to-learn</link><description>&lt;p&gt;As a student at Turing, I’ve recently been thinking about learning how to learn, specifically in the context of software development.&lt;/p&gt;

&lt;p&gt;I am a bit hyperactive when it comes to trying to learn new things. Over the years, I’ve done plenty of ineffective learning, and at least a little bit of &lt;em&gt;effective&lt;/em&gt; learning. The good news is that even as I’ve not learned most of the topics I’ve originally set out to learn, I have learned a bit about &lt;em&gt;learning&lt;/em&gt;. (Does this make it “metalearning”?)&lt;/p&gt;

&lt;p&gt;I’m defining “learning” or “learning a topic” as &lt;em&gt;to be able to rearrange or reorganize or reuse the idea or pieces of the idea in new ways to resolve unstructured problems I face&lt;/em&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;This “rearranging/reorganizing” and “unstructured problems” explicitly &lt;em&gt;excludes&lt;/em&gt; the kind of learning most of us have done when we were young, where we just tried to have the right answer for fill-in-the-blank questions like “In _____(year) Christopher Columbus sailed the ocean blue”.&lt;/p&gt;

&lt;h2 id="overview-of-process"&gt;Overview of Process&lt;/h2&gt;

&lt;p&gt;All things worth doing should fit into some sort of process. If there’s no process, I’m just shooting in the dark, hoping to hit something. That said, the right process is almost always not the first thing I try, and I’m usually skeptical of “expert advice”, for many reasons. So, I like to try to pick a reasonable starting point, and experiment with process from there.&lt;/p&gt;

&lt;p&gt;Additionally, even a loosely-defined process reduces friction to attempting the thing. If, every time I came across a difficult concept in programming, I had to decide how to approach learning it, I’d waste time and energy deciding how to learn the thing.&lt;/p&gt;

&lt;p&gt;But, since I have a process, as imperfect as it is, I can just say “ah, a hard thing. Time to attack it with my six-step process to learning difficult things”.&lt;/p&gt;

&lt;p&gt;I’ve been thinking about friction, and learning, and the relationship between the two, for quite some time. For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="/make-hard-things-easier-by-removing-friction"&gt;Make hard things easy by removing friction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s my &lt;em&gt;current&lt;/em&gt; iteration of “how to learn difficult things”&lt;/p&gt;

&lt;h2 id="steps-to-try-to-learn-something"&gt;Steps to try to learn something&lt;/h2&gt;

&lt;h3 id="1-define-the-boundaries-of-the-topic"&gt;1. Define the boundaries of the topic&lt;/h3&gt;

&lt;p&gt;If you want to learn &lt;strong&gt;Software development&lt;/strong&gt;, that has no boundaries.&lt;/p&gt;

&lt;p&gt;If you want to learn &lt;strong&gt;Session management in conjunction with OmniAuth&lt;/strong&gt;, you can actually figure out what you need to learn. It’s better-bounded.&lt;/p&gt;

&lt;p&gt;The more specific I can be about what I am trying to learn, the better I can approach the process. I also always try to find the smallest viable chunk of the topic, and start there. So even session management with OmniAuth is contingent upon having a notion of how session management works, so I would start with just understanding sessions, and THEN move to OAuth, and THEN move to OmniAuth, and THEN roll everything together.&lt;/p&gt;

&lt;h3 id="2-find-a-way-to-play-with-the-component-pieces"&gt;2. Find a way to play with the component pieces.&lt;/h3&gt;

&lt;p&gt;One of my end goals of learning is to build an accurate mental map of the process. I need to be able to visualize how the pieces fit together, and what each piece is composed of. In a REPL session, I would spend a few minutes “playing” with the object that OmniAuth returns in the user is authenticated.&lt;/p&gt;

&lt;p&gt;For example, the core piece of OmniAuth comes back to the requesting service inside of &lt;code class="language-plaintext highlighter-rouge"&gt;request.env&lt;/code&gt;, which is a HUGE hash. So, after looking at it, I can figure out that the OmniAuth hash is at &lt;code class="language-plaintext highlighter-rouge"&gt;request.env["omniauth.auth"]&lt;/code&gt;. That hash contains all the user details, a &lt;code class="language-plaintext highlighter-rouge"&gt;uid&lt;/code&gt;, and more.&lt;/p&gt;

&lt;p&gt;(With the Omniauth example above, the “object” that comes back from a successfully logged in user can be accessed in the &lt;code class="language-plaintext highlighter-rouge"&gt;request&lt;/code&gt;. So, I’d look at the &lt;code class="language-plaintext highlighter-rouge"&gt;request&lt;/code&gt; object, the &lt;code class="language-plaintext highlighter-rouge"&gt;request.env&lt;/code&gt; object, the &lt;code class="language-plaintext highlighter-rouge"&gt;request.env["omniauth.auth"]&lt;/code&gt;, object, &lt;code class="language-plaintext highlighter-rouge"&gt;request.env["omniauth.auth"].keys&lt;/code&gt;, and examine each of the sub-pieces.)&lt;/p&gt;

&lt;h3 id="3-write-down-on-real-dead-trees-the-component-pieces-of-the-process"&gt;3. Write down, on real dead trees, the component pieces of the process.&lt;/h3&gt;

&lt;p&gt;At a low level, this is actual code blocks, and once I get the individual pieces (for example, using a &lt;code class="language-plaintext highlighter-rouge"&gt;from_omniauth(auth_params)&lt;/code&gt; method with &lt;code class="language-plaintext highlighter-rouge"&gt;first_or_create_by&lt;/code&gt; to query my &lt;code class="language-plaintext highlighter-rouge"&gt;users&lt;/code&gt; database) I’ll then write out the associated piece of code next to it. So, if I’m moving between a &lt;code class="language-plaintext highlighter-rouge"&gt;user&lt;/code&gt; model and &lt;code class="language-plaintext highlighter-rouge"&gt;sessions&lt;/code&gt; controller, I’ll write both code blocks side by side. I can easily add in the related routes and views, and anything else that fits into the process along side.&lt;/p&gt;

&lt;p&gt;Something that is important to me is having pens of two colors at hand, and using one color for all my text, and the other one to draw arrows between things.&lt;/p&gt;

&lt;p&gt;The arrows are the core piece of finding and identifying &lt;em&gt;relationships&lt;/em&gt; inside my code, and accross files, so I think it’s pretty important.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Some of my OmniAuth notes" src="/images/17-05-18-omniauth_1.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;The process of writing code out, by hand, helps me identify the many wrong assumptions I make about the code as I am reading it. It’s critical to me, but most people don’t take these sorts of paper notes, so I might be an outlier. Everyone in the class is learning the same stuff, and learning it well.&lt;/p&gt;

&lt;h3 id="4-write-down-again-at-a-higher-level-the-involved-pieces"&gt;4. Write down again, at a higher level, the involved pieces.&lt;/h3&gt;

&lt;p&gt;At this point, I might just be writing down the involved object types, and their associated methods. I.E. I am for a “cheat cheet” of notes that I can look at and refresh my entire knowledge of the topic. This means instead of individual code blocks, I might list the flow or progression of the code execution through the application, noting what are the involved files and pieces.&lt;/p&gt;

&lt;p&gt;For user authentication, it will touch:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;routes&lt;/li&gt;
  &lt;li&gt;Sessions controller&lt;/li&gt;
  &lt;li&gt;User model&lt;/li&gt;
  &lt;li&gt;user database&lt;/li&gt;
  &lt;li&gt;Possibly a service&lt;/li&gt;
  &lt;li&gt;a view or twoÂ&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I capture each of these pieces on paper. This way I’ve got a detailed and higher-level mental model of what is happening.&lt;/p&gt;

&lt;h3 id="5-get-a-few-reps-of-implementation"&gt;5. Get a few “reps” of implementation.&lt;/h3&gt;

&lt;p&gt;If I was following a tutorial, I’ll delete the work I just did and implement again, without referring to anything but my paper notes. (This is a sanity check to make sure I captured the right information on paper. Often I’ve not caught enough, so I modify my notes.)&lt;/p&gt;

&lt;h3 id="6-capture-some-of-the-high-and-low-level-details-in-anki"&gt;6. Capture some of the high and low level details in Anki.&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;This section was getting longer and longer, so I split it into it’s own post. &lt;a href="/anki-spaced-repetition-system"&gt;Read on about memorization and spaced repetition software here –&amp;gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;After working through these steps, I can usually say I’ve attained my goal of learning the topic. If I have not learned the topic, I’ve probably bitten off more than I can chew, and should revisit my original learning goal.&lt;/p&gt;

&lt;p&gt;I’ve certainly have not learned everything about the given topic, but I have a mental framework on which I can hang further learning, &lt;em&gt;and&lt;/em&gt; I can take the low and high-level knowledge and either apply it in other similar projects, or recognize the patterns of others using it in their projects.&lt;/p&gt;

&lt;p&gt;My goal is to get the minimum effective dose of learning so I can move on, but not lose what I’ve just spent a while working on.&lt;/p&gt;

&lt;p&gt;The notes and implementation practice helps me learn the thing, and Anki keeps me from losing it, so it’s quick to bring to mind weeks and months later.&lt;/p&gt;

&lt;p&gt;Full disclosure - this is a time consuming and difficult process. I don’t do it every day, though I wish I did. To buckle down on a topic like this necessarily requires NOT attending to other topics I could be studying. Life is full of trade-offs, but in general I’d rather learn one thing well than four things poorly.&lt;/p&gt;

&lt;h3 id="resources"&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.amazon.com/Mind-Numbers-Science-Flunked-Algebra/dp/039916524X"&gt;Mind for Numbers (book)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.fullerton.edu/LearningAssistance/Review-and-Summary-of-A-Mind-for-Numbers.pdf"&gt;Detailed summary of the above book&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=""&gt;Deep Work (book)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=""&gt;Peak: The Science of Human Achievement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://codewithoutrules.com/2017/04/17/learning-without-a-mentor/"&gt;Learning without a Mentor: how to become an expert programmer on your own&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Mon, 05 Jun 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/learning-how-to-learn</guid></item><item><title>Simplifying Classes, Cleaner Interface</title><link>https://www.wints.org/notes/2017.06.05/</link><description>&lt;p&gt;I did some restructuring today. Figured out that the best approach would be to keep all my main objects in the sps.py file.&lt;/p&gt;
&lt;p&gt;So I deleted database.py and moved it into a &lt;strong&gt;Database&lt;/strong&gt; class in the sps module.
I create a Scraper object and a Database object to use.
Now it&amp;rsquo;s a cleaner interface, yay.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;import sps

scraper = sps.Scraper()

database = sps.Database()

report = scraper.inventory_report()

database.add_report(report)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Keep it as simple as possible, until I&amp;rsquo;m forced to bring in complexity.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 05 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.05/</guid></item><item><title>Write Simple Code to Prevent Headaches Later</title><link>https://benovermyer.com/blog/2017/06/write-simple-code-to-prevent-headaches-later/</link><description>&lt;p&gt;Consider the following code snippet:&lt;/p&gt;
&lt;pre class="giallo" style="color: #F8F8F2; background-color: #282A36;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;someVar = false;&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;if ( anotherVar &amp;gt;= 1 ) {&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt; someVar = true;&lt;/span&gt;&lt;/span&gt;
&lt;span class="giallo-l"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, consider this rewrite:&lt;/p&gt;
&lt;pre class="giallo" style="color: #F8F8F2; background-color: #282A36;"&gt;&lt;code&gt;&lt;span class="giallo-l"&gt;&lt;span&gt;someVar = ( anotherVar &amp;gt;= 1 );&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both snippets work as designed, so why is the second one better? It comes down to simplicity. The first snippet includes an &lt;em&gt;if&lt;/em&gt; block. It would be possible for another programmer to add logic into that block that, while not modifying the final result of &lt;em&gt;someVar&lt;/em&gt;, increases the complexity of the code. This makes it harder to maintain in the long run. The second snippet is very clear about what it does, and is more difficult to tack additional logic onto.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Mon, 05 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2017/06/write-simple-code-to-prevent-headaches-later/</guid></item><item><title>Continuous acceptance tests for complex applications</title><link>https://kyrofa.com/posts/continuous-acceptance-tests-for-complex-applications/</link><description>So you&amp;rsquo;re developing a complex application. Maybe it has some really specific dependencies, or requires a lot of setup. In many cases (such as my own), it&amp;rsquo;s a web application. I have a suite of tests, varying all the way from unit tests through integration tests. The latter typically uses Selenium, and I often integrate it with Sauce Labs. I&amp;rsquo;ve written an article about this before. However, even those integration tests aren&amp;rsquo;t testing the real application: it&amp;rsquo;s not running against a production database, it&amp;rsquo;s not running with a production web server, and so on.</description><author>kyrofa's blog</author><pubDate>Mon, 05 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/continuous-acceptance-tests-for-complex-applications/</guid></item><item><title>Why you should buy an old arcade machine</title><link>https://jasoneckert.github.io/myblog/why-you-should-buy-an-old-arcade-machine/</link><description>&lt;p&gt;Why on earth would anyone want to buy a video game the size of a refrigerator?!?&lt;/p&gt;
&lt;p&gt;The simple answer: It’s the best bang for your buck!&lt;/p&gt;
&lt;p&gt;Since the dawn of video games in the 1970s, video game makers have been all about making as much money as they can.  Today, a game console will cost you about $500, and the games anywhere from $40-80 each on top of it. - if you go the Nintendo route, expect to sink just as much if not more.  A gaming PC is even more expensive, and the games will run you even more than console games when you get hooked.  Mobile gaming is somewhat inexpensive if you don’t mind seeing plenty of ads, and don’t spend money to unlock the cool features of each game (a marketing technique called micro-transactions). It’s big business, and you don’t get good gameplay value, even if you spend all day playing the games.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Mon, 05 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/why-you-should-buy-an-old-arcade-machine/</guid></item><item><title>A simple, powerful self-hosted git setup</title><link>https://alanpearce.eu/post/self-hosted-git/</link><description>I describe my git server setup (using cgit and gitolite), and what it allows</description><author>Alan Pearce</author><pubDate>Sun, 04 Jun 2017 13:33:02 GMT</pubDate><guid isPermaLink="true">https://alanpearce.eu/post/self-hosted-git/</guid></item><item><title>Waiting screen UX in Mediatemple</title><link>https://yasha.solutions/waiting-screenmediatempleuxjustanexample/</link><description>justSomeUX is a series where I share some interesting UX / UI and smart copy for your inspiration (and my archive of references).
 Media Temple is a web hosting company – at the high-end spectrum – I mean they are pretty good – both in service and in functionalities and options for hosting your site.
But… I just created a site on it the other day and they had a super cool UX trick for their waiting screen.</description><author>Yasha Solutions</author><pubDate>Sun, 04 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/waiting-screenmediatempleuxjustanexample/</guid></item><item><title>2017-06-04</title><link>https://ho.dges.online/pictures/2017-06-04/</link><description/><author>ho.dges.online</author><pubDate>Sun, 04 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-06-04/</guid></item><item><title>Zombies</title><link>https://venam.net/blog/unix/2017/06/04/zombies.html</link><description>You check your processes and see some hanging around with a weird status and using no resources. You don't know if you should remove them or not. Then you try removing them and it doesn't work.  In this episode we're going to discuss zombie processes.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/zombies.html</guid></item><item><title>WM &amp;amp; DE</title><link>https://venam.net/blog/unix/2017/06/04/wm-de.html</link><description>We've had a previous episode discussing xcb, x11, wayland, all about display servers.  I've said in the beginning of the episode that it would not be about window managers.  Well, today folks we're going to do just that.  This one is going to be about window managers and desktop environments.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/wm-de.html</guid></item><item><title>Green on black?</title><link>https://venam.net/blog/unix/2017/06/04/why-green-on-black.html</link><description>The idea of green text on black background comes from the "Green screens" aka monochrome monitors.  It was nicknamed Green screen even though the monochrome monitor came in many other different colors other than green.  A monochrome monitor is a monitor that only has one color, as the name implies. It was used before color screens were invented in the early days of computing, from 60s till the 80s, as a successor to the teletype terminal, which was a typewriter, with papers connected to a machine.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/why-green-on-black.html</guid></item><item><title>Shells</title><link>https://venam.net/blog/unix/2017/06/04/unix-shells.html</link><description>What's a shell, what does it do, why would we need that?  A shell is a program that acts as an intermediary between the user and the operating system, the kernel.  It lets you execute commands on a computer.  Specifically, on Unix, the shell is a command-line interface, a prompt that waits for commands entered by the user, interpret and execute them, and when its done, prompts again for a new command.  It stays in this state that we call REPL, read evaluate print loop, or interpreter.  All that while hiding the details of how it did it.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/unix-shells.html</guid></item><item><title>Unix philosophy</title><link>https://venam.net/blog/unix/2017/06/04/unix-philosophy.html</link><description>Understanding the Unix philosophy and what makes a Unix system Unixy.  Let the good discussion flow, let all arguments and ideas be put down on the table.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/unix-philosophy.html</guid></item><item><title>Terminals</title><link>https://venam.net/blog/unix/2017/06/04/terminals.html</link><description>We spend so much time typing at a terminal and yet the underlying mechanisms and history behind it are often overlooked.  The TTY is an integral part of Unix, and we take most of its behavior for granted even though it has a huge history baggage that it carries to this day.  For instance pressing control-C or control-Z to stop or put in the background a process, or using control-A to go to the beginning of the line.  You might think that the control-A comes from the EMACS keybinds but it doesn't, it's the opposite, the EMACS keybinds are inspired by the TTY.  In this episode we're going to dive in the world of terminals.  A big, rough, and unhoned overview of this part of Unix.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/terminals.html</guid></item><item><title>Unix system calls</title><link>https://venam.net/blog/unix/2017/06/04/system-calls.html</link><description>System calls are one subject that scares many people.  Actually most of the low level stuffs happening on the operating system scares a lot of people.  I admit, I was a bit afraid of dealing with this subject.  Not because it's hard or anything but because it's something that we're not used to dealing with every day, it's like a hidden magic spell.  I was also afraid of dealing with this subject because I thought I could make mistakes while explaining it and giving other people false assumptions about the mechanism of their Unix operating systems.  But that's ok...  We'll explain everything slowly.  In this podcast we're discussing system calls on Unix operating systems, it's going to be a quick overview of what's happening there.  If you're someone that hardly know anything about them then it's the episode you need to listen to.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/system-calls.html</guid></item><item><title>Special Files</title><link>https://venam.net/blog/unix/2017/06/04/special-files.html</link><description>Everything is a file, right.  Files on Unix have no specific format, nothing is imposed about how they should be, and there's no need to incorporate anything specific for them to be files.  There's no file type, all the files are the same.  But that's not really true.  There are two differentiations.  One is at a higher level, a meta level, using mimetypes which we discussed in an earlier episode about default programs. You can listen to it to get a small overview.  The other difference is at a lower level, and that's what we're going to discuss.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/special-files.html</guid></item><item><title>Ricing</title><link>https://venam.net/blog/unix/2017/06/04/ricing.html</link><description>We've had an episode about display servers and libraries, and then we had another episode about window managers and desktop environments, and so the next logical step is to do one about ricing and customization.  This is what we're going to do today in the company of xero, neeasade, and halfwit.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/ricing.html</guid></item><item><title>Newcomers</title><link>https://venam.net/blog/unix/2017/06/04/newcomers.html</link><description>What would you say or give as advice to newly unix users. What is there first to dabble with.  Today we're discussing advices and tips you'd like to tell newcomers. Remember the first time you laid your hands on a Unix box, most probably you were lost, just like most people. Now that you've got some experience with Unix in general what would you tell yourself from the past.  Guests, thlst, abhx/stark</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/newcomers.html</guid></item><item><title>Making the best CLI</title><link>https://venam.net/blog/unix/2017/06/04/making-the-best-cli.html</link><description>Unix is known for its set of small command line utilities. What are your ideas and features for the best CLI programs. What makes a complete utility.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/making-the-best-cli.html</guid></item><item><title>Licenses on Unix</title><link>https://venam.net/blog/unix/2017/06/04/licenses.html</link><description>The world of licenses is the legal world, a world where the literal meaning of words is important and where all the crevasses are exploited.  I'm not a lawyer, nor have I studied laws, and whatever I say will be based on what I understood from my reading.  In this episode we're going to do a small overview of the topic of licenses on Unix. But beware, a "small" overview in the legal world is quite heavy!</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/licenses.html</guid></item><item><title>Fonts on Unix</title><link>https://venam.net/blog/unix/2017/06/04/fonts-on-unix.html</link><description>Understanding how the fonts work on Unix isn't simple. I had never thought when starting this research that this field was this deep. Not only is it overwhelming, but the information around the subject is also not easily digestable.  The last two weeks I've been researching this and in this podcast you'll barely find but the essential. It's still skimming the surface of the topic. If I explain something in a wrong manner, be sure to correct me in the extended podcast discussion thread.  The people that truly understand the full font stack can be counted on one's hand, I'd like to salute those true heroes. They deserve respect. And if they had an anthem I would've played it at the beginning of this episode.  So yes, we're going to discuss fonts.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/fonts-on-unix.html</guid></item><item><title>File hierarchy</title><link>https://venam.net/blog/unix/2017/06/04/filesystem.html</link><description>Files, the predominant representation of everything on Unix, how are they scattered around?</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/filesystem.html</guid></item><item><title>Unix executables</title><link>https://venam.net/blog/unix/2017/06/04/executables.html</link><description>An executable is something that causes a computer to perform some tasks according to encoded instructions.  It's in opposition to a data file which must be parsed by another program to be meaningful, for example an image or video.  The instructions are usually in machine code, read by the cpu and so dependent on the cpu architecture.  An executable once compiled will only work on a particular family of processor because the machine code instruction differs within the families of processors. It also differs depending on the hardware, let's say the GPU.  An exception to this are the fat binaries which include the code for multiple hardwares in a single binary. It makes it bigger though, obviously.  There aren't many implementations of this in the Unix world but the most relevant example are the OSX and ios binaries, which are architecture independant, they are fat binaries, which explains why their binaries are huge.  We've said the instructions were in machine code but more generally they can be in any format, interpreted and reconstituted into bytecode by a scripting language or a middle man program that will do just in time compilation or anything else so that the machine understands.  An emulator for example, java bytecode is also a good take.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/executables.html</guid></item><item><title>Environment Variables</title><link>https://venam.net/blog/unix/2017/06/04/environment-vars.html</link><description>A set of dynamic values, helper or configuration values, that can affect the way a process runs.  Usually it's the process that queries those values, they are part of its "environment" and consequently the name.  They are there so that the process can know the suitable values of the system it's running on.  They are metadata, so to say.  For example, the temporary location to store temporary files, or the home directory.  This defintion is vague, the implementation could be done in a lot of ways.  What's really an environment variable... Well, this isn't clear. Are those environment variables respected, forced? Also, this isn't a clear thing.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/environment-vars.html</guid></item><item><title>Daemons on Unix</title><link>https://venam.net/blog/unix/2017/06/04/daemons.html</link><description>You've certainly heard of daemons, those processes that lurk in the background and do what they're supposed to do. You might even have written and run programs that are daemons.  Today we'll talk about them, those daemons ({day,dee}mon), what there is to know about their mechanism and details. A big generic overview of daemons on Unix.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/daemons.html</guid></item><item><title>Browsers</title><link>https://venam.net/blog/unix/2017/06/04/browsers-on-unix.html</link><description>Browsers, your windows to the WWW What do you use, customize, the problems you've stumbled upon, how we're using those browsers in the Unix world, the most used browsers, why we use them, and all the problems we've encountered I'm venam and you're listening to. The nixers podcast</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/browsers-on-unix.html</guid></item><item><title>Booting On Unix</title><link>https://venam.net/blog/unix/2017/06/04/booting-on-unix.html</link><description>At the beginning of time there was nothing...  But that all depends on your definition of nothingness, what is nothingness...  A power button is pressed, and suddenly BIG BANG... After a while, you get a Unix login prompt.  Have you ever wondered what led to this, what happened behind the scenes from the time you pressed the power button until this prompt appears?  In this episode we're discussing the boot process and what is specific to Unix about it.  I'm venam and you're listening to the Nixers podcast.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/booting-on-unix.html</guid></item><item><title>Bits and words</title><link>https://venam.net/blog/unix/2017/06/04/bits-and-words.html</link><description>The topics in this episode are fairly simple, even basic, but I'd like to tackle them from a different perspective.  The information in a computer is represented in binary form. For them the bit is the basic unit of this information. Bits are binary, and binary means that there can only be two states, or it's the first or the second state, nothing else.  The CPU has some built-in commands to manipulate a fix set of those bits.  The set of bits with a fixed size for a processor, that this processor is designed to handle at a time, is called a word. This varies between processors.  Because of how tied and low level binary operations are, they are operations directly supported by the cpu, they are faster than higher level abstractions and consume less memory space. For this reason it is sometimes chosen, at the sake of clarity, by some programmers as a data structure.  We're going to discuss some topics related to words and some usages of bitwise operations in Unix.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sun, 04 Jun 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2017/06/04/bits-and-words.html</guid></item><item><title>Counting in your head</title><link>https://honza.pokorny.ca/2017/06/counting-in-your-head/</link><description>&lt;p&gt;I was born and raised in the Czech Republic.  I learned to speak English and
French in school.  When I was 19, I moved out of the country and have been
living in English-speaking countries ever since.  Gradually, I have been losing
the ability to speak my native language.  This is especially obvious in
professional settings (work, bank, government offices, etc) since I learned to
be an adult while living in the UK.  At this point, when speaking to strangers I
feel much more comfortable speaking English.  Even though my English is far from
perfect.&lt;/p&gt;
&lt;p&gt;One thing that I have found over the years is that no matter how comfortable you
get with another language, you will still count things in your head in your
mother tongue.  Counting coins, or scoops, or sheep, or anything.  I am unable
to count things quickly in English.  Somehow the brain isn&amp;rsquo;t able to work on
keeping the count in memory while incrementing the number once a second.
Sequential numbers must have been burned into my mind at an early age and thus
enjoy special treatment.&lt;/p&gt;
&lt;p&gt;Are you bilingual?  Do you experience this, too?&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Sat, 03 Jun 2017 19:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/06/counting-in-your-head/</guid></item><item><title>Nonsense and Sensibility</title><link>https://one.mikro2nd.net/pages/nonsense-and-sensibility/</link><description>Come In, Number Five, your time is up! Hear the terrible and tragic cry of the grammarnazi. Feel pity for the nitpicking OC attentions of your inner copy-editor. C&amp;rsquo;mon, you know you have one in there.
Reach out and touch someone in the head. There&amp;rsquo;ll come a time, don&amp;rsquo;t know where, don&amp;rsquo;t know when &amp;mdash; perhaps when Kurzweil&amp;rsquo;s Singularity comes around &amp;mdash; which, in my ever-so-jumbled opinion, will be a couple of centuries after The Rapture of the Christians &amp;mdash; a time when we&amp;rsquo;ll be able to transmit thoughts, emotions, sensations and memories direct from one sentient brain to another, but for now&amp;hellip; for now we&amp;rsquo;re stuck with words.</description><author>one mikro2nd</author><pubDate>Sat, 03 Jun 2017 16:24:11 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/nonsense-and-sensibility/</guid></item><item><title>ADOT Campaign – Words kills War – adspiration</title><link>https://yasha.solutions/adot-campaign-words-kills-war-adspiration/</link><description>adspiration is a series of post where I store interesting ads campaign for the purpose of documenting and referencing how we communicate ideas and concepts</description><author>Yasha Solutions</author><pubDate>Sat, 03 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/adot-campaign-words-kills-war-adspiration/</guid></item><item><title>if it is free, you are [not] the product</title><link>https://yasha.solutions/if-it-is-free-you-are-not-the-product/</link><description>_“If it is free, you are the product” _
This statement is an easy shot.
Google, Facebook, Twitter, etc. are free because they use our data.
Therefore we are bound to agree to this fact or simply close our social account and disconnect from the rest of the world.But is it really true?
Can we never see anything offered for free that is not perverted at its core?
It is not what you think The usual argument says : “Free for the users, means that you have to pay with your privacy and the reason for it is that since you are not willing to pay for the service, then somebody has to – hence advertisers“.</description><author>Yasha Solutions</author><pubDate>Sat, 03 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/if-it-is-free-you-are-not-the-product/</guid></item><item><title>Vintage ads for modern products – youtube facebook twitter adspiration</title><link>https://yasha.solutions/vintage-ads-facebook-youtube-adspiration/</link><description>adspiration is a series of post where I store interesting ads campaign for the purpose of documenting and referencing how we communicate ideas and concepts
The following is an a series of print ads realised for Maxi Media – around the topic – “everything age fast”
Youtube Vintage Ad  Skype Vintage Ad  Twitter Vintage Ad  Facebook Vintage ad</description><author>Yasha Solutions</author><pubDate>Sat, 03 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/vintage-ads-facebook-youtube-adspiration/</guid></item><item><title>Pandas with SQLAlchemy (and Postgres)</title><link>https://www.wints.org/notes/2017.06.02/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
More mental contortions today to understand how sqlalchemy, pandas and database sessions fit together.
I got the data into postgres finally, but without cleaning it. But still, &lt;em&gt;phew&lt;/em&gt;, it works.&lt;/p&gt;
&lt;h5 id="modules-organization"&gt;Modules Organization &lt;a href="#modules-organization"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;In the &lt;code&gt;sps&lt;/code&gt; package, I have:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;__init__.py
database.py
models.py
stoneland.py
utils.py
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;__init__.py&lt;/strong&gt;
I moved all the functions into utils.py so here it&amp;rsquo;s just initializing logging and importing all relevant modules.
I will need to clean this up to make a nice API to the package. It&amp;rsquo;s very messy right now.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 02 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.02/</guid></item><item><title>Owl Poem by Caroline Bird</title><link>https://ho.dges.online/words/commonplace/owl-poem-by-caroline-bird/</link><description>&lt;p&gt;![[2022-02-07-002.jpg]]&lt;/p&gt;
&lt;p&gt;I refuse to write about an owl,&lt;br /&gt;
Better to write about a person with an owl,&lt;br /&gt;
Or a person who wants an owl, or better still,&lt;br /&gt;
A person who hates owls and will never&lt;br /&gt;
Have an owl.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Fri, 02 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/owl-poem-by-caroline-bird/</guid></item><item><title>Hamlet</title><link>https://apurva-shukla.me/bookshelf/hamlet/</link><description>⭐ ⭐ ⭐ ⭐ ⭐ An intensely meaningful reflection over the nature of humanity and ontology.</description><author>Apurva Shukla's RSS Feed</author><pubDate>Thu, 01 Jun 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/hamlet/</guid></item><item><title>Database Sessions and User facing API</title><link>https://www.wints.org/notes/2017.06.01/</link><description>&lt;p&gt;&lt;a href="http://newcoder.io/scrape/part-4/"&gt;Newcoder Scraping (Part 4)&lt;/a&gt;
&lt;a href="http://docs.sqlalchemy.org/en/latest/orm/session_basics.html"&gt;SQLAlchemy Session Basics&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I struggled with structuring database sessions in my python program.
Reading through a few articles and tutorials on SQLAlchemy best practices, and studying Kenneth Reitz&amp;rsquo;s fantastic &lt;a href="https://github.com/requests/requests"&gt;requests&lt;/a&gt; library, I realize I want a clean interface to the package.
Kenneth does this by having an &amp;ldquo;api&amp;rdquo; module that wraps/uses the underlying classes/objects into neat little functions, so you can do &lt;code&gt;request.get(&amp;quot;https://www.google.com&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="modules"&gt;Modules &lt;a href="#modules"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;models.py&lt;/em&gt;
This contains all the database models created using sqlalchemy. It&amp;rsquo;s likely to change and evolve, so thought to best keep it separate from the database module.
I need to look into Alembic to handle migrations. As I understand it, I&amp;rsquo;ll need that for when the schema changes.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Thu, 01 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.06.01/</guid></item><item><title>What do you get out of Expo?</title><link>https://goshacmd.com/is-expo-worth-it/</link><author>Gosha Spark</author><pubDate>Thu, 01 Jun 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/is-expo-worth-it/</guid></item><item><title>Elephant Proofing Your Web Servers</title><link>https://blog.eutopian.io/elephant-proofing-your-web-servers/</link><description>750 words, 3 minutes. The Case For Default Deny What&amp;rsquo;s free, permanently reduces your exposure to a range of potential vulnerabilities, requires no maintenance, and takes only a few minutes to implement?
Most web servers are installed to serve content to unauthenticated users on the Internet. Most only have a finite list of URLs or a specific number of web apps. I&amp;rsquo;ve always thought it strange that they install in a default-permit mode.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 01 Jun 2017 00:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/elephant-proofing-your-web-servers/</guid></item><item><title>Node.js, Redis, and You! at RedisConf17</title><link>https://thomashunter.name/posts/2017-05-31-node-redis-and-you-redisconf17</link><author>Thomas Hunter II</author><pubDate>Wed, 31 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-05-31-node-redis-and-you-redisconf17</guid></item><item><title>Nothing is Something</title><link>https://www.wints.org/notes/2017.05.30/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I stumbled across &lt;a href="https://www.youtube.com/watch?v=29MAL8pJImQ"&gt;Sandi Metz&amp;rsquo;s talk&lt;/a&gt; a few days ago, and found time to watch it today. I&amp;rsquo;m no expert on Object Oriented design, so this was definitely an eye opener.&lt;/p&gt;
&lt;h4 id="take-aways"&gt;Take Aways &lt;a href="#take-aways"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Don&amp;rsquo;t use conditionals for checking for nil.
Don&amp;rsquo;t use inheritance to share code.
Learn that non-physical/non-traditional things can be modeled as objects.
Get into the habit of composing a class (object), then create other classes (roles) and inject them in other classes to modify specific behavior of the objects.
If a specific, default behavior is modified, make sure to define the default behavior as well.
Now you have a vanilla object with dependencies, and it&amp;rsquo;s arbitrary to define the default behavior or modify it.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Tue, 30 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.05.30/</guid></item><item><title>Workflow for developers (AKA My current tools)</title><link>https://josh.works/developer-workflow</link><description>&lt;p&gt;I’m a huge fan of “a good workflow”. Makes you think better.&lt;/p&gt;

&lt;p&gt;This is still under construction, but I’m fleshing out all the tools, tidbits, and other things that serve me well every day as I build my skills as a developer. It will always be a work in progress, but will hopefully serve others.&lt;/p&gt;

&lt;p&gt;Your workflow is more than just tools. It encompasses &lt;a href="/better-questions"&gt;how you ask questions&lt;/a&gt; and &lt;a href="/learning-how-to-learn"&gt;how you integrate new knowledge&lt;/a&gt;. This page will be a running list of tools and workflows that I use regularly.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;em&gt;Last updated 02/20/18. If you’re curious, version history &lt;a href="https://github.com/josh-works/josh-works.github.io/commits/master/_posts/2017-05-27-developer-workflow.md"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id="topics"&gt;Topics&lt;/h2&gt;

&lt;h3 id="small-desktopos-tweaks-misc-utilities"&gt;Small desktop/OS tweaks, misc utilities&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="#key-repeat-speed"&gt;max out “key repeat speed” and “min wait on key hold”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#see-more-code"&gt;See more code at once&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#alfred-for-clipboard-buffering"&gt;Smarter copy/pasting with Alfred: Clipboard buffering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#manage-your-windows"&gt;Moom/Spectacle: Window management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="iterm"&gt;iTerm&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="#split-panes"&gt;Split panes: &lt;code class="language-plaintext highlighter-rouge"&gt;cmd+d&lt;/code&gt;/&lt;code class="language-plaintext highlighter-rouge"&gt;cmd+shft+d&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#optimize-for-information"&gt;Optimize prompt for information&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#pulling-up-previous-commands"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;!foo&lt;/code&gt; pulls last command that started with &lt;code class="language-plaintext highlighter-rouge"&gt;foo&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#navigate-iterm-output-quickly"&gt;keybindings to allow quick cursor movement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#global-key-binding"&gt;global key binding to open iTerm from anywhere&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#reuse-current-working-directory-for-new-tabspanes"&gt;set new tabs/panes to open from current working directory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="atom"&gt;Atom&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="#useful-packages"&gt;Misc valuable (to me) packages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#splitting-screens-for-fun-and-profit"&gt;Split screens&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#new-lines-where-you-want-them"&gt;Insert new line above/below&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#find-all-the-things"&gt;Global Find&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="gitgithub"&gt;Git/Github&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="#use-a-staging-branch-for-group-work"&gt;on group projects that need a “stable” branch at all times - set default branch to “staging”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#pull-request-template"&gt;Use a PR template for fun and for profit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#always-merge-staging-into-your-branch-before-making-a-pull-request"&gt;Avoid merge conflicts by pulling in &lt;code class="language-plaintext highlighter-rouge"&gt;staging/master&lt;/code&gt; before making a PR&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#optimize-for-information"&gt;Display your current branch in terminal prompt&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="chromefirefox"&gt;Chrome/Firefox&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="#extensions"&gt;Chrome Extensions, like The Great Suspender, Vimium, etc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#shortcuts-for-chrome"&gt;Chrome shortcuts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="applications-some-free-some-not"&gt;Applications (some free, some not)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="#dash-documentation-that-doesnt-suck"&gt;Dash: offline (and instant) documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#alfred-do-anything-on-your-computer"&gt;Alfred w/Powerpack: do all the things&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#flux-save-your-eyes"&gt;Flux (free)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#browsing-securely-with-a-vpn"&gt;PIA (VPN)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id="desktopos-tweaks"&gt;Desktop/OS tweaks&lt;/h1&gt;

&lt;h3 id="key-repeat-speed"&gt;Key repeat speed&lt;/h3&gt;

&lt;p&gt;Holding down the delete key should delete text &lt;em&gt;quickly&lt;/em&gt;, and you shouldn’t have to wait a long time for it to start deleting text.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;System Preferences &amp;gt; Keyboard&lt;/code&gt;, max out key repeat speed, minimum delay until repeat:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Keyboard Settings" src="/images/17-05-29-tools_1.jpg" style="width: 450px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;h3 id="see-more-code"&gt;See More Code&lt;/h3&gt;

&lt;p&gt;Most of us are on Macbooks with retina screens. The default resolution of your mac doesn’t take advantage of this high-resolution capability.&lt;/p&gt;

&lt;p&gt;There’s a few different ways of showing the difference in resolution. I’ll show one way, but ultimately, you should experiment yourself with maxing out the resolution and then bumping up the text size as needed. This allows the less-important parts of your tools take up less space (like sidebars, navigation elements, etc) while leaving you more room for what matters. (Code, text)&lt;/p&gt;

&lt;p&gt;&lt;img alt="Keyboard Settings" src="/images/17-05-29-display_1.jpg" style="width: 650px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;p&gt;Compare the side bar in the first image to the one in the second. There’s about 25% more visible items. This is a win, in my book. Laptop screens are small enough.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Keyboard Settings" src="/images/17-05-29-display_2.jpg" style="width: 650px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;p&gt;Change your resolution under &lt;code class="language-plaintext highlighter-rouge"&gt;System Preferences &amp;gt; Displays &amp;gt; Built-in Retina Display&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Keyboard Settings" src="/images/17-05-29-display_3.jpg" style="width: 400px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;h3 id="alfred-for-clipboard-buffering"&gt;Alfred for clipboard buffering&lt;/h3&gt;

&lt;p&gt;Copy-paste makes the world go around. What if you want to copy two things to your clipboard, and then paste them both?&lt;/p&gt;

&lt;p&gt;Or what if you copied a URL, and then a few minutes later (and after putting more stuff on your clipboard) you decided you wanted that URL again?&lt;/p&gt;

&lt;p&gt;Enter “Clipboard buffering”. With Alfred’s &lt;a href="https://www.alfredapp.com/help/features/clipboard/"&gt;Clipboard Buffering tool&lt;/a&gt; (it’s not free), you can cycle back through items you’ve copied to your clipboard.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I use this tool many times a day&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-v&lt;/code&gt; is the system default for pasting from the clipboard, so I’ve mapped my Clipboard History toggle to &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-opt-v&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id="manage-your-windows"&gt;Manage your windows&lt;/h3&gt;

&lt;p&gt;We spend all day moving between programs and windows. Surprise surprise, there are some great tools for customizing how your desktop looks.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://manytricks.com/moom/"&gt;Moom&lt;/a&gt;, others use &lt;a href="https://www.spectacleapp.com/"&gt;Spectacle&lt;/a&gt;. I prefer Moom because it has a bit more customization, but it’s up to you. Both are free.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Moom defaults" src="/images/17-05-31-moom.jpg" style="width: 650px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;h4 id="spectacle-video"&gt;Spectacle video&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=uulWZVXOuxs&amp;amp;list=PLwJTr6-X6O0SX5YOVZx_c7GkZPOM-eTwN&amp;amp;index=1"&gt;Regis gives a great overview of using Atom and Spectacle shortcuts (YouTube)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id="iterm-1"&gt;iTerm&lt;/h1&gt;

&lt;p&gt;iTerm is powerful. It can also be intimidating, because it’s your window into the command line, github, and the dark depths of your machine. The more you can make it match your workflow, the less intimidating it will seem.&lt;/p&gt;

&lt;h3 id="split-panes"&gt;Split Panes&lt;/h3&gt;

&lt;p&gt;You can split your iTerm panes, similar to how you might split Atom.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-d&lt;/code&gt; splits iTerm vertically. &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-d&lt;/code&gt; splits it horizontally. I like to have all my windows related to a certain app under a single iTerm tab, so I might have two or three panes open, and when I want to see one pane better, I’ll hit &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-enter&lt;/code&gt; to expand the pane to fill the entire iTerm window.&lt;/p&gt;

&lt;p&gt;This is useful if I need to see a full stack-trace, or scroll back through server error messages. Once I’m done looking, I hit &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-enter&lt;/code&gt; again, and it shrinks back to its normal size.&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;cmd+shft+d splits iTerm2 horizontally. Cmd+d splits vertically. hello, Fibonacci sequence: &lt;a href="https://t.co/StnBubNoAU"&gt;pic.twitter.com/StnBubNoAU&lt;/a&gt;&lt;/p&gt;&amp;mdash; Josh Thompson (@josh_works) &lt;a href="https://twitter.com/josh_works/status/853240281411584001"&gt;April 15, 2017&lt;/a&gt;&lt;/blockquote&gt;


&lt;p&gt;(When you set this up, if you’ve not already, &lt;a href="#reuse-current-working-directory-for-new-tabs-panes"&gt;configure iTerm to open new tabs to your current working directory&lt;/a&gt;)&lt;/p&gt;

&lt;h3 id="optimize-for-information"&gt;Optimize for Information&lt;/h3&gt;

&lt;p&gt;Your terminal prompt is that little piece of text before your cursor that is visible pretty much all the time.&lt;/p&gt;

&lt;p&gt;You spend &lt;em&gt;all day&lt;/em&gt; looking at your terminal prompt, so it’s reasonable to ask it to work for you a bit.&lt;/p&gt;

&lt;p&gt;I have two &lt;em&gt;minimum&lt;/em&gt; recommendations:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Change the color of JUST the prompt, so is contrasted compared to the output next to it.&lt;/li&gt;
  &lt;li&gt;Set up Git tab-completion AND display the current git branch in the prompt&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id="compare-default-prompt-with-non-default"&gt;Compare default prompt with non-default&lt;/h4&gt;

&lt;p&gt;As an example, where in this block of text did I enter the next command?&lt;/p&gt;

&lt;p&gt;&lt;img alt="hard to find the prompt, eh?" src="/images/17-05-29-prompt_2.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Hint, it’s sorta in the middle, where it says &lt;code class="language-plaintext highlighter-rouge"&gt;bash-3.2$ curl josh.works&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Compare that to this version:&lt;/p&gt;

&lt;p&gt;&lt;img alt="easier to find the prompt now, methinks" src="/images/17-05-29-prompt_1.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;(Oops, shouldn’t be making changes on &lt;code class="language-plaintext highlighter-rouge"&gt;master&lt;/code&gt;…)&lt;/p&gt;

&lt;h4 id="configuration"&gt;Configuration&lt;/h4&gt;

&lt;p&gt;To set this all up, carefully follow Michael Hartl’s instructions on his &lt;a href="https://www.learnenough.com/git-tutorial#sec-prompt_branches_and_tab_completion"&gt;Learn Enough Git&lt;/a&gt; tutorial. That will give you tab completion and the current branch in your prompt.&lt;/p&gt;

&lt;p&gt;To change the color of your prompt, that’s a bit more of a hassle.&lt;/p&gt;

&lt;p&gt;Open up your &lt;code class="language-plaintext highlighter-rouge"&gt;~/.bashrc&lt;/code&gt;, and find the line that starts with &lt;code class="language-plaintext highlighter-rouge"&gt;PS1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It should have somewhere inside of it the code you just added per Michael Hartl’s tutorial. You need to update that line to the following:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;PS1='\[\e[0;32m\][\W$(__git_ps1 " (%s)")]$ \[\e[m\]'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This just adds color codes (and color code escapes, and a bunch of other color-related formatting) to your “Prompt String 1”. It’s voodoo, and will suck away hours of your life if you let it.&lt;/p&gt;

&lt;p&gt;I wrote about this topic in more detail here: &lt;a href="https://gist.github.com/josh-works/7f2e6c82d22dca6e9fbc029c8b17703d"&gt;Gist on Prompt customization&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="pulling-up-previous-commands"&gt;Pulling up previous commands&lt;/h3&gt;

&lt;p&gt;In iTerm, the up arrow cycles through previously entered commands.&lt;/p&gt;

&lt;p&gt;Just as useful, though, is filtering through this list. Imagine you ran &lt;code class="language-plaintext highlighter-rouge"&gt;rspec spec/features/sessions/guest_user_can_sign_up_spec.rb&lt;/code&gt;, all the tests passed, so you did your &lt;code class="language-plaintext highlighter-rouge"&gt;git add/commit/push&lt;/code&gt; workflow, and maybe some other stuff.&lt;/p&gt;

&lt;p&gt;Now you want to run that specific RSpec command again, but it might be many commands ago.&lt;/p&gt;

&lt;p&gt;If you type &lt;code class="language-plaintext highlighter-rouge"&gt;!rsp&lt;/code&gt; and hit &lt;code class="language-plaintext highlighter-rouge"&gt;enter&lt;/code&gt;, iTerm will find the last command that starts with &lt;code class="language-plaintext highlighter-rouge"&gt;rsp&lt;/code&gt;, and place it under your cursor. If you want to run it, hit &lt;code class="language-plaintext highlighter-rouge"&gt;enter&lt;/code&gt;. I use this &lt;em&gt;all the time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;(There’s more complex “interactive search” tools you can use, but the &lt;code class="language-plaintext highlighter-rouge"&gt;!command&lt;/code&gt; is a great starting point.)&lt;/p&gt;

&lt;h3 id="navigate-iterm-output-quickly"&gt;Navigate iTerm output quickly&lt;/h3&gt;

&lt;p&gt;Since the up arrow pulls up previous commands, to scroll back through your iTerm output one line at a time, hold down &lt;code class="language-plaintext highlighter-rouge"&gt;shift&lt;/code&gt; and hit &lt;code class="language-plaintext highlighter-rouge"&gt;up arrow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To scroll one page at a time, hold down &lt;code class="language-plaintext highlighter-rouge"&gt;shift + command&lt;/code&gt; and hit &lt;code class="language-plaintext highlighter-rouge"&gt;up arrow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get back to the bottom, let go of &lt;code class="language-plaintext highlighter-rouge"&gt;shift/command&lt;/code&gt; and hit the up or down arrow.&lt;/p&gt;

&lt;h3 id="global-key-binding"&gt;Global key binding&lt;/h3&gt;

&lt;p&gt;We use alt-tab all day long, but it’s imprecise. The order of the items that you cycle through with alt-tab depends on what you last used.&lt;/p&gt;

&lt;p&gt;I like being able to jump to important programs straight away.&lt;/p&gt;

&lt;p&gt;In &lt;code class="language-plaintext highlighter-rouge"&gt;preferences &amp;gt; keys &amp;gt; hotkey&lt;/code&gt; you can set a “system-wide hotkey”. I’ve got mine mapped to &lt;code class="language-plaintext highlighter-rouge"&gt;cmd+shift+i&lt;/code&gt; (&lt;code class="language-plaintext highlighter-rouge"&gt;i&lt;/code&gt; for “iTerm”), and it doesn’t conflict with any other bindings on my machine. I use it dozens of times a day.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Keyboard Settings" src="/images/17-05-30-iterm_1.jpg" style="width: 400px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;h3 id="reuse-current-working-directory-for-new-tabspanes"&gt;Reuse current working directory for new tabs/panes&lt;/h3&gt;

&lt;p&gt;Split panes are cool, but it’s a huge pain if it always opens a new tab to your root directory. You have to &lt;code class="language-plaintext highlighter-rouge"&gt;cd&lt;/code&gt; around just to get to where you want to be.&lt;/p&gt;

&lt;p&gt;The fix is easy. Set iTerm to use your “Present Working Directory” for new panes. When I’m pairing with other students, this is one of the first changes I recommend they make.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Keyboard Settings" src="/images/17-05-30-iterm_2.jpg" style="width: 400px; margin: 0 auto; display: block;" /&gt;&lt;/p&gt;

&lt;h3 id="misc"&gt;Misc&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=d3gujjfzAfw&amp;amp;list=PLwJTr6-X6O0SX5YOVZx_c7GkZPOM-eTwN&amp;amp;index=3"&gt;Regis’ iTerm tutorial (YouTube)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id="atom-1"&gt;Atom&lt;/h1&gt;

&lt;p&gt;I spend quite a bit of time in Atom every day. It’s a big piece to bite off, so I’m not going to go into too much depth, and will let others do most of the talking.&lt;/p&gt;

&lt;p&gt;Here’s some useful starting points if you’re getting up and running with Atom:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=uulWZVXOuxs&amp;amp;list=PLwJTr6-X6O0SX5YOVZx_c7GkZPOM-eTwN&amp;amp;index=1"&gt;Regis’ Atom/Spectacle shortcuts video&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://readwrite.com/2014/05/20/github-atom-5-tips-getting-started-tutorial-corey-johnson/"&gt;Atom getting started guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="useful-packages"&gt;Useful packages&lt;/h3&gt;

&lt;p&gt;Next, a few packages I like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://atom.io/packages/advanced-open-file"&gt;Advanced-open-file&lt;/a&gt;: Create new directories/files inside of Atom. No need to jump to your terminal.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://atom.io/packages/indent-guide-improved"&gt;indent-guide-improved&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://atom.io/packages/minimap"&gt;minimap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://atom.io/packages/multi-cursor"&gt;multi-cursor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="splitting-screens-for-fun-and-profit"&gt;Splitting Screens for fun and profit&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://flight-manual.atom.io/using-atom/sections/panes/"&gt;Split screens/panes and move between them&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="new-lines-where-you-want-them"&gt;New lines where you want them&lt;/h3&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-enter&lt;/code&gt; makes a new line under your cursor, and places your cursor there. &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-enter&lt;/code&gt; makes a new line above your cursor, also places your cursor there.&lt;/p&gt;

&lt;h3 id="find-all-the-things"&gt;Find all the things&lt;/h3&gt;

&lt;p&gt;Have you ever had a spelling error, but you’re not sure where in your project it is?&lt;/p&gt;

&lt;p&gt;You’re familiar with &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-f&lt;/code&gt;, or “find within document”. You should also use the related &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-f&lt;/code&gt;, or “find within project”. Atom will search your entire project (everything that is in the sidebar) for whatever criteria you give it.&lt;/p&gt;

&lt;p&gt;If you misspelled a method somewhere and don’t recall where, use global find to get find it.&lt;/p&gt;

&lt;p&gt;It’s got many, many uses. You’ll find them all.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id="gitgithub-1"&gt;Git/Github&lt;/h1&gt;

&lt;p&gt;Oh boy. Git. It’s the most amazing thing ever, but it can be intimidating.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Magical incantations" src="https://imgs.xkcd.com/comics/git.png" /&gt;&lt;/p&gt;

&lt;p&gt;Even professional developers are not completely at home with git. (I read a study about this, but now I can’t find it…)&lt;/p&gt;

&lt;p&gt;This is good news! This means as intimidating is Git may seem, we’re in good company. Any effort expended on better understanding Git will be well-spent.&lt;/p&gt;

&lt;p&gt;Many others have written about Git and how to use it far better than I ever could, so I’ll make just a few suggestions.&lt;/p&gt;

&lt;h3 id="use-a-staging-branch-for-group-work"&gt;Use a staging branch for group work&lt;/h3&gt;

&lt;p&gt;If you’ve got a group project and you need the &lt;code class="language-plaintext highlighter-rouge"&gt;master&lt;/code&gt; branch to always be stable (because Heroku is always running on it, or something) change the repo settings to make a branch besides master the default branch.&lt;/p&gt;

&lt;p&gt;Just make &lt;code class="language-plaintext highlighter-rouge"&gt;staging&lt;/code&gt; the default branch for your repo, and now all your PRs will (by default) be against this branch. This is perfect, because you might find yourself often squashing bugs when merging in other’s work, and it’s way better to hotfix bugs on something that is not &lt;code class="language-plaintext highlighter-rouge"&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id="pull-request-template"&gt;Pull Request Template&lt;/h3&gt;

&lt;p&gt;When we’re first starting, a good pull request is the last thing that is on our mind. We just wanna merge in our branch without merge conflicts.&lt;/p&gt;

&lt;p&gt;As soon as you start doing group work, though, the value of explaining to the rest of the team what you’re working on will rival the importance of the actual code that you’re writing.&lt;/p&gt;

&lt;p&gt;So, when you make a pull request, I’d strongly recommend getting in the habit of giving a summary of what the new code does, making a few other standard comments, and then also adding comments to your code, calling out interesting bits and pieces.&lt;/p&gt;

&lt;p&gt;This helps your learning, this helps their learning, and this habit will serve you well for the rest of your life.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/blog/2111-issue-and-pull-request-templates"&gt;It’s very easy to setup a PR template&lt;/a&gt;, and you’re welcome to copy the &lt;a href="https://github.com/josh-works/corkboard/tree/master/.github"&gt;PR template my group is using right now&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="consider-merging-staging-into-your-branch-before-making-a-pull-request"&gt;Consider merging &lt;code class="language-plaintext highlighter-rouge"&gt;staging&lt;/code&gt; into your branch before making a pull request&lt;/h3&gt;

&lt;p&gt;In group work, especially if you have a branch checked out for more than a few hours (or a day), it’s possible that the “base branch” will change between when you check out your branch, and when you want to merge it back in.&lt;/p&gt;

&lt;p&gt;It will be a great service to your team if, before making your pull request for your new feature, to fetch and merge the most recent version of staging, and then merge staging into your branch.&lt;/p&gt;

&lt;p&gt;THEN make your pull request. If you do this every time you make a PR, you should pretty much never have merge conflicts, and then you and the team don’t have to try to sort all that out when merging.&lt;/p&gt;

&lt;p&gt;Then, whenever &lt;code class="language-plaintext highlighter-rouge"&gt;staging&lt;/code&gt; is in good shape, and you want to update &lt;code class="language-plaintext highlighter-rouge"&gt;master&lt;/code&gt;, just merge &lt;code class="language-plaintext highlighter-rouge"&gt;staging&lt;/code&gt; to &lt;code class="language-plaintext highlighter-rouge"&gt;master&lt;/code&gt;, and you’re good to go!&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id="chrome"&gt;Chrome&lt;/h1&gt;

&lt;p&gt;You’ll spend a lot of time in your browser.&lt;/p&gt;

&lt;p&gt;There’s some keyboard shortcuts I use all the time for Chrome. Don’t try to use all at once, but test each one once or twice, decide if you like it, and then use it for a few days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt; I’ve recently migrated to Firefox, for a few reasons. All of the extensions and shortcuts are available in, and apply to, Firefox, so I’m leaving this section otherwise untouched. &lt;del&gt;I just wish Firefox had a hide/reveal bookmarks toolbar keyboard shortcut like Chrome.&lt;/del&gt; &lt;a href="/firefox-toggle-bookmark-bar-keyboard-shortcut"&gt;Here’s how to hide/reveal bookmarks by keyboard shortcut in Firefox&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="shortcuts-for-chrome"&gt;Shortcuts for Chrome&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-l&lt;/code&gt; puts the “focus” on the address bar. You can copy the address, paste a different one in, etc.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-[&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-]&lt;/code&gt; cycles left and right through your current tabs. (This tab movement works in Atom too!)&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-shift-c&lt;/code&gt; opens your “element selector” in your dev tools.&lt;/li&gt;
  &lt;li&gt;the above shortcut pairs well with &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-opt-i&lt;/code&gt;, which toggles your dev tools. I often hit the element selector shortcut, click the item I want to inspect, and then toggle dev tools closed again, all in a second or two.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cmd-w&lt;/code&gt; closes the current tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="extensions"&gt;Extensions&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/the-great-suspender/klbibkeccnjlkjkiokjodocebajanakg?hl=en"&gt;The Great Suspender&lt;/a&gt; will “put to sleep” inactive tabs. Chrome is a bit of a resource hog, and this seems to help it consume less energy.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en"&gt;Vimium&lt;/a&gt; gets you Vim-like navigation around your browser. I use it mostly to move up/down a page and to “click” links with the keyboard, but it can do much more than that.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en"&gt;uBlock Origin&lt;/a&gt; is so much more than an ad-blocker. I love it. &lt;a href="/take-back-your-attention"&gt;You can &lt;em&gt;delete&lt;/em&gt; unwanted elements from pages (like ads), too.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id="applications"&gt;Applications&lt;/h1&gt;

&lt;h3 id="dash-documentation-that-doesnt-suck"&gt;Dash: Documentation that doesn’t suck&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kapeli.com/dash"&gt;Dash&lt;/a&gt; is an application that lets you download documentation for just about anything with documentation. I regularly use docs for Ruby, Rails, HTML, CSS, Sass, JavaScript, MySQL, Redis, etc. With Dash, I don’t have to hop into a browser and google for things, because it’s already installed locally, and is searchable.&lt;/p&gt;

&lt;p&gt;It’s not free, but I find it worth it. (It has a free-to-use mode that makes you wait a short period of time before using it.)&lt;/p&gt;

&lt;h3 id="alfred-do-anything-on-your-computer"&gt;Alfred: Do anything on your computer&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.alfredapp.com/"&gt;AlfredApp&lt;/a&gt; is my favorite program on my computer, by miles. It replaces your “omnibar”, or whatever pops up when you hit &lt;code class="language-plaintext highlighter-rouge"&gt;cmd-space&lt;/code&gt;. Alfred’s workflows are where the real power shows.&lt;/p&gt;

&lt;p&gt;I use Alfred, a lot. Since Dec 29, 2014, I’ve used Alfred 59,510 times. That actually seems a bit low.&lt;/p&gt;

&lt;p&gt;I can’t give it a fraction of the praise it deserves, so here’s some “getting started with Alfred” guides that might convince you to give it a whirl.&lt;/p&gt;

&lt;p&gt;The powerpack extension is not free, but the base application is free. It’s a big step up from the default mac omnisearch thing.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.alfredapp.com/blog/tips-and-tricks/beginners-guide-to-alfred-searching-your-mac-and-the-web/"&gt;Beginners guide to Alfred&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://lifehacker.com/a-beginners-guide-to-mouseless-computing-with-alfred-1596198655"&gt;Lifehacker: Beginners guide to Alfred&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.maketecheasier.com/alfred-workflows-mac/"&gt;Some Starter Workflows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id="my-personal-favorite-workflows"&gt;My personal favorite workflows&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;First, I use Alfred to bind programs to “global hotkeys”&lt;/strong&gt;. I’ve got four global hotkeys, one each for: iTerm, Atom, Firefox, and Slack. (They’re &lt;code class="language-plaintext highlighter-rouge"&gt;cmd + shift + i|k|l|j&lt;/code&gt;, respectively.)&lt;/p&gt;

&lt;p&gt;This means I don’t use &lt;code class="language-plaintext highlighter-rouge"&gt;cmd + tab&lt;/code&gt; nearly as often, as I can quickly and confidently switch to whatever application I want. No guessing required. &lt;a href="https://www.alfredapp.com/help/workflows/triggers/hotkey/creating-a-hotkey-workflow/"&gt;Here’s a guide on setting up your own application-toggling workflows&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next, I use Alfred to do site-specific searches.&lt;/strong&gt; For example, at Wombat, we use Jira, and everything has a ticket number. Rather than be fumbling for bookmarks, or hand-editing URLs, I just set up a simple workflow to open a given ticket.&lt;/p&gt;

&lt;p&gt;I have at least seven site-specific search workflows. &lt;a href="https://www.alfredapp.com/help/features/web-search/#custom"&gt;Here’s how to set up your own custom search&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I open Alfred, type &lt;code class="language-plaintext highlighter-rouge"&gt;ts[tab]&lt;/code&gt;, enter the ticket number, and hit &lt;code class="language-plaintext highlighter-rouge"&gt;return&lt;/code&gt;. Boom. Ticket opens up in browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toggle VPN.&lt;/strong&gt; I use a VPN while working, but when I shut my computer I have to re-start the VPN when I open it back up.  &lt;a href="https://www.alfredforum.com/topic/191-workflow-for-vpn-services/"&gt;I use this workflow&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="flux-save-your-eyes"&gt;Flux: Save your eyes&lt;/h3&gt;

&lt;strike&gt;[Flux](https://justgetflux.com/) is a neat little utility that increases the "warmth" of your laptop screen at night. It will save you a bunch of eye strain.&lt;/strike&gt;
&lt;p&gt;Macs now have this built in with the &lt;a href="https://support.apple.com/en-us/HT207513"&gt;Night Shift&lt;/a&gt; feature.&lt;/p&gt;

&lt;h3 id="browsing-securely-with-a-vpn"&gt;Browsing securely with a VPN&lt;/h3&gt;

&lt;p&gt;Do you use coffee shop wifi? If so, especially once you’re working on someone else’s product, you should consider using a Virtual Private Network.&lt;/p&gt;

&lt;p&gt;It secures your traffic from snooping, even from others who are using the network, and the network provider itself. I’ve been using &lt;a href="https://www.privateinternetaccess.com/"&gt;PIA&lt;/a&gt; for two years (it’s ~$30/year) and am quite happy with it.&lt;/p&gt;

&lt;h1 id="master-your-tools"&gt;Master your tools&lt;/h1&gt;

&lt;p&gt;This list is simultaneously wide-ranging, and barely scratches the surface.&lt;/p&gt;

&lt;p&gt;I aim to always improve how I use my tools and my development environment, both out of respect for the “craft” of software development, and to minimize friction between me and the things I want to do.&lt;/p&gt;

&lt;p&gt;This list barely touches all of the tools and keyboard shortcuts and small workflow modifications I use, or anyone else uses, but I hope it might help get you on the same path to efficiency.&lt;/p&gt;

&lt;p&gt;My &lt;em&gt;opinion&lt;/em&gt; on the matter is a well-organized workspace and environment will free up cognitive resources to spend on the programming challenge at hand.&lt;/p&gt;

&lt;p&gt;I’m sensitive to friction, and anytime something seems like it’s too clunky to navigate or use, I expect that there’s a better way to do it.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Mon, 29 May 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/developer-workflow</guid></item><item><title>Sleep bookmarks</title><link>https://xenodium.com/sleep-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=15997016"&gt;Algorithmic Solution to My Insomnia (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gwern.net/Melatonin"&gt;Melatonin - Gwern.net&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://slatestarcodex.com/2018/07/10/melatonin-much-more-than-you-wanted-to-know"&gt;Melatonin: Much More Than You Wanted To Know | Slate Star Codex&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 29 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/sleep-bookmarks</guid></item><item><title>Attending PyCon US Development Sprints</title><link>https://blog.tafkas.net/2017/05/29/attending-pycon-us-development-sprints/</link><description>After three great days at the PyCon US 2017 in Portland, OR Hendrik and I decided to participate in the development sprints succeeding the conferece. The code sprints are an essential part of PyCon, and a chance to meet some of the maintainers and contributors of various open source projects. For us it was the first time attending a code sprint.
The day before the sprint there was a session helping people to set up Git, Python (including virtual environments) and getting familiar with version control.</description><author>Tafkas Blog</author><pubDate>Mon, 29 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/2017/05/29/attending-pycon-us-development-sprints/</guid></item><item><title>Hello world!</title><link>https://shankhs.com/hello-world/</link><description>This is my blog where I will document recent interview questions, tips and tricks. Also my plan is to post some how-tos if I get sometime. See you at the next post!</description><author>shankhs</author><pubDate>Sun, 28 May 2017 15:31:40 GMT</pubDate><guid isPermaLink="true">https://shankhs.com/hello-world/</guid></item><item><title>While a correction is currently taking place, and it’s impossible to foresee what will happen over…</title><link>https://olshansky.info/posts/2017-05-28-while-a-correction-is-currently-taking-place-and-its-impossible-to-foresee-what-will-happen-over/</link><description>I don’t think we’ll see real stability until it’s adopted by mainstream organizations, which could very well take at least ten years. By…</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 28 May 2017 10:25:39 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-05-28-while-a-correction-is-currently-taking-place-and-its-impossible-to-foresee-what-will-happen-over/</guid></item><item><title>Balaji S. Srinivasan One of the projects you omitted that I think is very noteworthy is Aragon.</title><link>https://olshansky.info/posts/2017-05-28-balaji-s-srinivasan-one-of-the-projects-you-omitted-that-i-think-is-very-noteworthy-is-aragon/</link><description>&lt;p&gt;&lt;a href="https://medium.com/u/f5a2e83d6d8f"&gt;Balaji S. Srinivasan&lt;/a&gt; One of the projects you omitted that I think is very noteworthy is &lt;a href="https://aragon.one/"&gt;Aragon&lt;/a&gt;. It’s built on top of ethereum and helps you manage a company (token issuance, vesting schedules, etc…) without all the intermediaries.&lt;/p&gt;</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 28 May 2017 10:18:48 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-05-28-balaji-s-srinivasan-one-of-the-projects-you-omitted-that-i-think-is-very-noteworthy-is-aragon/</guid></item><item><title>Tea bookmarks</title><link>https://xenodium.com/tea-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.notesontea.com"&gt;Georgia's notes on tea&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.drweil.com/videos-features/videos/9-green-teas-to-try/"&gt;Nine Green Teas To Try | Video (Andrew Weil, M.D.)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 28 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/tea-bookmarks</guid></item><item><title>The value of time</title><link>http://dimitarsimeonov.com/2017/05/28/the-value-of-time</link><description>&lt;p&gt;The amount of value we assign to our time could be a self-fulfilling
prophecy. If we value our time at $1000, then it is actually possible
to achieve a payoff in the future, which when prorated for number our
hours spent working towards it and adjusted for inflation and so on,
will amount to $1000 for that very next hour.&lt;/p&gt;

&lt;p&gt;If I had a low value on my time, I would be more likely to waste it. I
could be watching TV excessively, beyond the point of relaxation, I
could be getting stuck in traffic or doing errands in slow and
inefficient way.&lt;/p&gt;

&lt;p&gt;But if I knew, that spending this time working on a project, or
developing a skill, or starting a business would pay off large in the
future, and I could trace this back to this hour now, and attribute a
thousand dollars to it, I would be much less likely to waste it. What
if I can attribute even more. Then, suddenly, it doesn’t make sense to
take to do wasteful activities, but to spend the time on the activity
that would pay off.&lt;/p&gt;

&lt;p&gt;Lets imagine for a minute that I realize I have the raw talent to
become a big painter. Lets assume it would take me ten years and ten
thousand hours over these ten years, to become really good. This is
about twenty hours per week for ten years - not too bad. Lets also
assume, that when I get really good, I will be able to earn ten
million dollars, inflation adjusted, for the paintings I’ve made and
sold. This averages about a thousand dollar per each hour spent!&lt;/p&gt;

&lt;p&gt;Lets also realize that these are not wild assumptions! They are
perfectly reasonable for a lot of people, except that they would need
to replace painting with some other way to make ten million
dollars. There are ways. One can start a business, or find a way to
produce a service to others at scale. Or they can get distinguished
artist and earn a lot from their art.&lt;/p&gt;

&lt;p&gt;The financing is trickier. The payout of this endeavor is likely to
come after some time in the future. But meanwhile, the person needs to
support the effort both in terms of money and in terms of
emotions.&lt;/p&gt;

&lt;p&gt;The money part is obvious. If a person strive to be an artist, they
need to buy enough canvas, paint, brushes and other supplies so you
can practice effectively. They need also somehow to cover the basic
living expenses. It will cost a lot less than the eventual payoff will
bring, but it needs to be covered in the present moment. This could
be covered by savings, job on the side, or by selling the art as they
go. Or any combination of these, adjusted according to the situation.&lt;/p&gt;

&lt;p&gt;The emotional part is hard. What if I have the talent to be painter,
but I am not excited about painting and art, and would rather do
something else? Can I still go through the ten years and develop into
a top earning artist? If I’m not excited about it, then I would find
it harder to devote the time, even if I have the money to
support myself through that. And even if I eventually develop
excitement and passion for art, in the present moment I will be
unhappy to work on it.&lt;/p&gt;

&lt;p&gt;If I had a passion for painting, I would be more resourceful and find
ways to paint and develop and will be willing to spend more time on
it. Then, even if I find the money part hard, I would not be
discouraged, because I would be getting immediate emotional payoff.&lt;/p&gt;

&lt;p&gt;That emotional payoff is a necessary fuel in the feedback loop, which
will propel the talent to success. Without it, that talent just won’t
get developed. And rightfully so! Developing a talent that I am not
excited about would not necessarily benefit me. It might benefit the
society. But if I am unhappy doing it, why do it? I myself am one part
of society. If something else makes me happier, my goal would be to
maximize that, no matter if it brings any profit at all. It might
still make sense to develop another talent, to the point of providing
enough money to sustain life.&lt;/p&gt;

&lt;p&gt;The emotional payoff though… is all in the head. It is perfectly
subjective. Yes, there is some body-based hedonism involved, but that
only goes so far. Much of the emotional payoff is acquired taste. And
we can trick ourself to perceive the future emotional payoff, even if
it doesn’t pan out, and motivate ourself in the present moment.&lt;/p&gt;

&lt;p&gt;Just like there are many techniques to finance the money, there are
techniques to finance the emotional motivation. I don’t want to go in
the details yet, but I’d like to take a moment and appreciate that it
is possible and realistic to assign a high value on our time.&lt;/p&gt;</description><author>D13V</author><pubDate>Sun, 28 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/05/28/the-value-of-time</guid></item><item><title>Venice in spring</title><link>https://hth.is/2017/05/27/venice-in-spring/</link><description>Link to album
This month I jumped on a plane to one of these places that I had expected not to see anytime soon, that always seems so exotic when you see and read about it. I was joining the 30th birthday party of a friend of my girlfriend&amp;rsquo;s which took place in Venice. As an added bonus the Biennale (Feneyjartvíeyringurinn) was happening this year, so we got to experience one of the more interesting art events in the world with friends.</description><author>Hrafn Thorvaldsson</author><pubDate>Sat, 27 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://hth.is/2017/05/27/venice-in-spring/</guid></item><item><title>Review of the International version of the 4th edition of Probability and Statistics by DeGroot and Schervish</title><link>https://sean.lane.sh/posts/2017/05/Review-of-the-International-version-of-the-4th-edition-of-Probability-and-Statistics-by-DeGroot-and-Schervish/</link><description>&lt;p&gt;As a computer science graduate student at Brigham Young University, I am taking &lt;a href="https://gradstudies.byu.edu/course/bayesian-methods-computer-science"&gt;CS 677: Bayesian Methods in Computer Science&lt;/a&gt;, which covers some aspects of using probability within computer science, as you probably guessed from its title. The required textbook for the course is Morris DeGroot&amp;rsquo;s 4th edition of Probability and Statistics, which at the time of writing this post is selling for about &lt;a href="https://www.amazon.com/Probability-Statistics-4th-Morris-DeGroot/dp/0321500466"&gt;$170 new, $112 used on Amazon.com&lt;/a&gt;. Between being a graduate student and having a family of my own, I am not exactly swimming in funds for expensive textbooks, and my classmates had already checked out all of the available copies at the excellent &lt;a href="https://lib.byu.edu"&gt;Harold B. Lee Library&lt;/a&gt; already, so I looked for some alternatives.&lt;/p&gt;
&lt;p&gt;It turns out that there is an international version in English that is printed for use in India, Pakistan, and other English speaking countries in that region of the world. I found it available at a number of different electronic purveyors of new and used books, and I purchased my copy for about $22, including shipping, from &lt;a href="https://www.abebooks.com/"&gt;AbeBooks&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="Cover of the International version" src="https://sean.lane.sh/images/2017/05/review_of_prob_and_stats/cover.png" /&gt;&lt;figcaption&gt;
            &lt;p&gt;Cover of the International version&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The biggest issue I had with getting this book is that I wasn&amp;rsquo;t able to definitively find any sources that detailed the differences between the international and USA versions of the book. A colleague of mine asked the professor if he knew whether the international version would be suitable course, but he was unfamiliar with the international version. So I am going to do just that, for anyone who might have the same question as I did.&lt;/p&gt;
&lt;h2 id="contents"&gt;Contents&lt;/h2&gt;
&lt;figure&gt;&lt;img alt="First page of the Table of Contents" src="https://sean.lane.sh/images/2017/05/review_of_prob_and_stats/toc_1.png" /&gt;&lt;figcaption&gt;
            &lt;p&gt;First page of the Table of Contents&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img alt="Second page of the Table of Contents" src="https://sean.lane.sh/images/2017/05/review_of_prob_and_stats/toc_2.png" /&gt;&lt;figcaption&gt;
            &lt;p&gt;Second page of the Table of Contents&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The first thing to notice is that there is no Preface in the international edition, which isn&amp;rsquo;t the worst loss but you do miss out on changes between the editions, a section from the author on how to use the book, supplemental items (the instructor&amp;rsquo;s and student&amp;rsquo;s solution manuals), and then a section on acknowledgments.&lt;/p&gt;
&lt;p&gt;As you can see above and in comparison to the USA version of the book, after the Preface the contents appear to be identical down to the same page number up until Chapter 12. The international version &lt;em&gt;does not&lt;/em&gt; contain a twelfth chapter, which in the USA edition is about Simulation, and contains the following sections:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What Is Simulation?&lt;/li&gt;
&lt;li&gt;Why Is Simulation Useful?&lt;/li&gt;
&lt;li&gt;Simulating Specific Distributions&lt;/li&gt;
&lt;li&gt;Importance Sampling&lt;/li&gt;
&lt;li&gt;Markov Chain Monte Carlo&lt;/li&gt;
&lt;li&gt;The Bootstrap&lt;/li&gt;
&lt;li&gt;Supplementary Exercises&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unfortunately, CS 677 at BYU has some required readings in Chapter 12, so I have had to make other arrangements to access the material. However, if your course doesn&amp;rsquo;t need this chapter, then you are all set with this version of the text.&lt;/p&gt;
&lt;p&gt;After the last chapter, the contents are also mostly the same, though slightly out of order. with the distribution tables last in the USA edition, but before the index in the international edition. The index of the USA version also appears to be more detailed than the other, having 9 pages of content compared to the 5 pages of the international version.&lt;/p&gt;
&lt;h2 id="quality"&gt;Quality&lt;/h2&gt;
&lt;p&gt;I wanted to write a brief note on the quality of the production of this copy. While the content appears to be the same where the same material was included, the book is printed on cheaper quality paper, like what you might find in a study manual for the USA version of the textbook. That might matter for some individuals, but I do not have any qualms with it. Also, the book is a soft cover, as opposed to the hard cover of the USA versions that my classmates who bought the book appear to have.&lt;/p&gt;
&lt;h2 id="legality"&gt;Legality&lt;/h2&gt;
&lt;p&gt;It is interesting to see the various notices on the front and back covers, as well as on second page, indicating that the book is authorized to be circulated on the Indian subcontinent. It gives the book an air of illegality to even have in the United States. If anyone is having any doubts about this, while publishers gave it their all to make this sort of thing illegal in the United States, the Supreme Court ruled that it is indeed legal to purchase this edition of the book from a reseller: &lt;a href="https://arstechnica.com/tech-policy/2014/11/how-an-ebay-bookseller-defeated-a-publishing-giant-at-the-supreme-court/"&gt;How an eBay bookseller defeated a publishing giant at the Supreme Court&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;While it is unfortunate that I have some assigned readings in a chapter that isn&amp;rsquo;t available in this book, and the quality is as nice, I would definitely do this again. I was able to purchase about 91% of the book for about 25% of the cost of a worn used copy, and 13% of a new copy. Feel free to reach out if you have any questions about this copy of the book, and happy studies!&lt;/p&gt;</description><author>Posts on Sean Lane</author><pubDate>Sat, 27 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2017/05/Review-of-the-International-version-of-the-4th-edition-of-Probability-and-Statistics-by-DeGroot-and-Schervish/</guid></item><item><title>reboot(2) syscall and agic numbers</title><link>https://andrestc.com/post/reboot-syscall-magic-numbers/</link><description>&lt;p&gt;I’m currently reading “The Linux Programming Interface” and I intend to use this blog as a way to share what i’m learning (to make sure I’m actually learning).&lt;/p&gt;
&lt;p&gt;In one of the first chapters there is an exercise about the &lt;a href="http://man7.org/linux/man-pages/man2/reboot.2.html"&gt;reboot(2) syscall&lt;/a&gt; and some magic numbers that are used as parameters.&lt;/p&gt;
&lt;p&gt;The reboot(2) syscall has the following signature:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-c"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;int&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;reboot&lt;/span&gt;(&lt;span style="color: #66d9ef;"&gt;int&lt;/span&gt; magic, &lt;span style="color: #66d9ef;"&gt;int&lt;/span&gt; magic2, &lt;span style="color: #66d9ef;"&gt;int&lt;/span&gt; cmd, &lt;span style="color: #66d9ef;"&gt;void&lt;/span&gt; &lt;span style="color: #f92672;"&gt;*&lt;/span&gt;arg);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As can be read from the man page, the first parameter, magic, must be set to &lt;code&gt;LINUX_REBOOT_MAGIC1&lt;/code&gt;, that is &lt;code&gt;0xfee1dead&lt;/code&gt;(nice one). But the mistery lies on the second parameter, &lt;code&gt;magic2&lt;/code&gt;, which must be set to one of the following constants:&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Sat, 27 May 2017 02:16:49 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/reboot-syscall-magic-numbers/</guid></item><item><title>{Spam|Shadow marketing} is {amazing|great}!</title><link>https://rybakov.com/blog/say_tell_no/</link><description>&lt;p&gt;Spam emails try to get through filters by having slightly different content, such as writing &amp;ldquo;incredible&amp;rdquo; and &amp;ldquo;fantastic&amp;rdquo; interchangeably.&lt;br /&gt;
For this, a template with all the possibilities is created and processed before sending. But sometimes unprocessed templates get sent instead. The writing is quite {incredible|fantastic|marvelous| outstanding}:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;{Say|Tell} No To {Fat|Being Fat}: {Act Now|Act Fast} &amp;amp; Get {Instant|Quick|Incredible| Fantastic|Marvelous| Outstanding} Results&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;{Having|Getting} the {body of you dreams|slim body|fit body|beach body} is {easier|much easier} than you {think|always thought|thought}, {all thanks to|thanks to|with the help of} the {correct|right|low carb} {diet|diet program|diet plan|nutrition plan|nutrition program}, {good|regular} {workout|gym workouts|workouts} and this {amazing|exclusive| revolutionary|advance| spectacular} {product|supplement|solution} that will {help you|allow you to|give you a chance to|give you an opportunity to|give you a possibility to} achieve {instant|quick|incredible| fantastic|marvelous| outstanding} results.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;{Incredible|Revolutionary| Exceptional|Phenomenal|Outstanding| Glorious|Brilliant|Rapid-acting|Fast-acting} {product|supplement|solution} {working|suitable} for {all body types|types of bodies} has proven to {bring fast|show incredible|show fantastic|show quick|show jaw-dropping} results, {motivate|give motivation} for {ongoing|further} {weight reduction|weight loss}, improve {mood|your mood}, {reduce|decrease} appetite and {bring|provide} {all|other|many other} {positive|beneficial|great} effects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;{With the help of|Thanks to its} {exclusive|advanced| amazing|marvelous| unique|one-of-a-kind} formula {developed|created} {in collaboration|together} by {Japanese|German} and American {nutritionists|dietologists| scientists}, your {beach|fit|slim|dream} body is {only one click|one link} away, what are you waiting for?&lt;/p&gt;
&lt;/blockquote&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Fri, 26 May 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/say_tell_no/</guid></item><item><title>WakeMeUpInTheMiddleOfTheNight log level</title><link>https://divan.dev/posts/wakemeupinthemiddleofthenight/</link><description>&lt;p&gt;On the last &lt;a href="https://www.meetup.com/Golang-Barcelona/"&gt;Golang Barcelona meetup&lt;/a&gt; we decided to try new format of conversation and after the talk started open discussion on logging, tracing and metrics. The idea was to encourage people to read a very nice blog post by Peter Bourgon on this subject - &lt;a href="https://peter.bourgon.org/blog/2017/02/21/metrics-tracing-and-logging.html"&gt;&amp;ldquo;Metrics, Tracing and Logging&amp;rdquo;&lt;/a&gt; and discuss it in a free format.&lt;/p&gt;
&lt;p&gt;It went surprisingly well, and while most of the people were conscious about the topic, one thing seemed to be still confusing - what to log and when. I think we&amp;rsquo;re all more or less agree that we should log only when program requires human to take a look. It wasn&amp;rsquo;t a case, let&amp;rsquo;s say, 10 years ago - there were no ELK, solid solutions for metrics or tracing - we were using logs for everything, then were building &amp;ldquo;log analyzers&amp;rdquo; to deal with a vast amount of information. But now, when we have all these best practices, powerful time-series databases, visualization platforms, tracing tools - what should we print to the log?&lt;/p&gt;</description><author>divan's blog</author><pubDate>Fri, 26 May 2017 14:55:00 GMT</pubDate><guid isPermaLink="true">https://divan.dev/posts/wakemeupinthemiddleofthenight/</guid></item><item><title>Developing a Keylogger: Hardware vs. Software Techniques</title><link>https://serhack.me/articles/development-keylogger-techniques-hardware-software/</link><description>To celebrate 400+ visits to my blog after just 10 days (not bad, come on), I managed in my spare time to write another, very interesting article on another popular category of malware: keyloggers. -&lt;a href="https://serhack.me/articles/development-keylogger-techniques-hardware-software/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Fri, 26 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/development-keylogger-techniques-hardware-software/</guid></item><item><title>Structuring an Application</title><link>https://www.wints.org/notes/2017.05.26/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
Based on the scraped data, I&amp;rsquo;m planning on building an API, that&amp;rsquo;ll sync with the inventory management database (IMS).
Things are still fuzzy in my head. Hopefully writing this down helps. As of now, these are the different parts of the application.&lt;/p&gt;
&lt;p&gt;Stage 1: READ ONLY (No API)
&lt;em&gt;IMS &amp;mdash;&amp;mdash;&amp;gt; Scraper &amp;mdash;&amp;mdash;&amp;gt; Postgres &amp;mdash;&amp;mdash;&amp;gt; Utility Scripts&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stage 2: READ ONLY
&lt;em&gt;IMS &amp;mdash;&amp;mdash;&amp;gt; Scraper &amp;mdash;&amp;mdash;&amp;gt; Postgres &amp;mdash;&amp;mdash;&amp;gt; API Server &amp;mdash;&amp;mdash;&amp;gt; [Front Ends]&lt;/em&gt;&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 26 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.05.26/</guid></item><item><title>SQLAlchemy with PostgreSQL</title><link>https://www.wints.org/notes/2017.05.25/</link><description>&lt;ul&gt;
&lt;li&gt;PostgreSQL 9.5.6 &lt;a href="https://www.postgresql.org/docs/9.5/static/index.html"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SQLAlchemy 1.1.10 &lt;a href="https://docs.sqlalchemy.org/en/rel_1_1/"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SQLAlchemy with PostgreSQL &lt;a href="https://www.compose.com/articles/using-postgresql-through-sqlalchemy/"&gt;Blog Post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
Mostly I&amp;rsquo;ve worked on scrapers/crawlers and scripts, and those usually don&amp;rsquo;t require a full blown database. Flat file and/or MongoDB are usually sufficient. However, now that I&amp;rsquo;m building a database web service for a client, I need to get familiar with a relational database.&lt;/p&gt;
&lt;h4 id="requirements"&gt;Requirements &lt;a href="#requirements"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Using sqlalchemy with a postgres database requires a Database API (DBAPI) and two objects - the database engine and a metadata object.
The most well known DBAPI for Postgres is &lt;strong&gt;psycopg2&lt;/strong&gt;, so install it &lt;code&gt;pip install psycopg2&lt;/code&gt;. SQLAlchemy will use this by default.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Thu, 25 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.05.25/</guid></item><item><title>Introducing Marvin</title><link>https://muffinman.io/blog/introducing-marvin/</link><description>&lt;article class="article"&gt;&lt;p&gt;I&amp;#x27;m happy to announce &lt;a href="https://github.com/stanko/marvin"&gt;Marvin&lt;/a&gt;, boilerplate for kicking off React/Redux applications.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Marvin" height="1052" src="./marvin.jpg" width="600" /&gt;&lt;/figure&gt;
&lt;p&gt;Basically my &lt;a href="/blog/webpack-2-react-redux/"&gt;boilerplate&lt;/a&gt; became Work &amp;amp; Co&amp;#x27;s internal project. It is meant to be a starting point for our React projects. This way faster development is assured along with higher quality code. It is open source, and external contributions are welcome.&lt;/p&gt;
&lt;p&gt;Name comes from a fictional character Marvin, android from the The Hitchhiker&amp;#x27;s Guide to the Galaxy book as a homage to it&amp;#x27;s author Douglas Adams.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Thu, 25 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/introducing-marvin/</guid></item><item><title>From Ubuntu to Arch Linux</title><link>https://danielpecos.com/2017/05/24/ubuntu-arch-linux/</link><description>&lt;img alt="Ubuntu vs Arch" class="size-full aligncenter" height="303" src="https://danielpecos.com/assets/2017/04/ubuntu_vs_arch.png" width="773" /&gt;
&lt;p&gt;Recently I took the decision of leaving my &lt;a href="https://danielpecos.com/2008/06/10/debian-vs-ubuntu/"&gt;long beloved distro – Ubuntu (sorry, link in spanish)&lt;/a&gt; and moving forward into Arch Linux.&lt;/p&gt;
&lt;p&gt;And why? As &lt;a href="https://en.wikipedia.org/wiki/We_choose_to_go_to_the_Moon"&gt;JFK said&lt;/a&gt; when the USA was aiming to land on the moon, “not because it’s easy, but because it’s hard”, maybe not that much compared to getting to the moon, but definitely more tedious than Ubuntu. One thing you can take for sure if you take the chance to install Arch: no matter if you success or give up with it, &lt;strong&gt;you will learn something new about how a Linux distro works&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But really, why? Well, the announcement of retiring Unity 8 from Ubuntu from version 18.04 was the trigger to explore other desktop options. I started testing &lt;strong&gt;Gnome 3&lt;/strong&gt; (which is going to be the official replacement for Unity) but it didn’t make me fall in love with it. Then I tried &lt;strong&gt;XFCE&lt;/strong&gt; but it was too simple, way to much. Finally I tried &lt;strong&gt;Plasma (former KDE Desktop)&lt;/strong&gt; and I got impressed. Since I switched to Ubuntu back in 2008, I’ve been using Gnome 2 or Unity based desktops and never got too curious about trying anything else. Plus, installing KDE always required tons of extra libraries that would be probable be left out in the system after an eventual removal of the desktop environment (and the screenshots and feedback I read for KDE 4 were really discouraging).&lt;/p&gt;
&lt;p&gt;But Plasma look &amp;amp; feel was really slick. And, after digging a little bit about latest events in the KDE / Qt community, finally decided to completely move to Plasma, specifically to latest version available in Ubuntu 17.04, Plasma 5.8.&lt;/p&gt;
&lt;p&gt;And then I saw a review of Plasma 5.9, introducing some improvements over previous version and decided to test it, so I looked for a PPA to install it in Ubuntu, but there was none available 🙁&lt;/p&gt;
&lt;p&gt;What could I do to get the latest version working in my desktop? I could have waited for a while until it would eventually made it into a PPA. Or I could try a rolling distro 😉 And this is when Arch ringed a bell. Maybe this was the opportunity to give it a chance and try the (tedious) installation process. And of course move to a totally different package system (&lt;strong&gt;pacman&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;The first installation took me around a couple hours, going from a blank VM to a fully working Plasma desktop. Don’t get me wrong, I’m not saying it’s an easy process or meant to someone with little or none Linux experience: it requires some basic knowledge and experience in Linux systems to know what you’re doing (and not just blindly copying &amp;amp; pasting from the wiki) .&lt;/p&gt;
&lt;p&gt;I have to confess: I’ve been hooked by Arch since then on, and decided to move all my desktop environments to Arch + Plasma. Although it has a quite steep learning curve, once you get familiar with pacman and any of the &lt;strong&gt;AUR&lt;/strong&gt; package managers, it’s quite straight forward to get the packages you need installed and set up. And when you eventually face any problem then you discover the strong point of this distro: its documentation. It’s really amazing to see how many pages that wiki contains and how complete it is. It even has a page to setup &lt;a href="https://wiki.archlinux.org/index.php/starcraft"&gt;Starcraft&lt;/a&gt; (which now is free!)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description><author>GeekWare - Daniel Pecos Martínez</author><pubDate>Wed, 24 May 2017 22:57:44 GMT</pubDate><guid isPermaLink="true">https://danielpecos.com/2017/05/24/ubuntu-arch-linux/</guid></item><item><title>Junemobile</title><link>https://june.kim/junemobile/</link><author>june.kim</author><pubDate>Wed, 24 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/junemobile/</guid></item><item><title>Didact: Components and State</title><link>https://medium.com/hexacta-engineering/didact-components-and-state-53ab4c900e37</link><description>Build your own React series</description><author>Rodrigo Pombo</author><pubDate>Wed, 24 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/didact-components-and-state-53ab4c900e37</guid></item><item><title>Caffeine at ~30</title><link>https://www.wints.org/notes/2017.05.24/</link><description>&lt;p&gt;I&amp;rsquo;m turning 30 this year, and am realizing I can no longer depend on caffeine to carry me through the day after an incomplete night&amp;rsquo;s sleep. In college, this was not a problem.&lt;/p&gt;
&lt;p&gt;Not sure if this is because of age, or increasing caffeine tolerance.&lt;/p&gt;
&lt;p&gt;Get a good night&amp;rsquo;s sleep by keeping a routine and caffeine to a minimum.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Wed, 24 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.05.24/</guid></item><item><title>Call for testing: Nextcloud snap v11.0.3snap3</title><link>https://kyrofa.com/posts/call-for-testing-nextcloud-snap-v11-0-3snap3/</link><description>We&amp;rsquo;re getting ready to release a new version of the Nextcloud snap. v11.0.3snap3-rc1 is now in the candidate channel:
$ sudo snap install --candidate nextcloud This update includes:
 An update to MySQL v5.7.18 An update to certbot v0.14.1  We&amp;rsquo;d love this new version (particularly features that involve those updates) to get some exercise before we release it. Feel like helping? We&amp;rsquo;ve put together some smoke tests to get you started.</description><author>kyrofa's blog</author><pubDate>Wed, 24 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/call-for-testing-nextcloud-snap-v11-0-3snap3/</guid></item><item><title>Talk on Big Data Tools and Architectures at Foo Cafe</title><link>https://liza.io/talk-on-big-data-tools-and-architectures-at-foo-cafe/</link><description>&lt;p&gt;I went to a really interesting talk at Foo Cafe in Stockholm tonight. I stayed almost 2 hours over my time limit, but it was so worth it. The talk was by Martin Neumann, and he gave us an introduction to big data and some tools commonly used to wrangle it. Below are the notes I took throughot the talk. I cleaned them up a tiny bit, but mostly these are just for my personal benefit and are super messy - if you didn&amp;rsquo;t attend the talk they may not be that useful.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Tue, 23 May 2017 22:13:01 GMT</pubDate><guid isPermaLink="true">https://liza.io/talk-on-big-data-tools-and-architectures-at-foo-cafe/</guid></item><item><title>Postgres Setup</title><link>https://www.wints.org/notes/2017.05.23/</link><description>&lt;p&gt;&lt;em&gt;Based on PostgreSQL 9.5.6&lt;/em&gt; | &lt;a href="https://www.postgresql.org/docs/9.5/static/index.html"&gt;&lt;em&gt;Official 9.5 Documentation&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I&amp;rsquo;m scraping reports off of a inventory management system for a client. My approach is scraping and cleaning HTML tables using python, selenium, the pandas library and the beautifulsoup library. To store this data, I&amp;rsquo;m going to be using PostgreSQL. This was me getting up to speed on PostgreSQL.&lt;/p&gt;
&lt;h4 id="installing-postgres"&gt;Installing Postgres &lt;a href="#installing-postgres"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#on mac osx
$ brew install postgresql

#on ubuntu (16.04+)
$ sudo apt install postgresql
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="default-configuration"&gt;Default configuration &lt;a href="#default-configuration"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;After installing postgresql, a system-wide &lt;strong&gt;postgres&lt;/strong&gt; user is created. Postgres uses &lt;strong&gt;ident&lt;/strong&gt; authentication by default.
This means Postgres assumes a postgres role with the same name as the user. It also create a database with the same name -&amp;gt; postgres.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Tue, 23 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.05.23/</guid></item><item><title>E-Estonia – Is the digital utopia for real?</title><link>https://yasha.solutions/e-estonia-is-the-digital-utopia-for-real/</link><description>Eesti Vabariik – the Republic of Estonia
45,339 Km2 and a population 1.3 M people which like a ten time less than Paris or London.
They have a complex and interesting history (actually most countries have an interesting history – but maybe it is a personal taste.)
 But what is really interesting is how Estonia use the digital to organise their society.
E-residency
E-voting
E-school
E-police
E-etc.
 It looks quite a digital utopia…</description><author>Yasha Solutions</author><pubDate>Tue, 23 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/e-estonia-is-the-digital-utopia-for-real/</guid></item><item><title>Advice For A Nervous Traveller</title><link>https://ho.dges.online/words/commonplace/advice-for-a-nervous-traveller/</link><description>&lt;p&gt;&lt;em&gt;Included by me in a notebook AJBH took to Newlands, May 2017&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No wallowing. Being sad is ok but &lt;em&gt;making&lt;/em&gt; yourself sad is just&amp;hellip; well, &lt;em&gt;sad&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Find a positive thought from each hour and each day. It doesn&amp;rsquo;t have to be big things but keep thinking until you find something that makes you smile. Then tell someone about it and tell them why it made you smile.&lt;/li&gt;
&lt;li&gt;When you&amp;rsquo;re nervous about trying something you&amp;rsquo;ve not done before, remember that your brain sometimes gets stuck in a groove. Everything you love doing was new once. Maybe &lt;em&gt;this&lt;/em&gt; is your next favourite thing.&lt;/li&gt;
&lt;li&gt;If you&amp;rsquo;re felling sad, picture in your head a perfect place - a room, a house or town, whatever. Just somewhere where you’d be absolutely happy. Then imagine giving the people you love most a tour and tell them about all the little details that make the place perfect for you. When you’ve finished the tour, where you are in real-life may not seem so bad.&lt;/li&gt;
&lt;li&gt;Finally, remember that others will be having the exact same feelings as you. Keep an eye out for anyone who seems quiet or not themselves and make it your mission to get them to laugh and smile. This will make &lt;em&gt;both&lt;/em&gt; of you happier.&lt;/li&gt;
&lt;/ul&gt;</description><author>ho.dges.online</author><pubDate>Tue, 23 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/advice-for-a-nervous-traveller/</guid></item><item><title>2017-05-23</title><link>https://ho.dges.online/pictures/2017-05-23/</link><description/><author>ho.dges.online</author><pubDate>Tue, 23 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-05-23/</guid></item><item><title>How to integrate React with a Rails/PHP/X backend?</title><link>https://goshacmd.com/integrating-react-with-rails-php-backends/</link><author>Gosha Spark</author><pubDate>Tue, 23 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/integrating-react-with-rails-php-backends/</guid></item><item><title>Why Deliberate Positive Illusion Is Important</title><link>https://venam.net/blog/psychology/2017/05/23/deliberate-positive-illusion.html</link><description>There may exist someone in your entourage, someone you may care deeply about, or maybe even yourself, that is being crushed by the real and raw perception of themselves. They may appear to an external observer as someone who expresses a lot of self-deprecation or negativity, but the observed categorized this as realism.  We often hear the sentence "I am not a pessimist, but I am a realist," which doesn't necessarily carry the connotation we're bringing to light here. However, for that particular someone we mentioned, realism is equivalent to a degraded nihilism.  Realism in itself is a challenging subject because definitions are nebulous. We also tend to find absolute and eternal answers more attractive than vague ones. Certainty feels good to us. But nothing is like that for "real", we define and delimit things and at the same time we can see that those limits are vague and change through different lenses and scales. The absolute and vague are there at the same time.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Tue, 23 May 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2017/05/23/deliberate-positive-illusion.html</guid></item><item><title>How to Ask Questions of Experts To Gain More than Just Answers</title><link>https://josh.works/better-questions</link><description>&lt;blockquote&gt;
  &lt;p&gt;Recently, I co-led a session at Turing with &lt;a href="https://gitlab.com/selfup"&gt;Regis Boudinot&lt;/a&gt;, a Turing grad who works at &lt;a href="https://about.gitlab.com/"&gt;GitLab&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;We discussed two things:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;asking good questions&lt;/li&gt;
    &lt;li&gt;having a good workflow&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;After the session, I promised an overview of what we discussed. Here’s that overview for “Asking good questions”. &lt;a href="/developer-workflow"&gt;Get info on “having a good workflow” here&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2 id="why-do-questions-matter"&gt;Why do questions matter?&lt;/h2&gt;

&lt;p&gt;Without getting too philosophical, the process of formulating questions and finding answers to them is a big part of what makes us human.&lt;/p&gt;

&lt;p&gt;As developers, we’re asked to solve difficult problems. If we don’t happen to have all the knowledge we need for this problem readily accessible in our head, we turn to documentation and googling.&lt;/p&gt;

&lt;p&gt;On many problems, this is sufficient. On the hard ones, this will not be sufficient.&lt;/p&gt;

&lt;p&gt;We’ll need to ask for help.&lt;/p&gt;

&lt;p&gt;Since the hardest problems are also the ones we’re most likely to need help with, if we can optimize how we get help, it’ll return outsized results at advancing our skills and helping us be useful contributors to a development team.&lt;/p&gt;

&lt;p&gt;As a counterpoint, imagine you had terrible question-asking skills. In what aspects of your day-to-day would this have the largest impact?&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;The things you already know how to do&lt;/li&gt;
  &lt;li&gt;The things you &lt;em&gt;don’t already know how to do&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;!--more--&gt;

&lt;p&gt;Exactly! Questions matter.&lt;/p&gt;

&lt;h2 id="traits-of-a-bad-question"&gt;Traits of a bad question&lt;/h2&gt;

&lt;p&gt;Lets rollplay a bit. If you’re a student at Turing, and you have a friend considering attending Turing, and they sent you an email with the following sentence, how would you feel?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey there, Turing sounds cool. I’d like more information. Can you send me a link to their website, let me know the tuition, and let me know what the likelihood is that I’ll graduate with a well-paid job? Thanks!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yikes.&lt;/p&gt;

&lt;p&gt;It looks like &lt;em&gt;this person didn’t do one iota of research on their own&lt;/em&gt;. Finding the website of something is Googling 101, and they’re also asking you a very complex question that you couldn’t hope to answer without more information from them. (The likelihood that they’ll graduate with a well-paid job. How do you define well-paid? How hard will they work? Do they mean a job &lt;em&gt;on the day the graduate&lt;/em&gt; or are they willing to include a job they might find in the next two weeks?)&lt;/p&gt;

&lt;p&gt;It’s also a bit of a selfish question. We’re all selfish, but this is showing an interest only in the results, and not the process.&lt;/p&gt;

&lt;p&gt;Lets look at some other bad questions. (Some detail removed to protect the guilty, but all are pulled from Slack channels over the last few days.)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I can’t get [tool everyone uses] to work and I don’t know what I’m doing wrong&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was a real DM sent to a contemporary. No additional context, nothing. Just that one message in Slack.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Does anyone know anything about [topic]?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was a message posted in a public channel where anyone can ask questions and get help from others in the community.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Does anyone have a few minutes to pair with me on [current project]?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All of these questions were these one-liners, dropped into a public channel, where many of those that might be reading are domain experts and it is very reasonable to assume the right person with the right knowledge would see this message.&lt;/p&gt;

&lt;p&gt;All of these questions are bad because they assume the other person (the expert) is willing to ask further clarifying questions, or get wrapped into a conversation or pairing without any additional context.&lt;/p&gt;

&lt;h2 id="traits-of-a-good-question"&gt;Traits of a good question&lt;/h2&gt;

&lt;p&gt;Since we’re solving a hard problem, it’s reasonable to assume that the person helping us will also agree that it is a tricky problem. Even if it’s not “tricky”, they will need to “load up” the problem space into their head to understand what’s going on.&lt;/p&gt;

&lt;p&gt;For example - if a method isn’t doing the thing you expect it to do, someone probably needs to see the following before they can even hope to offer something useful.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the entire class&lt;/li&gt;
  &lt;li&gt;what object is being passed into the method&lt;/li&gt;
  &lt;li&gt;what object is expected&lt;/li&gt;
  &lt;li&gt;what tests you’ve written&lt;/li&gt;
  &lt;li&gt;more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that you probably will &lt;em&gt;not&lt;/em&gt; be so lucky as to get a silver-bullet solution.&lt;/p&gt;

&lt;p&gt;At a high level, when asking for help, aim to provide the “boundaries” of the problem space at the outset.&lt;/p&gt;

&lt;p&gt;Something like&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’m having problems running migrations on my app. It WAS working a few minutes ago, now it’s not. I’ve tried dropping/resetting my tables/db, &lt;code class="language-plaintext highlighter-rouge"&gt;bundle&lt;/code&gt; works just fine, my PG server is running, and I can access my ActiveRecord objects via &lt;code class="language-plaintext highlighter-rouge"&gt;rails console&lt;/code&gt;. It’s only when I try to run RSpec that I get warnings about unfinished migrations, but their recommended fix doesn’t work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This could still contain much more information, but it’s enough that someone can figure out what you’re working on, and has some context when they try to help.&lt;/p&gt;

&lt;p&gt;Contrast that question with this alternative:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Can someone help me with my migrations? They’re not working and I don’t know why.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lets talk about question workflow. If I have a problem that I cannot resolve, I open up a markdown file and start throwing notes into it.&lt;/p&gt;

&lt;p&gt;I am to be able to answer the following questions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What am I trying to do?&lt;/li&gt;
  &lt;li&gt;What have I done?&lt;/li&gt;
  &lt;li&gt;What evidence am I getting that something isn’t working? An error message? Something not calculating correctly or returning the expected results?&lt;/li&gt;
  &lt;li&gt;What different approaches have I tried?&lt;/li&gt;
  &lt;li&gt;What is all of the involved code? (Yes, I’ll copy and paste blocks of code into the document.)&lt;/li&gt;
  &lt;li&gt;If the problem is in my code, what tests do I have that are related?&lt;/li&gt;
  &lt;li&gt;What are the resources I’ve looked at in pursuit of this problem? (This is usually just a link of stack overflow posts, blog posts, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once I’ve pulled all that into a single document, I’ll add a quick summary at the top, push all the links to the bottom, and organize the code snippets a bit.&lt;/p&gt;

&lt;p&gt;At this point, I’ll throw it all into a gist and pass it along to someone who is willing and able to help.&lt;/p&gt;

&lt;p&gt;I treat the entire document almost as a letter.&lt;/p&gt;

&lt;h2 id="examples"&gt;Examples&lt;/h2&gt;

&lt;h3 id="minitest-setup-questions"&gt;MiniTest setup questions&lt;/h3&gt;

&lt;p&gt;In Mod 1, I was having problems with MiniTest setup methods. It was slowing our tests down. I really wanted to fix it, so I sent &lt;a href="https://gist.github.com/josh-works/9a386cd033dec833b65257af6eaa4fbc"&gt;this gist&lt;/a&gt; to a mentor. &lt;a href="https://gist.github.com/jasonnoble/fe58e521502c363165c708d15035fd40"&gt;His answer&lt;/a&gt; was very helpful, very focused, and exactly what I needed.&lt;/p&gt;

&lt;h3 id="mysql-usage-problems"&gt;MySql usage problems&lt;/h3&gt;

&lt;p&gt;In mod 2, I was trying to practice my ActiveRecord queries, which “compile down” to just SQL queries, so I was studying SQL. I was workin through a book that included tons of sample data to play with, but couldn’t load it up.&lt;/p&gt;

&lt;p&gt;I wrote &lt;a href="https://gist.github.com/josh-works/e1e05d1f0ead1eb3402f091b3b24ab99"&gt;this gist&lt;/a&gt; after Ed G kindly offered to help. I sent him the gist so he could understand the problem space, and it was helpful.&lt;/p&gt;

&lt;h3 id="rails-schema-problems-related-to-the-above-mysql-data-importing"&gt;Rails Schema problems (related to the above MySql data importing!)&lt;/h3&gt;

&lt;p&gt;More recently, I was having problems with the schema in a group rails app. My schema was getting loaded up with tons of tables that were nowhere to be found in my migrations! It was baffling!&lt;/p&gt;

&lt;p&gt;I sent this to our instructor:&lt;/p&gt;

&lt;p&gt;&lt;img alt="outline of problem" src="/images/josh_josh_question.jpeg" /&gt;&lt;/p&gt;

&lt;p&gt;That gave us a starting point, and forced me to be very thoughtful in all of the solutions I tried.&lt;/p&gt;

&lt;h2 id="optimize-for-learning-not-just-the-answer"&gt;Optimize for learning, not just the answer&lt;/h2&gt;

&lt;p&gt;We often feel like we just need the right answer, and we’ll be on our way, when the truth is, the most important thing for us is better &lt;em&gt;understanding&lt;/em&gt;. In the last question, with extra tables showing up in my schema, it turns out I had two instances of Postgres running on my machine. One showed up only as a running process, the other in the postgres app. One had a bunch of table in it, and I couldn’t see it.&lt;/p&gt;

&lt;p&gt;So, after kicking around some troubleshooting, Josh figured that out, and I uninstalled both, then reinstalled just one.&lt;/p&gt;

&lt;p&gt;My understanding of Postgres on my machine is much improved, and I now have a better idea how to troubleshoot similar problems in the future.&lt;/p&gt;

&lt;p&gt;If Josh had just given me the answer, without the understanding behind it, I’d barely be improved.&lt;/p&gt;

&lt;p&gt;You should seek to get the same sort of help from those around you. It’s tempting (especially when a student in Turing) to aim for the right answer. You might think you don’t have time to deepen your understanding when you have a project due in 12 hours, but really, you don’t have time to NOT deepen your understanding.&lt;/p&gt;

&lt;h2 id="better-questions-better-everything"&gt;Better questions, better everything&lt;/h2&gt;

&lt;p&gt;I am paraphrasing a recent conversation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A mediocre developer who asks good questions and can communicate well
can  become a bigger contributor to a team than an experienced
dev who doesn’t communicate well&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, here’s a checklist for the next time you need help. Write down the answers to these questions, and you’ll get &lt;em&gt;understanding&lt;/em&gt; instead of just an answer, and whoever helps will be much more likely to enjoy the process.&lt;/p&gt;

&lt;h2 id="checklist-for-asking-questions"&gt;Checklist for asking questions&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;What you are trying to do.&lt;/li&gt;
  &lt;li&gt;What steps have you taken so far?&lt;/li&gt;
  &lt;li&gt;What errors have you seen?&lt;/li&gt;
  &lt;li&gt;What sources have you consulted in your search for these answers?&lt;/li&gt;
  &lt;li&gt;What is the TL;DR?&lt;/li&gt;
  &lt;li&gt;Have you included relevant code snippets or stack traces?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This puts the burden of asking questions on &lt;em&gt;you&lt;/em&gt;, instead of the person you’re asking for help.&lt;/p&gt;

&lt;p&gt;If you don’t provide this information, the first thing the other person will ask is&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What are you trying to do?
What steps have you taken so far?
What errors have you seen?
What have you done to try to fix this?
Can I look at some code?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

&lt;h2 id="additional-reading"&gt;Additional reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://jvns.ca/blog/good-questions/"&gt;How to ask good questions&lt;/a&gt; by Julia Evans&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://jvns.ca/blog/answer-questions-well/"&gt;How to answer questions in a helpful way&lt;/a&gt;, also by Julia Evans&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Mon, 22 May 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/better-questions</guid></item><item><title>Portlanding</title><link>https://faingezicht.com/photos/2017/05/22/pdx/</link><description>This past week I got to travel to Portland for work, and took a couple of extra days to explore the city. I was attending a conference, PyCon, which took up most of my time, but I still got to travel quite a bit. We got an Airbnb on the east side of the city, and got to explore a bunch of neighborhoods: Burnside, Hawthorne, and Pearl District were where we spent most of our time.

Much like San Francisco, Portland is filled with foodies and hipsters obsessed over good coffee, good beer, and good restaurants. Unlike San Francisco though, things there are reasonably priced. If it weren't so spread out, I might consider living there at some point in my life, but I can't get past its suburban feel. Even with its electric orange Nike Bikes everywhere, the need for a car was evident. Another thing I found really odd was that all the shops closed super early - finding any coffee other than Starbucks open past 5pm was a challenge. Small city problems I guess.

For the nerds out there, &lt;a href="/articles/2017/06/15/pycon/"&gt;here&lt;/a&gt; are some notes about my experience at the conference itself. The TL;DR is 10/10, would attend again.</description><author>Avy Faingezicht</author><pubDate>Mon, 22 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/05/22/pdx/</guid></item><item><title>RequireJS Basics</title><link>https://www.wints.org/notes/2017.05.22/</link><description>&lt;p&gt;&lt;a href="http://requirejs.org/docs/start.html"&gt;Requirejs Official Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
Requirejs is used to asynchronously load javascript modules. I needed to use this for a game project for a client, and they wantedit in requirejs format. My javascript is weak at this point, so this was an excercise, not only in requirejs but in javascript itself.&lt;/p&gt;
&lt;p&gt;For basic usage with JQuery, you need the following files:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;|--scripts/
|     |--main.js
|     |--app.js
|     |--lib/
|     	  |--jquery-3.2.1.js
|     	  |--require.js
|--index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Download &lt;a href="http://requirejs.org/docs/download.html#requirejs"&gt;RequireJS&lt;/a&gt; and &lt;a href="https://jquery.com/download/"&gt;JQuery&lt;/a&gt;. These go in your &lt;strong&gt;lib&lt;/strong&gt; folder.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Mon, 22 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2017.05.22/</guid></item><item><title>10 laws of project management</title><link>https://yasha.solutions/10-laws-of-project-management/</link><description>Augustine’s Law A bad idea executed to perfection is still a bad idea
Corollary: A good idea poorly executed is of no use to anyone
 Lakein’s Law Failing to plan is planning to fail
Eisenhower’s corollary : Plans are useless, but planning is indispensable.
 Fitzgerald’s Law There are two states to any large project :
 too early to tell and too late to stop  Corollary: Projects have momentum, once started they become increasingly difficult to stop</description><author>Yasha Solutions</author><pubDate>Mon, 22 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/10-laws-of-project-management/</guid></item><item><title>3 elearning platforms you probably never heard of</title><link>https://yasha.solutions/3-elearning-platform-you-probably-never-heard-of/</link><description>We always talk about elearning through the lense of MOOCs and self-study management.
WordPress (Sensei, Learndash, LeanPress, WP-Courseware), Moodle, edX, Blackboard, Canvas, Sakai and others come out as the solutions mentioned over and over again.
 Here I wanted to show you three different directions for education and elearning needs.
 HR Driven: JollyDeck JollyDeckis an HR driven elearning platform to help managers and training departments develop and deploy internal learning strategies.</description><author>Yasha Solutions</author><pubDate>Mon, 22 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/3-elearning-platform-you-probably-never-heard-of/</guid></item><item><title>Donation options – the canary</title><link>https://yasha.solutions/justanexample-donation-options-the-canary/</link><description>justSomeUX is a series where I share some interesting UX / UI and smart copy for your inspiration (and my archive of references).
Asking for donations is never easy.
Well, the Canary found a nice way to phrase it.
  &amp;gt;Interesting Donation UX   Why is good?
 It gives perspective Make you realise that spend money more on dumb stuff so you might as well give them so of it</description><author>Yasha Solutions</author><pubDate>Sun, 21 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/justanexample-donation-options-the-canary/</guid></item><item><title>Finish your ideas</title><link>https://yasha.solutions/finish-your-ideas/</link><description>We all have ideas.
Sometime we don’t even realise we do, as we don’t always pay attention to the flow of our mind.
Some ideas come and pass and never come back.
Some stick around.
Sometime we turn these ideas into action.
But even then we seldom finish them.
 Parkinson’s law Parkinson’s law is a project-management rule of thumb stating that :
 “Work expands so as to fill the time available for its completion”</description><author>Yasha Solutions</author><pubDate>Sun, 21 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/finish-your-ideas/</guid></item><item><title>How big is Google?</title><link>https://yasha.solutions/how-big-is-google/</link><description>I was working earlier on a post on privacy, then realised I cannot even start to give a proper introduction to it without laying down some facts first.
So, there will be no jumping straight into the subject of privacy, centralisation of the internet, and how politics is affecting the internet as a whole.
Instead, we will take a couple of posts to really define the current state of the internet, also give an historical perspective, before diving into the core of the subject.</description><author>Yasha Solutions</author><pubDate>Sun, 21 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/how-big-is-google/</guid></item><item><title>Bedford/St. Martin&amp;amp;#8217;s data breach</title><link>https://eligrey.com/blog/bedford-st-martins-data-breach/</link><description>Some time between Aug 27, 2012 and May 3, 2014, the Macmillan Publishers subsidiary Bedford/St. Martin&amp;#8217;s suffered a data breach that leaked the unique email address that I provided to them. I have previously informed them of the breach and it appears that they do not care to investigate. I don&amp;#8217;t appreciate large companies getting [&amp;#8230;]</description><author>Eli Grey</author><pubDate>Sun, 21 May 2017 01:14:29 GMT</pubDate><guid isPermaLink="true">https://eligrey.com/blog/bedford-st-martins-data-breach/</guid></item><item><title>My name is Cow</title><link>https://rybakov.com/blog/mynameiscow/</link><description>&lt;p&gt;In a &lt;a href="https://www.reddit.com/r/AskReddit/comments/598qrb/health_inspectors_of_reddit_whats_the_worst/d96q5f9/?st=j011bv6k&amp;amp;sh=6db93259"&gt;reddit thread&lt;/a&gt; on health inspection violations someone offered a story about a run away cow licking bread in a recreation of a 18th century french bakery.&lt;br /&gt;
A commenter wrote a poem about the incident:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;my name is Cow,&lt;br /&gt;
and wen its nite,&lt;br /&gt;
or wen the moon&lt;br /&gt;
is shiyning brite,&lt;br /&gt;
and all the men&lt;br /&gt;
haf gon to bed -&lt;br /&gt;
i stay up late.&lt;br /&gt;&lt;br /&gt;
i lik the bred.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is unclear why it caught on so quickly, but the poem inspired countless imitations, telling more stories from the perspective of &lt;a href="http://copperbadge.tumblr.com/post/155365010096/my-name-is-cat-no-cares-have-i-be-it-sun-or"&gt;Cat&lt;/a&gt;, &lt;a href="http://sashayed.tumblr.com/post/155925205420/thenatsdorf-cow-catching-snowflakes-full"&gt;Cow&lt;/a&gt; or even &lt;a href="https://www.reddit.com/r/AskReddit/comments/5cnu7b/if_dogs_had_a_911_hotline_what_dogemergencies/d9y72vd/?st=j3kno2iz&amp;amp;sh=96a29c8e"&gt;Dog&lt;/a&gt;.&lt;br /&gt;
I would guess it is the plain form and the formidable self-confidence of Cow that makes this poem an essential response to our troubled times. Cow does not ponder on its identity or its actions. Cow knows what it is and what it does. Naturally. It liks the bred.&lt;/p&gt;
&lt;p&gt;I wish for all my friends to be more like Cow. Believe in what you do. Do it. And find something to lik.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sat, 20 May 2017 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/mynameiscow/</guid></item><item><title>State of the Snail - Debugging Hell</title><link>https://liza.io/state-of-the-snail-debugging-hell/</link><description>&lt;p&gt;It has been a while! SnailLife work has been moving at a snail&amp;rsquo;s pace. Why? Because debugging the snail brain has turned into a highly demotivating, hellish endeavour. The snails make decisions and perform actions based on so much &lt;em&gt;crap&lt;/em&gt;, that the simple log files I was using all long are just not cutting it anymore. The Laravel log for the original app has turned into 3 Laravel logs because I now have 3 independent apps (the front-end, BrainRunner, and BrainHub to coordinate all the brain runners). That then turned into individual log files per snail plus individual log files per brain task. And still making sense of why snails are choosing to behave in certain ways is nigh impossible - the brain &lt;em&gt;and&lt;/em&gt; infrastructure issues I have been facing have been seemingly neverending.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 20 May 2017 09:27:54 GMT</pubDate><guid isPermaLink="true">https://liza.io/state-of-the-snail-debugging-hell/</guid></item><item><title>Before I Fall</title><link>https://olshansky.info/movie/before_i_fall/</link><description>Olshansky's review of Before I Fall</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 20 May 2017 04:56:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/before_i_fall/</guid></item><item><title>Mythic Roller</title><link>https://mbutler.org/mythic-roller/</link><description>For the past couple of days I&amp;#8217;ve been fascinated by the Mythic GM Emulator. I created this mobile application to automate rolls on the Mythic Fate Chart. Set a Chaos Rank, choose your Odds, and it will determine your outcome plus random events based on a pseudorandom javascript d100 roll. Check out the code on [&amp;#8230;]</description><author>mbutler</author><pubDate>Sat, 20 May 2017 03:49:15 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/mythic-roller/</guid></item><item><title>The Little Book That Beats the Market</title><link>https://olshansky.info/book/the_little_book_that_beats_the_market/</link><description>Olshansky's review of The Little Book That Beats the Market by Joel Greenblatt</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 20 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/the_little_book_that_beats_the_market/</guid></item><item><title>Everything is a remix</title><link>https://yasha.solutions/everything-is-a-remix/</link><description>The quote above is a funny, yet very accurate introduction to the topic developed in the documentary by Kirby Ferguson : Everything is a Remix.
(side note: If you care who said this quote go check this link to figure out why nobody really knows.)
Everything is a remix explores the concept of originality in creativity.
 Never heard of it?
Please, take the time to watch it below.</description><author>Yasha Solutions</author><pubDate>Sat, 20 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/everything-is-a-remix/</guid></item><item><title>2017-05-20/01</title><link>https://ho.dges.online/pictures/2017-05-20-01/</link><description/><author>ho.dges.online</author><pubDate>Sat, 20 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-05-20-01/</guid></item><item><title>2017-05-20/02</title><link>https://ho.dges.online/pictures/2017-05-20-02/</link><description/><author>ho.dges.online</author><pubDate>Sat, 20 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-05-20-02/</guid></item><item><title>2017-05-20/03</title><link>https://ho.dges.online/pictures/2017-05-20-03/</link><description/><author>ho.dges.online</author><pubDate>Sat, 20 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-05-20-03/</guid></item><item><title>Scripting LaTeX: Create A Base Conversion Worksheet</title><link>https://cscrunch.com/blog/corey-pennycuff/scripting-latex-create-base-conversion-worksheet</link><description>&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;div class="illustration"&gt;&lt;img alt="Sample worksheet thumbnail" height="320" src="https://cscrunch.com/sites/default/files/imce/u2/baseConversionWorksheetOverview.png" width="250" /&gt;&lt;br /&gt;Sample base conversion worksheet&lt;br /&gt;created in LaTeX.&lt;/div&gt;
&lt;p&gt;&lt;a href="http://www.latex-project.org/"&gt;LaTeX&lt;/a&gt; is amazing.  And frustrating.  And powerful. And frustrating.&lt;/p&gt;
&lt;p&gt;This coming Fall semester, I will be teaching an introductory programming class for engineering students.  To help them understand bits, bytes, integers, etc., is to have them practice base conversions between decimal, binary, and hexadecimal.  I wanted to set this up in LaTeX, but the idea of typesetting all of those tables instantly gave me a headache.  LaTeX &lt;em&gt;should&lt;/em&gt; be able to help with the monotony, but convincing it of that will be an uphill climb.&lt;/p&gt;
&lt;h2&gt;Objectives&lt;/h2&gt;
&lt;p&gt;I want a single command that I can call, giving it two numbers (in decimal): (1.) the number on which to be shown in decimal, binary, and hexadecimal, and (2.) which of the 3 to not hide.  The output should be a table in which every cell is a digit from the number of that base.  The cells for binary and hexadecimal should line up so as to reinforce the relationship between them.  The decimal cell, however, will not be split up, since it does not line up nicely with either binary or hexadecimal.  Here is an example of what I want:&lt;/p&gt;
&lt;!--break--&gt;&lt;p&gt;
&lt;img alt="Example table layout showing three rows: decimal, binary, and hexadecimal, with all correct digits present" height="81" src="https://cscrunch.com/sites/default/files/imce/u2/baseConversionWorksheet42.png" width="427" /&gt;&lt;/p&gt;
&lt;p&gt;Lastly, because this is for student worksheets (and I also want to be able to produce an answer key), We need the ability to hide some of the output without losing the physical spacing.  Here is an example of a base conversion in which only the binary is visible:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Example table layout showing three rows: decimal, binary, and hexadecimal, with only the binary digits present" height="82" src="https://cscrunch.com/sites/default/files/imce/u2/baseConversionWorksheetBinary.png" width="423" /&gt;&lt;/p&gt;
&lt;h2&gt;Defining the problem&lt;/h2&gt;
&lt;p&gt;We need to build 3 commands in LaTeX:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;A command to get the specific digit for a number when in a particular base (up to base 16)&lt;/li&gt;
&lt;li&gt;A command to selectively hide parts of the output (while preserving the physical layout spacing)&lt;/li&gt;
&lt;li&gt;A command to output the table&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;Getting the correct digit for a given base.&lt;/h3&gt;
&lt;p&gt;This is perhaps the hardest requirement.  I could not find a LaTeX command to perform this action, so I had to build it.  The problem is, though, that LaTeX is not meant to be a programming language at all, so doing even simple calculations can be cumbersome, and there are significant limitations on what you can do.&lt;/p&gt;
&lt;p&gt;We will use 3 packages: &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fp&lt;/code&gt;&lt;/span&gt;, &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;ifthen&lt;/code&gt;&lt;/span&gt;, and &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fmtcount&lt;/code&gt;&lt;/span&gt;.  &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fp&lt;/code&gt;&lt;/span&gt; is limited on the range of numbers that it can represent, but it has a larger range than the common alternative, &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;pgfmath&lt;/code&gt;&lt;/span&gt;.  Nevertheless, &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fp&lt;/code&gt;&lt;/span&gt; is sufficient for this use case (representing up to a 16-bit unsigned number).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="geshifilter"&gt;&lt;div class="text geshifilter-text" style="font-family: monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal;"&gt;\usepackage{fp}
\usepackage{ifthen}
\usepackage{fmtcount}
 
\newcommand{\getdigit}[3]{% number, digit, base
  \FPeval\power{round((#3)^(#2-1),0)}%
  \ifthenelse{#1&amp;lt;\power}{0}{%
    \FPeval\place{round((#3)^(#2),0)}%
    \FPeval\temp{round(#1-(trunc(#1/\place,0))*\place, 0)}%
    \ifthenelse{\power&amp;gt;\temp}{0}{%
      \FPeval\temp{trunc(\temp/\place*(#3),0)}%
      \Hexadecimalnum{\temp}%
    }%
  }%
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This would be easier to understand if seen in a more readable language such as C++:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="geshifilter"&gt;&lt;div class="cpp geshifilter-cpp" style="font-family: monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal;"&gt;&lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; getdigit&lt;span style="color: #008000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; number, &lt;span style="color: #0000ff;"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; digit, &lt;span style="color: #0000ff;"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; base&lt;span style="color: #008000;"&gt;)&lt;/span&gt; &lt;span style="color: #008000;"&gt;{&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; power &lt;span style="color: #000080;"&gt;=&lt;/span&gt; &lt;span style="color: #0000dd;"&gt;pow&lt;/span&gt;&lt;span style="color: #008000;"&gt;(&lt;/span&gt;base, digit &lt;span style="color: #000040;"&gt;-&lt;/span&gt; &lt;span style="color: #0000dd;"&gt;1&lt;/span&gt;&lt;span style="color: #008000;"&gt;)&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; &lt;span style="color: #008000;"&gt;(&lt;/span&gt;number &lt;span style="color: #000080;"&gt;&amp;lt;&lt;/span&gt; power&lt;span style="color: #008000;"&gt;)&lt;/span&gt; &lt;span style="color: #008000;"&gt;{&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #FF0000;"&gt;'0'&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
  &lt;span style="color: #008000;"&gt;}&lt;/span&gt;
  &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;span style="color: #008000;"&gt;{&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; place &lt;span style="color: #000080;"&gt;=&lt;/span&gt; &lt;span style="color: #0000dd;"&gt;pow&lt;/span&gt;&lt;span style="color: #008000;"&gt;(&lt;/span&gt;base, digit&lt;span style="color: #008000;"&gt;)&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;unsigned&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; temp &lt;span style="color: #000080;"&gt;=&lt;/span&gt; number &lt;span style="color: #000040;"&gt;-&lt;/span&gt; &lt;span style="color: #008000;"&gt;(&lt;/span&gt;&lt;span style="color: #008000;"&gt;(&lt;/span&gt;number &lt;span style="color: #000040;"&gt;/&lt;/span&gt; place&lt;span style="color: #008000;"&gt;)&lt;/span&gt; &lt;span style="color: #000040;"&gt;*&lt;/span&gt; place&lt;span style="color: #008000;"&gt;)&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; &lt;span style="color: #008000;"&gt;(&lt;/span&gt;power &lt;span style="color: #000080;"&gt;&amp;gt;&lt;/span&gt; temp&lt;span style="color: #008000;"&gt;)&lt;/span&gt; &lt;span style="color: #008000;"&gt;{&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #FF0000;"&gt;'0'&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;}&lt;/span&gt;
    &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;span style="color: #008000;"&gt;{&lt;/span&gt;
      temp &lt;span style="color: #000080;"&gt;=&lt;/span&gt; &lt;span style="color: #008000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;float&lt;/span&gt;&lt;span style="color: #008000;"&gt;)&lt;/span&gt;temp &lt;span style="color: #000040;"&gt;/&lt;/span&gt; place &lt;span style="color: #000040;"&gt;*&lt;/span&gt; base&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; hex&lt;span style="color: #008000;"&gt;[&lt;/span&gt;&lt;span style="color: #008000;"&gt;]&lt;/span&gt; &lt;span style="color: #000080;"&gt;=&lt;/span&gt; &lt;span style="color: #FF0000;"&gt;"0123456789ABCDEF"&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
      &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; hex&lt;span style="color: #008000;"&gt;[&lt;/span&gt;temp&lt;span style="color: #008000;"&gt;]&lt;/span&gt;&lt;span style="color: #008080;"&gt;;&lt;/span&gt;
    &lt;span style="color: #008000;"&gt;}&lt;/span&gt;
  &lt;span style="color: #008000;"&gt;}&lt;/span&gt;
&lt;span style="color: #008000;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Obviously, I would &lt;em&gt;never&lt;/em&gt; use this approach in C++, but it serves the purpose to point out the difficulties of using &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fp&lt;/code&gt;&lt;/span&gt; in LaTeX.  &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fp&lt;/code&gt;&lt;/span&gt; math is not exact.  Even a simple exponent of whole numbers must be rounded in order to be correct.  &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;fp&lt;/code&gt;&lt;/span&gt; does not have the concept of integers (its name literally means "floating point"), so we must truncate and round everywhere.  All of this means that the code is messy.  To make it even less intuitive, the &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;ifthen&lt;/code&gt;&lt;/span&gt; package does not understand &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;&amp;lt;=&lt;/code&gt;&lt;/span&gt;, so you must test for the opposite (e.g., &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;&amp;gt;&lt;/code&gt;&lt;/span&gt;).  Lastly, there is no concept of &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;return&lt;/code&gt;&lt;/span&gt;ing early from a command, so all code must be constructed using the &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;\ifthenelse&lt;/code&gt;&lt;/span&gt; command.&lt;/p&gt;
&lt;p&gt;The main point, however, is that it works, and with that we can go to the next step.&lt;/p&gt;
&lt;h3&gt;Selectively hide parts of the table&lt;/h3&gt;
&lt;p&gt;When we say "selectively hide", we have a very specific requirement in mind.  We want to have all of the physical space on the page preserved, but to not print it.  It was suggested to me that I could simply set the text color to white and thereby hide the text, but because I may need to distribute the PDF to students, I don't want them to be able to copy-and-paste the whited-out answers.  Luckily for us, there is a LaTeX package that will help us out: &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;censor&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The input for my command will have 3 parts: The text to either include or censor, and two numeric values.  If the first numeric value is 0, then I will always show the text (because it is an example).  If the two numeric values are equal, I will show the text, otherwise I will censor the text.&lt;/p&gt;
&lt;p&gt;You may be asking, why go to all of this trouble to "censor" text?  The answer is actually a feature of the &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;censor&lt;/code&gt;&lt;/span&gt; package: by using a single command, I can "uncensor" everything, and thereby have an immediate answer key.&lt;/p&gt;
&lt;p&gt;Here is the LaTeX code:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="geshifilter"&gt;&lt;div class="text geshifilter-text" style="font-family: monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal;"&gt;\usepackage{censor}
 
\newcommand{\censorifnotequal}[3]{% statement, val1, val2
  \ifthenelse{#2=0}{#1}{\ifthenelse{#2=#3}{#1}{\censor{#1}}}%
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3&gt;Create the table output&lt;/h3&gt;
&lt;p&gt;Creating a table programmatically is difficult in LaTeX.  See the comments &lt;a href="https://tex.stackexchange.com/questions/183740/insert-loop-inside-table"&gt;here&lt;/a&gt; to get an idea of the complexity involved.  Because I am &lt;em&gt;not&lt;/em&gt; a LaTeX guru, and I had already spent hours banging my head against my keyboard getting the above portions of code to work, I opted to hard-code the table inside the command.  There are a few quirks, though, that I will mention.  First, let's look at the bare table structure.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="geshifilter"&gt;&lt;div class="text geshifilter-text" style="font-family: monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal;"&gt;\def\colwidth{.42cm}
\newcommand{\baseconvertpractice}[2]{% number, # to not censor (1-3, or 0 for none)
  \renewcommand\arraystretch{2}
  \FPeval{\num}{#1}%
  \begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}r|*{8}{&amp;gt;{\centering}p{\colwidth}|}|*{8}{&amp;gt;{\centering}p{\colwidth}|}@{}c@{}} \cline{2-17}%
  Decimal &amp;amp; \multicolumn{16}{ r| }{X} &amp;amp;\\ \cline{2-17}%
  Binary &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp; X &amp;amp;\\ \cline{2-17}%
  Hexadecimal &amp;amp; \multicolumn{4}{c|}{X} &amp;amp;%
    \multicolumn{4}{c||}{X} &amp;amp;%
    \multicolumn{4}{c|}{X} &amp;amp;%
    \multicolumn{4}{c|}{X} &amp;amp;\\ \cline{2-17}%
  \end{tabular*}%
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This produces the following output:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Example table layout showing three rows: decimal, binary, and hexadecimal, with 'X' as a placeholder for all digits" height="86" src="https://cscrunch.com/sites/default/files/imce/u2/baseConversionWorksheetX.png" width="427" /&gt;&lt;/p&gt;
&lt;p&gt;There are a few peculiarities with the layout.  First of all, I put an empty column as the last column of the table.  When left out, it produces errors and will not compile.  I believe that this is a bug in the LaTeX compiler, so my workaround is to add the empty column.  Second, I had problems with the column spacing being different if it contained a 0 or a 1, so I chose a size measurement to use explicitly (&lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;\colwidth&lt;/code&gt;&lt;/span&gt;, change as needed).  Lastly, I had problems with the digits having a weird centering, so I had to use a more complex column declaration method.  In the end, though, the output is nice.&lt;/p&gt;
&lt;p&gt;Now for the final form, complete with optionally censored rows:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="geshifilter"&gt;&lt;div class="text geshifilter-text" style="font-family: monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal;"&gt;\def\colwidth{.42cm}
\newcommand{\baseconvertpractice}[2]{% number, # to not censor (1-3, or 0 for none)
  \renewcommand\arraystretch{2}
  \FPeval{\num}{#1}%
  \begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}r|*{8}{&amp;gt;{\centering}p{\colwidth}|}|*{8}{&amp;gt;{\centering}p{\colwidth}|}@{}c@{}} \cline{2-17}%
  Decimal &amp;amp; \multicolumn{16}{ r| }{\censorifnotequal{\num}{#2}{1}} &amp;amp;\\ \cline{2-17}%
  Binary &amp;amp; \censorifnotequal{\getdigit{\num}{16}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{15}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{14}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{13}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{12}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{11}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{10}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{9}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{8}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{7}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{6}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{5}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{4}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{3}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{2}{2}}{#2}{2} &amp;amp;%
  \censorifnotequal{\getdigit{\num}{1}{2}}{#2}{2} &amp;amp;\\ \cline{2-17}%
  Hexadecimal &amp;amp; \multicolumn{4}{c|}{\censorifnotequal{\getdigit{\num}{4}{16}}{#2}{3}} &amp;amp;%
    \multicolumn{4}{c||}{\censorifnotequal{\getdigit{\num}{3}{16}}{#2}{3}} &amp;amp;%
    \multicolumn{4}{c|}{\censorifnotequal{\getdigit{\num}{2}{16}}{#2}{3}} &amp;amp;%
    \multicolumn{4}{c|}{\censorifnotequal{\getdigit{\num}{1}{16}}{#2}{3}} &amp;amp;\\ \cline{2-17}%
  \end{tabular*}%
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This can be called in the following manner: &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;\baseconvertpractice{42}{0}&lt;/code&gt;&lt;/span&gt;, in which &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;42&lt;/code&gt;&lt;/span&gt; is the number that I want to be the answer, and &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt; 0 &lt;/code&gt;&lt;/span&gt; says that I don't want anything censored.  If I put a &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;2&lt;/code&gt;&lt;/span&gt; as the final argument instead, it would only include the binary but leave out the decimal and hexadecimal.  Finally, from the &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;censor&lt;/code&gt;&lt;/span&gt; package, the commands &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;\StopCensoring&lt;/code&gt;&lt;/span&gt; and &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;\RestartCensoring&lt;/code&gt;&lt;/span&gt; can be used to disable and reenable the censor behavior.&lt;/p&gt;
&lt;p&gt;You may notice that &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;censor&lt;/code&gt;&lt;/span&gt;, by default, puts a black box in place of the text.  By adding the &lt;span class="geshifilter"&gt;&lt;code class="text geshifilter-text"&gt;\censorruleheight=0ex&lt;/code&gt;&lt;/span&gt; command, there will be no black box at all, just the white space.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Hopefully this bit of LaTeX code will be beneficial to someone.  For now, I'm on to creating the next homework assignment!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;section class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above view-mode-rss"&gt;&lt;h2 class="field-label"&gt;Tags:&amp;nbsp;&lt;/h2&gt;&lt;ul class="field-items"&gt;&lt;li class="field-item even"&gt;&lt;a href="https://cscrunch.com/tags/latex"&gt;LaTeX&lt;/a&gt;&lt;/li&gt;&lt;li class="field-item odd"&gt;&lt;a href="https://cscrunch.com/tags/base-conversion"&gt;Base Conversion&lt;/a&gt;&lt;/li&gt;&lt;li class="field-item even"&gt;&lt;a href="https://cscrunch.com/tags/homework"&gt;Homework&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/section&gt;</description><author>CS Crunch</author><pubDate>Fri, 19 May 2017 23:11:33 GMT</pubDate><guid isPermaLink="true">https://cscrunch.com/blog/corey-pennycuff/scripting-latex-create-base-conversion-worksheet</guid></item><item><title>ROS production: behind the scenes</title><link>https://kyrofa.com/posts/ros-production-behind-the-scenes/</link><description>I&amp;rsquo;m an engineer, and am pretty clueless when it comes to film-making. However, I&amp;rsquo;ve been asked by a few different people how I made the ROS prototype to production on Ubuntu Core video series. While I&amp;rsquo;m not deluding myself into thinking I&amp;rsquo;m a pro, I&amp;rsquo;m happy with how they turned out, and they were made on a shoestring budget with open-source software. This post is for those who are curious about what I did, what I used, and how I did it.</description><author>kyrofa's blog</author><pubDate>Fri, 19 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-production-behind-the-scenes/</guid></item><item><title>How to get Ctrl-arrow shortcuts working in RDP sessions on macOS / OSX</title><link>http://blog.pythonaro.com/2017/05/how-to-get-ctrl-arrow-shortcuts-working.html</link><description>&lt;p&gt;It looks like recent versions of the official &lt;a href="https://itunes.apple.com/us/app/microsoft-remote-desktop/id715768417"&gt;Microsoft Remote Desktop client&lt;/a&gt; are a bit shy when it comes to sending CTRL to the remote Windows session. I discovered this because I use Ctrl-Arrow very often to move from word to word, and it just stopped working in RDP.&lt;/p&gt;

&lt;p&gt;The solution is to make sure you don't have any overlapping OSX shortcut - typically, CTRL is used for Mission Control actions. Just disable them from &lt;i&gt;System Preferences -&gt; Keyboard -&gt; Shortcuts -&gt; Mission Control&lt;/i&gt; and you should be good to go. Any recent Apple keyboard will have real keys dedicated to those actions anyway.&lt;/p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFYZoeouAP5rdL2F3-gZqIJxKtmWDVDbckUNd2LAgWDQJxMRsJryw9y6ZAF2YmZ00VlNP1B6dU3S-yjrd1oQ7R7cUxaoQtp0yn9vMZiUeoXzfj8Rz5VwYpmjuZR29EjDEnNwI6/s1600/Screen+Shot+2017-05-18+at+09.51.48.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFYZoeouAP5rdL2F3-gZqIJxKtmWDVDbckUNd2LAgWDQJxMRsJryw9y6ZAF2YmZ00VlNP1B6dU3S-yjrd1oQ7R7cUxaoQtp0yn9vMZiUeoXzfj8Rz5VwYpmjuZR29EjDEnNwI6/s320/Screen+Shot+2017-05-18+at+09.51.48.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;(Come on Microsoft, show some guts - have an option to bypass Mac shortcuts entirely!)&lt;/p&gt;</description><author>Subclassed</author><pubDate>Thu, 18 May 2017 12:01:00 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2017/05/how-to-get-ctrl-arrow-shortcuts-working.html</guid></item><item><title>Call for testing: Darktable v2.2.4snap1</title><link>https://kyrofa.com/posts/call-for-testing-darktable-v2-2-4snap1/</link><description>The Darktable snap (darktable-kyrofa) is terribly out-of-date. I&amp;rsquo;d like to bring it up to the latest release, but I could use your help verifying that things still work. If you&amp;rsquo;re a photographer, particularly if you have some experience using Darktable, mind putting it through its paces? v2.2.4snap1-rc1 is in the candidate channel:
$ sudo snap install --candidate darktable-kyrofa Please let me know if you run into any issues.
Update: v2.2.4snap1 has now been released into the stable channel.</description><author>kyrofa's blog</author><pubDate>Thu, 18 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/call-for-testing-darktable-v2-2-4snap1/</guid></item><item><title>On male-dominated technology, and marriage</title><link>https://stop.zona-m.net/2017/05/on-male-dominated-technology-and-marriage/</link><description>&lt;p&gt;Is there a connection between male dominance in ICT, and high-tech in general, and evolution of marriage? I don&amp;rsquo;t know for sure, but these two pieces make me wonder.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 17 May 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/05/on-male-dominated-technology-and-marriage/</guid></item><item><title>I hate electron apps</title><link>https://peterlyons.com/problog/2017/05/i-hate-electron-apps/</link><description>&lt;p&gt;The following applications I use regularly on my mac on built on electron:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Atom editor&lt;/li&gt;
&lt;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Google Play Music "Desktop"&lt;/li&gt;
&lt;li&gt;Insomnia HTTP client&lt;/li&gt;
&lt;li&gt;Part of my PIA VPN client&lt;/li&gt;
&lt;li&gt;Keybase&lt;/li&gt;
&lt;li&gt;Github Desktop (soon)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hate them for the following reasons in loosely descending order of importance.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They have a "Helper" process that periodically goes berzerk on my CPU for minutes on end doing God knows what&lt;/li&gt;
&lt;li&gt;The have an unending stream of "evergreen updates" and need to be restarted multiple times a week&lt;/li&gt;
&lt;li&gt;They often have some aspect of the web browser back/forward navigation which is terrible and busted and I don't want in native desktop apps&lt;/li&gt;
&lt;li&gt;They are large in terms of download/install size and contain tons of duplicated code for all kinds of shit chrome needs but a single-language, single-purpose native application should not&lt;/li&gt;
&lt;li&gt;They are slow to start up. I can remember the days when high-end Apple laptops first started getting SSDs and you could launch applications and have them fully loaded and usable in a fraction of a second. That's my standard and none of these apps come close anymore. Instead every damn time I open Google Play Music I'm treated to a 30-second spinner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But the thing that breaks my heart is just how poorly they compare to golden-age native OS X applications like Fantastical and other apps made by for-profit companies that directly charge a price to the end users; apps made by developers that understand why people choose OS X despite its numerous challenges compared to a PC (less hardware choice, less customization, fewer applications available, 2nd-tier support, etc). We bought Macs because the overall experience was a class above.&lt;/p&gt;
&lt;p&gt;In contrast, Fantastical costs some money (about 2 restaurant meals worth), is 33MB on disk. Is fully loaded with my entire multicalendar data set displayed on the screen in under 2s regardless of network status, is idle when no activity is necessary, and has a nice update every several months which never contains regressions.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 17 May 2017 07:15:02 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/05/i-hate-electron-apps/</guid></item><item><title>Technical Analysis of WannaCry Ransomware</title><link>https://serhack.me/articles/technical-analysis-ransomware-wannacry/</link><description>By now, on the net, on TV and around the world, there is nothing but talk about WannaCrypt: ransomware, or malware that can encrypt all the files on one&amp;rsquo;s computer and demand a ransom for unlocking them. -&lt;a href="https://serhack.me/articles/technical-analysis-ransomware-wannacry/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Wed, 17 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/technical-analysis-ransomware-wannacry/</guid></item><item><title>Do what you can’t</title><link>https://yasha.solutions/do-what-you-cant/</link><description>They did not know it was impossible so they did it
— Mark Twain
 Rules,
somehow,
always,
seems to be a barrier to innovation.
  Status-quo is cultural protectionism
The status-quo creates artificial scarcity.
Because it promotes the lack of initiative
It supports business as usual.
The status-quo is opposed to disruption, to change, to innovation.
It is opposed to improvement.
It is the systemic manifestation of the resistance.</description><author>Yasha Solutions</author><pubDate>Wed, 17 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/do-what-you-cant/</guid></item><item><title>React scroll decorator</title><link>https://muffinman.io/blog/react-scroll-position-decorator/</link><description>&lt;article class="article"&gt;&lt;h2 id="update-december-2017"&gt;Update, December 2017 &lt;a class="anchor-link" href="#update-december-2017"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Check &lt;a href="/blog/react-decorators-and-scroll-manager"&gt;this post&lt;/a&gt; for updated, more performant version.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I love JavaScript decorators. One that I copy to every React project is scroll decorator.
It is fairly simple way of injecting scroll position to react components. This way you can handle scroll using react lifecycle.&lt;/p&gt;
&lt;p&gt;This decorator is not listening to a scroll event, as that is the performance killer (especially when you push it to react lifecycle). Instead, it is using interval to check if scroll position has changed. To keep it performant, I&amp;#x27;m using &lt;code&gt;requestAnimationFrame&lt;/code&gt;. Interval is only there to throttle animation frame from triggering too often.&lt;/p&gt;
&lt;p&gt;Please note that it still may cause performance issues if you apply it to a large number of components. Personally, I never had to apply it to a more than three of four per page.&lt;/p&gt;
&lt;p&gt;So here it is:&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token function-variable function"&gt;withScroll&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;ComposedComponent&lt;/span&gt; &lt;span class="token arrow operator"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;ScrollDecorator&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;constructor&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;super&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Initial scroll position&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;state&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      scrollPosition&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getWindowScrollTop&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Bind handlers&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;handleInterval&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;handleInterval&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;bind&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;handleRequestAnimationFrame&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;handleRequestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;bind&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;componentWillMount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// 50 times per second, change to your needs&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token constant"&gt;INTERVAL&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;20&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;intervalID&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;setInterval&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;handleInterval&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token constant"&gt;INTERVAL&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Remove and reset interval/animationFrame&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;clearInterval&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;intervalID&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;cancelAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;requestID&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;requestID&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;intervalID&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;null&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;getWindowScrollTop&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Get scroll position, with IE fallback&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;return&lt;/span&gt; &lt;span class="token dom variable"&gt;window&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;pageYOffset&lt;/span&gt; &lt;span class="token operator"&gt;||&lt;/span&gt; &lt;span class="token dom variable"&gt;document&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;documentElement&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;scrollTop&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;handleInterval&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Interval is only used to throttle animation frame&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token function"&gt;cancelAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;requestID&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;requestID&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;handleRequestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;handleRequestAnimationFrame&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; scrollPosition &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;state&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;const&lt;/span&gt; newScrollPosition &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getWindowScrollTop&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Update the state only when scroll position is changed&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;newScrollPosition &lt;span class="token operator"&gt;!==&lt;/span&gt; scrollPosition&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;setState&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;        scrollPosition&lt;span class="token operator"&gt;:&lt;/span&gt; newScrollPosition&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; scrollPosition &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;state&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token class-name"&gt;ComposedComponent&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;        &lt;span class="token spread"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token spread operator"&gt;...&lt;/span&gt;&lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;props&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;        &lt;span class="token attr-name"&gt;scrollPosition&lt;/span&gt;&lt;span class="token script language-javascript"&gt;&lt;span class="token script-punctuation punctuation"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; scrollPosition &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;      &lt;span class="token punctuation"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;export&lt;/span&gt; &lt;span class="token keyword"&gt;default&lt;/span&gt; withScroll&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="usage"&gt;Usage &lt;a class="anchor-link" href="#usage"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Import the decorator and apply it to your component, easy-peasy.&lt;/p&gt;
&lt;p&gt;This will inject &lt;code&gt;scrollPosition&lt;/code&gt; to it&amp;#x27;s props.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;React&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;withScroll&lt;/span&gt; &lt;span class="token keyword"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;./scroll-decorator&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token decorator"&gt;&lt;span class="token at operator"&gt;@&lt;/span&gt;&lt;span class="token function"&gt;withScroll&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;class&lt;/span&gt; &lt;span class="token class-name"&gt;CoolComponent&lt;/span&gt; &lt;span class="token keyword"&gt;extends&lt;/span&gt; &lt;span class="token class-name"&gt;Component&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;render&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;const&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; scrollPosition &lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;this&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;props&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token keyword"&gt;return&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      &lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;        Current scroll position is: &lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; scrollPosition &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token plain-text"&gt;px.
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;      &lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 17 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-scroll-position-decorator/</guid></item><item><title>Where does authentication fit in a React Native app?</title><link>https://goshacmd.com/auth-in-react-native-apps/</link><author>Gosha Spark</author><pubDate>Wed, 17 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/auth-in-react-native-apps/</guid></item><item><title>Shakespeare, topology, and machine learning</title><link>https://bastian.rieck.me/blog/2017/shakespeare_topology_ml/</link><description>&lt;p&gt;In this post, I want to briefly explain how to combine methods from
&lt;a href="https://en.wikipedia.org/wiki/Topological_data_analysis"&gt;&amp;ldquo;topological data analysis&amp;rdquo;&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Machine_learning"&gt;&amp;ldquo;machine learning&amp;rdquo;&lt;/a&gt;.
Given a &lt;em&gt;Shakespearean social network&lt;/em&gt;, I want to predict whether it is
likely to be a comedy or not.&lt;/p&gt;
&lt;h1 id="preliminaries--terms"&gt;Preliminaries &amp;amp; terms&lt;/h1&gt;
&lt;p&gt;Let’s first discuss some terms: a &lt;em&gt;Shakespearean social network&lt;/em&gt;
is a co-occurrence network generated from an annotated corpus of
Shakespeare’s plays. The basic idea is to calculate a graph from
the play in which characters that co-occur in a scene are connected by
an edge. The edge weight roughly indicates how many lines of text
a character has—the idea being that less important characters
should be connected by edges with smaller weights.&lt;/p&gt;
&lt;p&gt;I already wrote two posts about these networks, with the &lt;a href="https://bastian.rieck.me/blog/2016/introduction_shakespeare_social_network_analysis/"&gt;first
one&lt;/a&gt;
talking about the general ideas behind these networks and providing some
basic statistics, and the &lt;a href="https://bastian.rieck.me/blog/2016/topology_shakespearean_social_networks/"&gt;second
one&lt;/a&gt; talking
about a more formal evaluation in the form of a short paper titled &lt;a href="https://bastian.rieck.me/research/Vis2016.pdf"&gt;&lt;em&gt;‘Shall I compare thee to a
network?’—Visualizing the Topological Structure of Shakespeare’s
Plays&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The short paper focuses more on &lt;em&gt;visualizing&lt;/em&gt; structural similarities
between plays. Much has happened in the meantime, however. I started
working on &lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, a library for
exploring persistent homology. Moreover, encouraged by previous
publications (namely, my two papers about &lt;a href="https://bastian.rieck.me/research/EuroVis2016_Comparing_Clusterings.pdf"&gt;analysing clustering
algorithms&lt;/a&gt; and &lt;a href="https://bastian.rieck.me/research/EuroVis2015.pdf"&gt;dimensionality reduction
methods&lt;/a&gt;), I started to delve a little bit
deeper into machine learning.&lt;/p&gt;
&lt;p&gt;In some sense, this post is a continuation of my work in that area.&lt;/p&gt;
&lt;h1 id="topological-data-analysis--persistent-homology"&gt;Topological data analysis &amp;amp; persistent homology&lt;/h1&gt;
&lt;p&gt;Since I want to keep this post brief (I plan on writing up a more
detailed explanation as a follow-up post), I merely focus on the basic
idea behind my analysis. Using &lt;em&gt;persistent homology&lt;/em&gt;, a method from
topological data analysis, it is possible to measure the amount of
‘holes’ in a network. Yes, you read that correctly. While
many algorithms describe what is &lt;em&gt;there&lt;/em&gt;, persistent homology focuses on
what is &lt;em&gt;missing&lt;/em&gt;. This paradigm is highly successful and has been
applied in many different application domains so far—let me just
mention Gunnar Carlsson’s paper &lt;a href="http://journals.cambridge.org/abstract_S0962492914000051"&gt;Topological pattern recognition
for point cloud data&lt;/a&gt;
as one particularly striking example of this.&lt;/p&gt;
&lt;p&gt;At the heart of persistent homology is the concept of a &lt;em&gt;persistence
diagram&lt;/em&gt;, a two-dimensional scatter plot that depicts scale information
about each hole. For every dimension of an input data set, we have
a separate persistence diagram. These diagrams are commonly taken as
a &lt;em&gt;feature descriptor&lt;/em&gt; that summarizes a data set. Their appeal lies in
certain structural properties such as robustness. Furthermore, it is
possible to calculate the &lt;a href="https://en.wikipedia.org/wiki/Wasserstein_metric"&gt;&amp;ldquo;Wasserstein distance&amp;rdquo;&lt;/a&gt; between them. This makes it possible to
compare two extremely complex objects, shapes, or spaces by a rather
simple algorithm!&lt;/p&gt;
&lt;h1 id="distances--kernels"&gt;Distances &amp;amp; kernels&lt;/h1&gt;
&lt;p&gt;In the aforementioned &lt;a href="https://bastian.rieck.me/research/Vis2016.pdf"&gt;short
paper&lt;/a&gt;, I used the Wasserstein distance between
persistence diagrams in order to obtain a low-dimensional embedding of
Shakespeare’s plays. Proximity in this embedding means that the
co-occurrence networks of two plays have a similar structure. Among
other things, one of the results of the short paper was that
comedies such as &lt;em&gt;A Midsummer Night’s Dream&lt;/em&gt; appear to form
clusters, while tragedies such as &lt;em&gt;Hamlet&lt;/em&gt; appear to be spread out more.&lt;/p&gt;
&lt;p&gt;It is thus a natural question to ask whether it is possible to decide if
a random Shakespeare play, described as a co-occurrence network, is
a comedy or not. This seems like a perfect job for machine learning!
Based on the successful usages of persistent homology in other contexts,
it seemed natural to me to use it in order to assess the dissimilarity
between the networks. There are other options out there for doing
this—and it would be an interesting side-project to compare all of
them—but seeing that most of my research centres on persistent
homology one way or the other, I will stick with it.&lt;/p&gt;
&lt;p&gt;In order to unleash the power of machine learning on these unsuspecting
networks, we require the definition of a suitable &lt;a href="https://en.wikipedia.org/wiki/Kernel_method"&gt;&amp;ldquo;kernel&amp;rdquo;&lt;/a&gt;. A kernel function permits us to use
supervised learning algorithms without ever having to specify
coordinates in the feature space. Given the fact that the feature space
is extremely hard to describe—notwithstanding current efforts to
introduce vector-based representations of persistence diagrams, such as
&lt;a href="http://www.jmlr.org/papers/volume18/16-337/16-337.pdf"&gt;persistence
images&lt;/a&gt;—kernel
methods are a blessing. Thanks to
&lt;a href="http://scikit-learn.org"&gt;&lt;code&gt;scikit-learn&lt;/code&gt;&lt;/a&gt;, they can be used quite
easily.&lt;/p&gt;
&lt;p&gt;There are multiple options for calculating kernels. Here, I experimented
a little bit with a simple Wasserstein kernel (obtained from
negating the Wasserstein distance values) as well as &lt;em&gt;persistence
indicator functions&lt;/em&gt;( of which I hope to write more in a subsequent
post).&lt;/p&gt;
&lt;p&gt;I am leaving out the generation process of the kernel matrices for now,
because I plan on describing them in a subsequent blog post: my library
for calculating persistent homology is still subject to change and I do
not want to prematurely write about APIs that are not yet ready.&lt;/p&gt;
&lt;h1 id="experiments--results"&gt;Experiments &amp;amp; results&lt;/h1&gt;
&lt;p&gt;After generating the kernel matrices with
&lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, we can use &lt;a href="https://en.wikipedia.org/wiki/Support_vector_machine"&gt;&amp;ldquo;support vector machines&amp;rdquo;&lt;/a&gt; to test how
easily we may detect comedies. Some caution is necessary, though: there
are only 37 plays, of which 17 are comedies. A standard splitting of the
data set into &lt;em&gt;training&lt;/em&gt; and &lt;em&gt;test&lt;/em&gt; data is thus not useful here because
there are not enough samples. I thus opted for &lt;a href="https://en.wikipedia.org/wiki/Cross-validation_(statistics)"&gt;&amp;ldquo;cross-validation techniques&amp;rdquo;&lt;/a&gt;, more precisely
&lt;em&gt;leave-p-out cross-validation&lt;/em&gt;, with &lt;code&gt;p&lt;/code&gt; up to 3.&lt;/p&gt;
&lt;p&gt;The results are as follows:&lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Kernel&lt;/th&gt;
    &lt;th&gt;Accuracy&lt;/th&gt;
    &lt;th&gt;Average ROC AUC&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Persistence indicator functions, &lt;code&gt;d=1&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;0.86&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;0.91&lt;/b&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Persistence indicator functions, &lt;code&gt;d=2&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;0.73&lt;/td&gt;
    &lt;td&gt;0.80&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Persistence indicator functions, &lt;code&gt;d=3&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;0.66&lt;/td&gt;
    &lt;td&gt;0.74&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Wasserstein, &lt;code&gt;d=1&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;0.86&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;0.95&lt;/b&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Wasserstein, &lt;code&gt;d=2&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;0.81&lt;/td&gt;
    &lt;td&gt;0.94&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Wasserstein, &lt;code&gt;d=3&lt;/code&gt;&lt;/td&gt;
    &lt;td&gt;0.81&lt;/td&gt;
    &lt;td&gt;0.93&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;The entries in the third column refer to the &lt;em&gt;area under the curve&lt;/em&gt; of
the &lt;a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic"&gt;&amp;ldquo;receiver operating characteristic&amp;rdquo;&lt;/a&gt; and give an idea about how the classifier
will perform in general. These values are to be taken with a grain of
salt, however, because there are few samples of &lt;em&gt;both&lt;/em&gt; classes.
I selected the &lt;em&gt;accuracy&lt;/em&gt; performance measure because there are only two
classes and they are not highly skewed. Given that the probability of
a random play being a comedy is about &lt;code&gt;0.46&lt;/code&gt;, it is nice to see that we
are able to detect comedies rather well.&lt;/p&gt;
&lt;p&gt;Nonetheless, the values in the table are somewhat surprising. First of
all, from personal experience I would have expected a slightly better
performance from the second Wasserstein distance—it is the one
that is commonly used because its local costs resemble the basic
Euclidean distance. This has the nice property of suppressing
topological features with low persistence values. It thus appears that
these features are useful for classification purposes. &lt;a href="http://www.paulbendich.com"&gt;Paul Bendich&lt;/a&gt; suspected something similar in his paper &lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5026243"&gt;&lt;em&gt;Persistent Homology Analysis of Brain Artery Trees&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That said, there is no guarantee of persistence being correlated
with importance, just with reliability. Indeed, one of the findings
in Section 5 is that dots of not-particularly-high persistence have
the most distinguishing power in our specific application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="what-now"&gt;What now?&lt;/h1&gt;
&lt;p&gt;This was/is a fun project for me as it combines several interesting
aspects. I look forward to trying out more kernels, such as the one
proposed by Reininghaus et al. in &lt;a href="https://arxiv.org/pdf/1412.6821.pdf"&gt;&lt;em&gt;A Stable Multi-Scale Kernel for
Topological Machine Learning&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the results of this paper was that the Wasserstein distance is
theoretically unsuitable as a kernel function. This is somewhat
unfortunate because it still appears to work.  I sincerely hope that the
persistence indicator function proves to be a viable candidate for
kernel methods because it can be calculated very quickly and, in
contrast to persistence diagrams, permits the definition of a unique
&lt;em&gt;mean&lt;/em&gt; function.&lt;/p&gt;
&lt;p&gt;As soon as time permits, I shall write a more detailed article about the
technical details of this experiment. Please take a look at the &lt;a href="https://github.com/Pseudomanifold/TML"&gt;GitHub
repository&lt;/a&gt; that I created for this
article. Here, you will find the raw data along with some scripts to
reproduce the values reported in this blog post.&lt;/p&gt;
&lt;p&gt;Have fun and feel free to drop me a line if you are interested in
these (or related) methods. I will be more than happy to have an
interesting discussion.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Tue, 16 May 2017 19:55:20 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/shakespeare_topology_ml/</guid></item><item><title>Java Exceptions naming convention: `&amp;lt;problem&amp;gt;&amp;lt;noun&amp;gt;Exception`</title><link>https://www.databasesandlife.com/java-exception-naming/</link><description>&lt;p&gt;I have long been inconsistent when creating Java Exception classes, in terms of how I name them. Having looked through the Exeptions that are supplied with Java, I see there is no real standard naming convention.&lt;/p&gt;
&lt;p&gt;I have found more exceptions with the form &lt;code&gt;&amp;lt;problem&amp;gt;&amp;lt;noun&amp;gt;Exception&lt;/code&gt;. For example, &lt;code&gt;IllegalArgumentException&lt;/code&gt;. So that&amp;rsquo;s what I&amp;rsquo;ve decided to use in the future.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Tue, 16 May 2017 12:20:37 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/java-exception-naming/</guid></item><item><title>New 3D printing demo opens huge market to makers</title><link>https://stop.zona-m.net/2017/05/new-3d-printing-demo-opens-huge-market-to-makers/</link><description>&lt;p&gt;They did &amp;ldquo;The Ultimate (3D printing) Bridge Test&amp;rdquo;. They had no idea of what may happen next.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 16 May 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/05/new-3d-printing-demo-opens-huge-market-to-makers/</guid></item><item><title>Social Proof and the Bystander Effect</title><link>https://blog.nawaz.org/posts/2017/May/social-proof-and-the-bystander-effect/</link><description>&lt;p&gt;Lately I&amp;#8217;ve been reading the book
&lt;a class="reference external" href="https://www.amazon.com/Influence-Psychology-Persuasion-Robert-Cialdini/dp/006124189X"&gt;Influence&lt;/a&gt;
by Robert Cialdini. The chapter on &lt;em&gt;Social Proof&lt;/em&gt; reminded me of an
&lt;a class="reference external" href="https://www.thisamericanlife.org/radio-archives/episode/420/transcript"&gt;episode&lt;/a&gt;
of &lt;a class="reference external" href="https://www.thisamericanlife.org/"&gt;This American Life&lt;/a&gt; I had
heard some years ago &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The episode begins with a mailman delivering mail, when he&amp;nbsp;sees:&lt;/p&gt;
&lt;blockquote&gt;
And they were punching each other and …&lt;/blockquote&gt;</description><author>Beetle Space</author><pubDate>Tue, 16 May 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2017/May/social-proof-and-the-bystander-effect/</guid></item><item><title>Wooden Ring</title><link>https://june.kim/wooden-ring/</link><author>june.kim</author><pubDate>Tue, 16 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/wooden-ring/</guid></item><item><title>Milgram experiment, company culture, work ethics</title><link>https://yasha.solutions/milgram-experiment-company-culture-work-ethics/</link><description>Or why “do as you are told” is a bad idea.
In 1964, Stanley Milgram back then a young researcher at Yale University, published the resultsa famous experiment known to this day as the Milgram Experiment.
The set up is simple:
The subject of the experiment takes part himself in a (staged) experiment supposed to study the impact of pain on memory and learning.
For this, he is asked by the experimenter to administer increasingly strong electric shocks to a test subject for every wrong answer.</description><author>Yasha Solutions</author><pubDate>Tue, 16 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/milgram-experiment-company-culture-work-ethics/</guid></item><item><title>Installing Apache Cassandra with PHP 7 on Ubuntu 16.04</title><link>https://www.jimwestergren.com/installing-cassandra-with-php-7-on-ubuntu</link><description>I spent a lot of time and paid for some help (thanks David Donari!) to figure out how to install Apache Cassandra with PHP 7 and the Datastax PHP Driver. I needed additional Cassandra servers with PHP and had to find a solution to this. Following the official installation instructions ... will not work. It &amp;#91;...&amp;#93;</description><author>Jim Westergren</author><pubDate>Tue, 16 May 2017 00:06:00 GMT</pubDate><guid isPermaLink="true">https://www.jimwestergren.com/installing-cassandra-with-php-7-on-ubuntu</guid></item><item><title>Switching to Jekyll</title><link>https://josh.works/switching-to-jekyll</link><description>&lt;h2 id="why-i-switched-to-jekyll"&gt;Why I switched to Jekyll&lt;/h2&gt;

&lt;p&gt;A few days ago, I was &lt;em&gt;really&lt;/em&gt; feeling the urge to write a short little blog post. So, I put it in a &lt;a href="https://gist.github.com/josh-works"&gt;gist&lt;/a&gt; on Github.&lt;/p&gt;

&lt;p&gt;I’m an advocate of writing publicly, and making it a habit, so why was I putting it in a gist, instead of here, on my website, where I theoretically can write and publish &lt;em&gt;anything I want&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Friction&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s very easy for me to sketch out a quick document with embedded screenshots in a text editor. I spend most of my day in a text editor anyway, so it’s trivially easy to write a new document.&lt;/p&gt;

&lt;p&gt;I can add code snippets, links, images, and have nicely formatted text, just the way that I like it, in a gist.&lt;/p&gt;

&lt;p&gt;SquareSpace, the service I &lt;em&gt;was&lt;/em&gt; using for my website, is not designed for people who write in Markdown. SquareSpace is very good at many things, but not the things I needed. &lt;a href="http://www.practicallyefficient.com/2016/04/03/static-and-free.html"&gt;Practically Efficient&lt;/a&gt; says it better than I can.&lt;/p&gt;

&lt;p&gt;So, last week, I decided that if I didn’t make my writing and publishing easy, I would probably just stop writing.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h2 id="what-is-jekyll"&gt;What is Jekyll?&lt;/h2&gt;

&lt;p&gt;Jekyll is a “blog-aware static site generator that can run on Github Pages” &lt;a href="https://jekyllrb.com/"&gt;(source)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All of these check off the “nice-to-have” boxes I’d look for. And now that I’m spending all day writing code, and inside of a text editor, and using Github, getting to merge my Git workflow with blogging is sorta perfect.&lt;/p&gt;

&lt;p&gt;Plus, Jekyll is written in Ruby, so it has lots of pieces I’m quite familiar with by now.&lt;/p&gt;

&lt;p&gt;I pulled from lots of articles others had written, to figure out all sorts of little tweaks. Here’s the list that I drew most heavily from:&lt;/p&gt;

&lt;h2 id="initial-resources-i-used-to-start"&gt;Initial Resources I used to start&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://joshualande.com/jekyll-github-pages-poole"&gt;Using the Poole theme&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://rck.ms/jekyll-github-pages-custom-domain-gandi-https-ssl-cloudflare/"&gt;Enabling SSL connections with Github pages and a custom domain&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://joshualande.com/short-urls-jekyll"&gt;setting up reasonable post short-links&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.controlfd.com/2016/05/16/add-a-mailchimp-subscriber-form-to-your-jekyll-blog.html"&gt;Add email subscription box to jekyll blog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://michaelsoolee.com/google-analytics-jekyll/"&gt;Google Analytics setup for Jekyll&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://coderwall.com/p/eazb7w/easily-create-blog-post-excerpts-for-jekyll-and-github-pages"&gt;Add and manage post excerpts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://gist.github.com/spiffytech/e73777e167dc5a8b6a87"&gt;Ruby script to parse SquareSpace XML archive into Jekyll-friendly posts (with images!)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://elliotekj.com/2016/12/05/jekyll-create-a-list-of-all-posts-in-the-same-category/"&gt;Adding “related posts” tool&lt;/a&gt; (I’m not currently satisfied w/my current implementation)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://sarathlal.com/add-meta-description-in-jekyll-posts/"&gt;Add meta description in Jekyll posts&lt;/a&gt; (&lt;a href="https://github.com/josh-works/josh-works.github.io/commit/d73080031d87390e165b84fcb678760f488375df"&gt;This is the commit where I added it, if the above directions caused you some confusion too&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s about it. It’s been an amazing experience, porting everything over to Jekyll.&lt;/p&gt;

&lt;p&gt;There are still some modifications I want to make, like how code snippets run off the edge of the page if the lines are long, but this is lower priority.&lt;/p&gt;

&lt;p&gt;There’s still plenty for me to learn with Jekyll, but I’m getting there.&lt;/p&gt;

&lt;p&gt;Until then, I’ll probably be posting a lot more online. Since it’s so easy.&lt;/p&gt;

&lt;h2 id="additional-resources-ive-made-use-of-since-2017"&gt;Additional resources I’ve made use of since 2017&lt;/h2&gt;

&lt;p&gt;Since switching to Jekyll in 2017, I’ve made additional changes. I’ll list useful resources here as I go.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://github.com/allejo/jekyll-toc"&gt;Jekyll Pure Liquid Table of Contents&lt;/a&gt; Auto-generate Table of Contents, &lt;em&gt;no javascript required&lt;/em&gt;. So nice.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/allejo/jekyll-anchor-headings"&gt;Jekyll Pure Liquid Heading Anchors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="misc-other-notes"&gt;Misc other notes&lt;/h2&gt;

&lt;p&gt;I recently made &lt;a href="https://gist.github.com/josh-works/a78f0f904af8b18123c2b9b48387722d"&gt;this gist&lt;/a&gt; to help mod 1 backend Turing students get up and running on Jekyll. I’ll convert that gist to a proper page on my website soon.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Mon, 15 May 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/switching-to-jekyll</guid></item><item><title>Hello world! I'm SerHack</title><link>https://serhack.me/articles/hello-world/</link><description>Hello world, I am SerHack, I am a developer, a security researcher and writer, I mostly write about software backend and a security researcher. I am from Italy where the security of citizens data is not seen as a priority. When I started looking to the world of development, I was like 12 years old. -&lt;a href="https://serhack.me/articles/hello-world/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Mon, 15 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/hello-world/</guid></item><item><title>Scientific Code</title><link>https://bastibe.de/2017-05-14-scientific-code.html</link><description>&lt;p&gt;A short while ago, I spent a few weeks collecting and evaluating various implementations of speech analysis algorithms for my current work. TL;DR: the general quality of scientific software is bad, and needs to improve.&lt;/p&gt;
&lt;p&gt;Let me state up front that I am explicitly &lt;em&gt;not&lt;/em&gt; talking about the quality of the science itself. This blog post is exclusively focused on the published &lt;em&gt;software&lt;/em&gt;. In general, the problems were bad programming, old and unmaintained code, and lack of documentation. While none of these things mean &lt;em&gt;bad science&lt;/em&gt;, they are a real challenge to reproducibility. Follow-up work can not quote algorithms they can't run.&lt;/p&gt;
&lt;p&gt;Most scientists are not programmers, and use programming as a tool for doing science. Scientists typically don't conceptualize algorithms as code, and don't reason about their implementation in terms of code. Consequently, executable implementations tend to not read like code, either. And frankly, this is as it should be. In my area of research, programming abstractions are not a great medium for expressing scientific ideas, and programming transformations are weak in comparison to mathematical operations.&lt;/p&gt;
&lt;p&gt;Still, the result is &lt;em&gt;bad code&lt;/em&gt;. And &lt;em&gt;bad code is a problem for reproducibility and comparability&lt;/em&gt;. Scientists therefore need to produce better code that is readable and portable. Straight-up letter-by-letter translations of the published math is just not enough, with all its single-letter variable names and complex nested expressions. We have to do better.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Include an Example Script&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I have seen many instances of code that clearly worked at one point on the original author's machine, but doesn't on my computer. Maybe that is because I am running a different version of the programming environment, maybe my data is subtly different, maybe the author forgot to document a dependency. All of these happened to me, and all of these are exactly what you would expect from old, unmaintained code from non-expert programmers.&lt;/p&gt;
&lt;p&gt;The least we can do to improve this situation, is to document how the code was supposed to work. A simple example script &lt;em&gt;with example data and example results&lt;/em&gt; lets me verify that the code does what it is supposed to be doing. Without this, I can not diagnose errors. Worse, if no example results are included, I might conclude that the algorithm was bad, when in reality I was simply using an incorrect version of a dependency.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Document Dependencies&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It is important to document all toolboxes, libraries, and programming languages used, &lt;em&gt;including their exact version and operating system&lt;/em&gt;. At one point, I spent several hours debugging some Java code that worked in Java 5, but didn't on any recent Java version. If this had been documented, I could have fixed that error much more quickly. In another case, one piece of C code contained a subtle error if compiled with a 64 bit compiler. Again, this took a long time to track down, and would have been much easier if the original operating system and compiler version had been documented.&lt;/p&gt;
&lt;p&gt;That same piece of C code could only be run by compiling several library dependency from old versions of their source code. In that case, the author helpfully included copies of the original source code for these libraries with his source distribution. Without that, I would never have gotten that piece of code to run!&lt;/p&gt;
&lt;p&gt;Also, if at all possible, published code should use as few dependencies as possible. Not only might I not have access to that fancy Matlab Toolbox, but every step in the installation instructions is another thing that can go wrong. The more contained the code, the more likely it is that it will still be executable many years later.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Higher Level Languages are better than Lower Level Languages&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In general, I had far less problems with non-compiled, high-level code for Matlab, Python, or R, than with low-level C or Java code. On the one hand, this is a technological problem: It is easier to keep an interpreter compatible with outdated code than it is to keep a more complex tool chains with compilers, linkers, and runtime libraries compatible. On the other hand though, this is a human problem as well: I happen to know Python, Matlab, and C pretty well, but I don't know much R or Java. Still, it is much easier to reason about the runtime behavior of R code (because I can inspect variables like in any other dynamic programming language) than to debug some unknown build tool interaction in Java (because compilation tool chains are typically much more complex and variable than REPLs).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Keep it Simple&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A particular problem are compiled modules for an interpreted language. Such Mex files and CPython extensions are almost guaranteed to break when programming language versions change, and are often hard to upgrade, since the C APIs often change with the language version as well. Often, these compiled modules are provided for performance reasons. But what was painfully slow on the original author's work laptop a few years ago might not be a problem at all on a future compute cluster. If the code absolutely has to be provided a Mex file or a CPython extension, we should at least provide an interpreted version as well.&lt;/p&gt;
&lt;p&gt;And speaking of compute clusters, I have had a lot of trouble with clever tricks such as massively parallelized code or GPU-optimized code. Not only does this age poorly, it also wreaks havoc when trying to run this code on a compute cluster. Such low-level performance optimizations are rarely a good idea for published scientific code, and should at least be optional and well-documented.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Document the Code&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Code is never self-documenting. Given enough time, entropy increases inexorably, and times change. Conventions change, and what seemed obvious a few years ago might look like gibberish today. What is perfectly readable to a domain expert is inscrutable even to scientists of closely related areas of research. It is therefore necessary to always document published code, even if the code looks perfectly obvious to the author. In the same vein, we should refrain from using jargon in our code, and clearly declare our variables and invariants (they are bound to be different for different people).&lt;/p&gt;
&lt;p&gt;Importantly, this includes documenting all file formats and data structures. Institutions often have in-house standards for how to represent certain kinds of data, and practitioners don't realize that these conventions are not followed universally. I had to ignore a few apparently high-quality algorithms simply because I could not figure out how to supply data to their code. For many other algorithms, I had to write custom data exporters and data importers. Again, an algorithm won't get quoted if it can't be run.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Make it Automatable&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Another thing I see frequently are very fancy graphical user interfaces for scientific code. The only thing that breaks faster than compiled language extensions are GUI programs. GUIs are necessarily complex, and therefore hard to debug. And worse yet, if the code can only be run in a GUI, it can't be automated, and I won't be able to compare its performance in a big experiment with hundreds of runs. In effect, GUIs make an algorithm non-reproducible. If a GUI needs to be included in the code, it should at least be made optional.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Do Release Code&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;However, more importantly than anything I said so far: &lt;em&gt;Do&lt;/em&gt; release source code for your algorithm. Nothing is more wasteful than reading about an amazing algorithm that I can't try out. If no source code is released, it is not reproducible, it can't be compared to other algorithms in the field, and it might as well not have been published.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Sun, 14 May 2017 16:05:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-05-14-scientific-code.html</guid></item><item><title>Gucci vs the Restaurant Who Must Not Be Named</title><link>https://stop.zona-m.net/2017/05/gucci-vs-the-restaurant-who-must-not-be-named/</link><description>&lt;p&gt;&lt;em&gt;(this is a translated excerpt of &lt;a href="http://gilioli.blogautore.espresso.repubblica.it/2017/05/12/uno-che-si-chiama-gucci/"&gt;&amp;ldquo;Uno che si chiama Gucci&amp;rdquo;&lt;/a&gt; by Alessandro Gilioli)&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt="Gucci vs the Restaurant Who Must Not Be Named /img/gidoc-restaurant-prato-menu.png" src="https://stop.zona-m.net//img/gidoc-restaurant-prato-menu.png" width="100%" /&gt;
&lt;/figure&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 14 May 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/05/gucci-vs-the-restaurant-who-must-not-be-named/</guid></item><item><title>Repainting</title><link>https://johnj.com/posts/repainting/</link><description>&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_6813.JPG"&gt;&lt;img class="resize" src="https://johnj.com/IMG_6813_hu_17460ef1ae2e9787.JPG" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Painting in Progress - from imagination
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
As I return to the painting on my easel, reworking both the major
figures and probably everything else as well, I am put to mind of a
lesson by a former teacher, &lt;a href="http://www.carolpylant.com/HOME.html"&gt;Carol Pylant&lt;/a&gt;.  She told me to be paint
over the edges of my foreground figures when working on backgrounds,
so the backgrounds don’t get too “stiff.” Of course, this applies not
just to edges.  “If you painted it once, you can paint it again,” she
said.&lt;/p&gt;
&lt;p&gt;
There are some variants to this last phrase which come to mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you painted it once, and are afraid you won’t be able to paint it
as well or better, you probably need more practice.&lt;/li&gt;
&lt;li&gt;If you painted it once, and had fun doing so, you can have fun doing
it again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think a major source of strength in a drawing or a painting (or a
computer program, for that matter) is the ability of letting go of
work completed so that better work can emerge.&lt;/p&gt;
&lt;p&gt;
This was vividly reinforced for me when I watched &lt;a href="http://steven-assael-mr8x.squarespace.com/work"&gt;Steven Assael&lt;/a&gt; paint
for two days in February.  He built up beautiful passages again and
again and destroyed them… mostly.  Traces remained, in the layers of
marks and paint and texture.  Same thing, last month, watching him
draw the figure, and encouraging students to make radical changes even
in the last few minutes of a pose… destroying what was there to open
a path for something much better to emerge.  As time goes on I can see
that opening that path over and over again is absolutely critical for
successful work. Destruction is often a prerequisite for successful
creation.&lt;/p&gt;</description><author>John Jacobsen</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/repainting/</guid></item><item><title>About Me</title><link>https://serhack.me/about/</link><description>Despite his nickname, SerHack is not an hacker.
SerHack (SeərHæck) is a security researcher, developer, and writer. He started his career with development of payment gateways for a popular cryptocurrency. Since then he has reported several bugs and security issues, many of them CVE. He is widely known for reporting the MEGA incident and conducts different malware analyses. Additionally, SerHack contributes to the Monero project – a cryptocurrency focused on privacy. -&lt;a href="https://serhack.me/about/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/about/</guid></item><item><title>Donate to SerHack</title><link>https://serhack.me/donate/</link><description>This page is for people who like my work and would like to boost my projects. At the moment, I&amp;rsquo;m writing the second edition of &amp;ldquo;Mastering Monero&amp;rdquo; and a new resource named &amp;ldquo;Breaking Cryptocurrencies&amp;rdquo;.
I have several ideas in my mind that needs funding, so please don&amp;rsquo;t hesitate to contact me for more information. Thanks to your support, I&amp;rsquo;ve been able to realize this blog and the books I&amp;rsquo;ve mentioned earlier. -&lt;a href="https://serhack.me/donate/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/donate/</guid></item><item><title>Subdivision Surfaces and Displacement Mapping</title><link>https://blog.yiningkarlli.com/2017/05/subdivision-and-displacement.html</link><description>&lt;p&gt;Two standard features that every modern production renderer supports are &lt;a href="https://en.wikipedia.org/wiki/Subdivision_surface"&gt;subdivision surfaces&lt;/a&gt; and some form of &lt;a href="https://en.wikipedia.org/wiki/Displacement_mapping"&gt;displacement mapping&lt;/a&gt;.
As we’ll discuss a bit later in this post, these two features are usually very closely linked to each other in both usage and implementation.
Subdivision and displacement are crucial tools for representing detail in computer graphics; from both a technical and authorship point of view, being able to represent more detail than is actually present in a mesh is advantageous.
Applying detail at runtime allows for geometry to take up less disk space and memory than would be required if all detail was baked into the geometry, and artists often like the ability to separate broad features from high frequency detail.&lt;/p&gt;

&lt;p&gt;I recently added support for subdivision surfaces and for both scalar and vector displacement to Takua; Figure 1 shows an ocean wave was rendered using vector displacement in Takua.
The ocean surface is entirely displaced from just a single plane!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/displacement_ocean_0.jpg"&gt;&lt;img alt="Figure 1: An ocean surface modeled as a flat plane and rendered using vector displacement mapping." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/displacement_ocean_0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both subdivision and displacement originally came from the world of rasterization rendering, where on-the-fly geometry generation was historically both easier to implement and more practical/plausible to use.
In rasterization, geometry is streamed to through the renderer and drawn to screen, so each individual piece of geometry could be subdivided, tessellated, displaced, splatted to the framebuffer, and then discarded to free up memory. 
Old REYES Renderman was famously efficient at rendering subdivision surfaces and displacement surfaces for precisely this reason.
However, in naive ray tracing, rays can intersect geometry at any moment in any order.
Subdividing and displacing geometry on the fly for each ray and then discarding the geometry is insanely expensive compared to processing geometry once across an entire framebuffer.
The simplest solution to this problem is to just subdivide and displace everything up front and keep it all around in memory during ray tracing.
Historically though, just caching everything was never a practical solution since computers simply didn’t have enough memory to keep that much data around.
As a result, past research work put significant effort into more intelligent ray tracing architectures that made on-the-fly subdivision/displacement affordable again; notable advancements include geometry caching for ray tracing &lt;a href="http://graphics.stanford.edu/papers/displace"&gt;[Pharr and Hanrahan 1996]&lt;/a&gt;, direct ray tracing of displacement mapped triangles &lt;a href="https://doi.org/10.1007/978-3-7091-6303-0_28"&gt;[Smits et al. 2000]&lt;/a&gt;, reordered ray tracing &lt;a href="https://jo.dreggn.org/home/2010_rayes.pdf"&gt;[Hanika et al. 2010]&lt;/a&gt;, and GPU ray traced vector displacement &lt;a href="https://www.crcpress.com/GPU-Pro-6-Advanced-Rendering-Techniques/Engel/p/book/9781482264616"&gt;[Harada 2015]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the past five years or so though, the story on ray traced displacement has changed.
We now have machines with gobs and gobs of memory (at a number of studios, renderfarm nodes with 256 GB of memory or more is not unusual anymore).
As a result, ray traced renderers don’t need to be nearly as clever anymore about managing displaced geometry; a combination of camera-adaptive tessellation and a simple geometry cache with a least-recently-used eviction strategy is often enough to make ray traced displacement practical.
Heavy displacement is now common in the workflows for a number of production pathtracers, including Arnold, Renderman/RIS, Vray, Corona, Hyperion, Manuka, etc.
With the above in mind, I tried to implement subdivision and displacement in Takua as simply as I possibly could.&lt;/p&gt;

&lt;p&gt;Takua doesn’t have any concept of an eviction strategy for cached tessellated geometry; the hope is to just fit in memory and be as efficient as possible with what memory is available.
Admittedly, since Takua is just my hobby renderer instead of a fully in-use production renderer, and I have personal machines with 48 GB of memory, I didn’t think particularly hard about cases where things don’t fit in memory.
Instead of tessellating on-the-fly per ray or anything like that, I simply pre-subdivide and pre-displace everything upfront during the initial scene load.
Meshes are loaded, subdivided, and displaced in parallel with each other.
If Takua discovers that all of the subdivided and displaced geometry isn’t going to fit in the allocated memory budget, the renderer simply quits.&lt;/p&gt;

&lt;p&gt;I should note that Takua’s scene format distinguishes between a mesh and a geom; a mesh is the raw vertex/face/primvar data that makes up a surface, while a geom is an object containing a reference to a mesh along with transformation matrices, shader bindings, and so on and so forth.
This separation between the mesh data and the geometric object allows for some useful features in the subdivision/displacement system.
Takua’s scene file format allows for binding subdivision and displacement modifiers either on the shader level, or per each geom.
Bindings at the geom level override bindings on the shader level, which is useful for authoring since a whole bunch of objects can share the same shader but then have individual specializations for different subdivision rates and different displacement maps and displacement settings.
During scene loading, Takua analyzes what subdivisions/displacements are required for which meshes by which geoms, and then de-duplicates and aggregates any cases where different geoms want the same subdivision/displacement for the same mesh.
This de-duplication even works for instances (I should write a separate post about Takua’s approach to instancing someday…).&lt;/p&gt;

&lt;p&gt;Once Takua has put together a list of all meshes that require subdivision, meshes are subdivided in parallel.
For Catmull-Clark subdivision &lt;a href="https://www.sciencedirect.com/science/article/abs/pii/0010448578901100"&gt;[Catmull and Clark 1978]&lt;/a&gt;, I rely on &lt;a href="https://graphics.pixar.com/opensubdiv/docs/intro.html"&gt;OpenSubdiv&lt;/a&gt; for calculating subdivision &lt;a href="https://graphics.pixar.com/opensubdiv/docs/far_overview.html#far-stenciltable"&gt;stencil tables&lt;/a&gt; &lt;a href="https://dl.acm.org/doi/10.1145/166117.166121"&gt;[Halstead et al. 1993]&lt;/a&gt; for feature adaptive subdivision &lt;a href="https://dl.acm.org/doi/10.1145/2077341.2077347"&gt;[Nießner et al. 2012]&lt;/a&gt;, evaluating the stencils, and final tessellation.
As far as I can tell, stencil calculation in OpenSubdiv is single threaded, so it can get fairly slow on really heavy meshes.
Stencil evaluation and final tessellation is super fast though, since OpenSubdiv provides a number of &lt;a href="https://graphics.pixar.com/opensubdiv/docs/osd_overview.html#limit-stencil-evaluation"&gt;parallel evaluators&lt;/a&gt; that can run using a variety of backends ranging from TBB on the CPU to CUDA or OpenGL compute shaders on the GPU.
Takua currently relies on OpenSubdiv’s TBB evaluator.
One really neat thing about the stencil implementation in OpenSubdiv is that the stencil calculation is dependent on only the topology of the mesh and not individual primvars, so a single stencil calculation can then be reused multiple times to interpolate many different primvars, such as positions, normals, uvs, and more.
Currently Takua doesn’t support creases; I’m planning on adding crease support later.&lt;/p&gt;

&lt;p&gt;No writing about subdivision surfaces is complete without a picture of a cube being subdivided into a sphere, so Figure 2 shows a render of a cube with subdivision levels 0, 1, 2, and 3, going from left to right.
Each subdivided cube is rendered with a procedural wireframe texture that I implemented to help visualize what was going on with subdivision.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/subdcube.jpg"&gt;&lt;img alt="Figure 2: A cube with 0, 1, 2, and 3 subdivision levels, going from left to right." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/subdcube.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each subdivided mesh is placed into a new mesh; base meshes that require multiple subdivision levels for multiple different geoms get one new subdivided mesh per subdivision level.
After all subdivided meshes are ready, Takua then runs displacement.
Displacement is parallelized both by mesh and within each mesh.
Also, Takua supports both on-the-fly displacement and fully cached displacement, which can be specified per shader or per geom.
If a mesh is marked for full caching, the mesh is fully displaced, stored as a separate mesh from the undisplaced subdivision mesh, and then a BVH is built for the displaced mesh.
If a mesh is marked for on-the-fly displacement, the displacement system calculates each displaced face, then calculates the bounds for that face, and then discards the face.
The displaced bounds are then used to build a tight BVH for the displaced mesh without actually having to store the displaced mesh itself; instead, just a reference to the undisplaced subdivision mesh has to be kept around.
When a ray traverses the BVH for an on-the-fly displacement mesh, each BVH leaf node specifies which triangles on the undisplaced mesh need to be displaced to produce final polys for intersection and then the displaced polys are intersected and discarded again.
For the scenes in this post, on-the-fly displacement seems to be about twice as slow as fully cached displacement, which is to be expected, but if the same mesh is displaced multiple different ways, then there are correspondingly large memory savings.
After all displacement has been calculated, Takua goes back and analyzes which base meshes and undisplaced subdivision meshes are no longer needed, and frees those meshes to reclaim memory.&lt;/p&gt;

&lt;p&gt;I implemented support for both scalar displacement via regular grayscale texture maps, and vector displacement from OpenEXR textures.
The ocean render from the start of this post uses vector displacement applied to a single plane.
Figure 3 shows another angle of the same vector displaced ocean:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/displacement_ocean_1.jpg"&gt;&lt;img alt="Figure 3: Another view of the vector displaced ocean surface from Figure 1. The ocean surface has a dielectric refractive material complete with colored attenuated transmission. A shallow depth of field is used to lend added realism." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/displacement_ocean_1.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For both ocean renders, the vector displacement OpenEXR texture is borrowed from Autodesk, who generously provide it as part of an &lt;a href="http://area.autodesk.com/learning/rendering-an-ocean-with-displacement1"&gt;article&lt;/a&gt; about vector displacement in Arnold.
The renders are lit with a skydome using &lt;a href="http://hdri-skies.com/shop/hdri-sky-193/"&gt;hdri-skies.com’s HDRI Sky 193&lt;/a&gt; texture.&lt;/p&gt;

&lt;p&gt;For both scalar and vector displacement, the displacement amount from the displacement texture can be controlled by a single scalar value.
Vector displacement maps are assumed to be in a local tangent space; which axis is used as the basis of the tangent space can be specified per displacement map.
Figure 4 shows three dirt shaderballs with varying displacement scaling values.
The leftmost shaderball has a displacement scale of 0, which effectively disables displacement.
The middle shaderball has a displacement scale of 0.5 of the native displacement values in the vector displacement map.
The rightmost shaderball has a displacement scale of 1.0, which means just use the native displacement values from the vector displacement map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/displacementscales.jpg"&gt;&lt;img alt="Figure 4: Dirt shaderballs with displacement scales of 0.0, 0.5, and 1.0, going from left to right." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/displacementscales.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 5 shows a closeup of the rightmost dirt shaderball from Figure 4.
The base mesh for the shaderball is relatively low resolution, but through subdivision and displacement, a huge amount of geometric detail can be added in-render.
In this case, the shaderball is tessellated to a point where each individual micropolygon is at a subpixel size.
The model for the shaderball is based on &lt;a href="http://bertrand-benoit.com/blog/free-mat-test-scene/"&gt;Bertrand Benoit&lt;/a&gt;’s shaderball.
The displacement map and other textures for the dirt shaderball are from &lt;a href="https://megascans.se"&gt;Quixel’s Megascans&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/dirtsphere.jpg"&gt;&lt;img alt="Figure 5: Closeup of the dirt shaderball from Figure 4. In this render, the shaderball is tessellated and displaced to a subpixel resolution." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/dirtsphere.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One major challenge with displacement mapping is cracking.
Cracking occurs when adjacent polygons displace the same shared vertices different ways for each polygon.
This can happen when the normals across a surface aren’t continuous, or if there is a discontinuity in either how the displacement texture is mapped to the surface, or in the displacement texture itself.
I implemented an optional, somewhat brute-force solution to displacement cracking.
If crack removal is enabled, Takua analyzes the mesh at displacement time and records how many different ways each vertex in the mesh has been displaced by different faces, along with which faces want to displace that vertex.
After an initial displacement pass, the crack remover then goes back and for every vertex that is displaced more than one way, all of the displacements are averaged into a single displacement, and all faces that use that vertex are updated to share the same averaged result.
This approach requires a fair amount of bookkeeping and pre-analysis of the displaced mesh, but it seems to work well.
Figure 6 is a render of two cubes with geometric normals assigned per face.
The two cubes are displaced using the same checkerboard displacement pattern, but the cube on the left has crack removal disabled, while the cube on the right has crack removal enabled:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/crackedcube.jpg"&gt;&lt;img alt="Figure 6: Displaced cubes with and without crack elimination." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/crackedcube.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In most cases, the crack removal system seems to work pretty well.
However, the system isn’t perfect; sometimes, stretching artifacts can appear, especially with surfaces with a textured base color.
This stretching happens because the crack removal system basically stretches micropolygons to cover the crack.
This texture stretching can be seen in some parts of the shaderballs in Figures 5, 7, and 8 in this post.&lt;/p&gt;

&lt;p&gt;Takua automatically recalculates normals for subdivided/displaced polygons.
By default, Takua simply uses the geometric normal as the shading normal for displaced polygons; however, an option exists to calculate smooth normals for the shading normals as well.
I chose to use geometric normals as the default with the hope that for subpixel subdivision and displacement, a different shading normal wouldn’t be as necessary.&lt;/p&gt;

&lt;p&gt;In the future, I may choose to implement my own subdivision library, and I should probably also put more thought into some kind of proper combined tessellation cache and eviction strategy for better memory efficiency.
For now though, everything seems to work well and renders relatively efficiently; the non-ocean renders in this post all have sub-pixel subdivision with millions of polygons and each took several hours to render at 4K (3840x2160) resolution on a machine with dual Intel Xeon X5675 CPUs (12 cores total).
The two ocean renders I let run overnight at 1080p resolution; they took longer to converge mostly due to the depth of field.
All renders in this post were shaded using a new, vastly improved shading system that I’ll write about at a later point.
Takua can now render a lot more complexity than before!&lt;/p&gt;

&lt;p&gt;In closing, I rendered a few more shaderballs using various displacement maps from the Megascans library, seen in Figures 7 and 8.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/shaderspheres_0.jpg"&gt;&lt;img alt="Figure 7: A pebble sphere and a leafy sphere. Note the overhangs on the leafy sphere, which are only possible using vector displacement." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/shaderspheres_0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/May/shaderspheres_1.jpg"&gt;&lt;img alt="Figure 8: A compacted sand sphere and a stone sphere. Unfortunately, there is some noticeable texture stretching on the compacted sand sphere where crack removal occured." src="https://blog.yiningkarlli.com/content/images/2017/May/preview/shaderspheres_1.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="references"&gt;References&lt;/h2&gt;

&lt;p&gt;Edwin E. Catmull and James H. Clark. 1978. &lt;a href="https://www.sciencedirect.com/science/article/abs/pii/0010448578901100"&gt;Recursively Generated B-spline Surfaces on Arbitrary Topological Meshes&lt;/a&gt;. &lt;em&gt;Computer-Aided Design&lt;/em&gt; 10, 6 (Nov. 1978), 350-355.&lt;/p&gt;

&lt;p&gt;Mark Halstead, Michael Kass, and Tony DeRose. 1993. &lt;a href="https://dl.acm.org/doi/10.1145/166117.166121"&gt;Efficient, Fair Interpolation using Catmull-Clark Surfaces&lt;/a&gt;. In &lt;em&gt;Proc. of SIGGRAPH (SIGGRAPH 1993)&lt;/em&gt;. 35-44.&lt;/p&gt;

&lt;p&gt;Johannes Hanika, Alexander Keller, and Hendrik P A Lensch. 2010. &lt;a href="https://dl.acm.org/citation.cfm?id=1839241"&gt;Two-Level Ray Tracing with Reordering for Highly Complex Scenes&lt;/a&gt;. In &lt;em&gt;Proc. of Graphics Interfaces (GI 2010)&lt;/em&gt;. 145-152.&lt;/p&gt;

&lt;p&gt;Takahiro Harada. 2015. &lt;a href="https://www.crcpress.com/GPU-Pro-6-Advanced-Rendering-Techniques/Engel/p/book/9781482264616"&gt;Rendering Vector Displacement Mapped Surfaces in a GPU Ray Tracer&lt;/a&gt;. In &lt;em&gt;GPU Pro 6&lt;/em&gt;. 459-474.&lt;/p&gt;

&lt;p&gt;Matthias Nießner, Charles Loop, Mark Meyer, and Tony DeRose. 2012. &lt;a href="https://dl.acm.org/doi/10.1145/2077341.2077347"&gt;Feature Adaptive GPU Rendering of Catmull-Clark Subdivision Surfaces&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 31, 1 (Jan. 2012), Article 6.&lt;/p&gt;

&lt;p&gt;Matt Pharr and Pat Hanrahan. 1996. &lt;a href="http://graphics.stanford.edu/papers/displace/"&gt;Geometry Caching for Ray-Tracing Displacement Maps&lt;/a&gt;. In &lt;em&gt;Proc. of Eurographics Workshop on Rendering (Rendering Techniques 1996)&lt;/em&gt;. 31-40.&lt;/p&gt;

&lt;p&gt;Brian Smits, Peter Shirley, and Michael M. Stark. 2000. &lt;a href="https://doi.org/10.1007/978-3-7091-6303-0_28"&gt;Direct Ray Tracing of Displacement Mapped Triangles&lt;/a&gt;.  In &lt;em&gt;Proc. of Eurographics Workshop on Rendering (Rendering Techniques 2000)&lt;/em&gt;. 307-318.&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2017/05/subdivision-and-displacement.html</guid></item><item><title>Millennials are a myth</title><link>https://yasha.solutions/millennials-are-a-myth/</link><description>Millenials (people born after 1980 and before 2000) are defined as :
 lazy entitled unattached not motivated by money want more holidays more horseshit  The point of this post is to share a truth more and more commonly agreed upon: Millenials are not real.
“Millennials” as a concept is mainly a huge pile of crap.
And I just stumbled upon wonderful talk by Adam Conover, and I think he made the point pretty brilliantly so please what the talk down there.</description><author>Yasha Solutions</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/millennials-are-a-myth/</guid></item><item><title>Time Pills tracks, stems, presets, loops and midi</title><link>https://muffinman.io/blog/time-pills-tracks-stems/</link><description>&lt;article class="article"&gt;&lt;p&gt;Friends of mine from the band &lt;a href="https://soundcloud.com/timepills"&gt;Time Pills&lt;/a&gt; opensourced bunch of their tracks. You can find them on &lt;a href="https://github.com/nndmlsvc/time-pills"&gt;GitHub&lt;/a&gt;. They are looking forward to having them remixed by creative people and sharing it with the world&lt;/p&gt;
&lt;p&gt;Repo contains all of the tracks, stems, presets, loops and even midi files.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Time Pills tracks, stems, presets, loops and midi" height="2048" src="./timepills.jpg" width="2048" /&gt;&lt;/figure&gt;
&lt;p&gt;Be sure to check them on &lt;a href="https://soundcloud.com/timepills"&gt;SoundCloud&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/time-pills-tracks-stems/</guid></item><item><title>2017-05-14</title><link>https://ho.dges.online/pictures/2017-05-14/</link><description>&lt;p&gt;Sign in the Royal Hospital, Glasgow.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-05-14/</guid></item><item><title>A better email template for icinga2</title><link>https://shyamjos.com/icinga2-html-template/</link><description>&lt;p&gt;I have created a very simple HTML email alert Template for Icinga 2 to replace the default boring text-based email alert. This template can be easily installed by replacing existing alert scripts inside /etc/icinga2/scripts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I have replaced mail command with mutt due to an incompatibility of options among different Linux distributions. Also, I have added new color highlight feature for different states (ok=green,warning=orange and critical=red).&lt;/p&gt;
&lt;h2 class="relative group" id="screenshots"&gt;Screenshots &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#screenshots"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;






 
 
&lt;figure&gt;&lt;img alt="Icinga2 email alert screenshot" class="mx-auto my-0 rounded-md" src="https://shyamjos.com/assets/img/icinga2/html-template-for-icinga.png" /&gt;
&lt;/figure&gt;








 
 
&lt;figure&gt;&lt;img alt="Icinga2 email alert screenshot" class="mx-auto my-0 rounded-md" src="https://shyamjos.com/assets/img/icinga2/icinga-2-html-email-template.png" /&gt;
&lt;/figure&gt;








 
 
&lt;figure&gt;&lt;img alt="Icinga2 email alert screenshot" class="mx-auto my-0 rounded-md" src="https://shyamjos.com/assets/img/icinga2/icinga-html-email.png" /&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 class="relative group" id="prerequisite"&gt;Prerequisite &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#prerequisite"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Make Sure mutt package is installed on your server&lt;/p&gt;
&lt;h2 class="relative group" id="how-to-install"&gt;How to install &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" href="#how-to-install"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Backup existing script files (mail-service-notification.sh and mail-host-notification.sh) inside /etc/icinga2/scripts&lt;/li&gt;
&lt;li&gt;Download the scripts from this github repo and edit the “Variables for HTML Template” section in both scripts&lt;/li&gt;
&lt;li&gt;Now replace the existing scripts with the new ones and Send a custom notification to test new HTML email template.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have any issues, please &lt;a href="https://github.com/shyamjos/HTML-email-template-for-Icinga-2/issues" rel="noreferrer" target="_blank"&gt;report it here&lt;/a&gt;&lt;/p&gt;</description><author>Shyam Jos</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://shyamjos.com/icinga2-html-template/</guid></item><item><title>Finding Idylwild Park</title><link>https://jasoneckert.github.io/myblog/finding-idylwild-park/</link><description>&lt;p&gt;&lt;img alt="Idylwild1" src="idylwild1.png#center" title="Idylwild1" /&gt;&lt;/p&gt;
&lt;p&gt;I grew up (and currently live) in the city of Cambridge in Ontario, Canada.  The city was formed when 3 smaller towns (Hespeler, Preston and Galt) amalgamated in 1973, but the towns have a rich history as some of the key centers for industry in Upper Canada during the 1800s and early 1900s.&lt;/p&gt;
&lt;p&gt;When I was Googling something related to the new light rail transit system currently being installed in the region, I came across a Wikipedia page where I learned that there was an electric passenger railway between Hespeler, Preston and Galt from the late 1800s until 1955 called the Galt, Preston &amp;amp; Hespeler (GP&amp;amp;H) Street Railway. To encourage people to use the train on the weekends, the company that owned the railway opened a recreational park between Hespeler and Preston called Idylwild Park.  The entrance to the park is shown in the picture at the top of this blog post, and the postcard below shows that the entrance was right next to the railway tracks (with a short bypass section):&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Sun, 14 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/finding-idylwild-park/</guid></item><item><title>Zero-crossing logic for robust meshing</title><link>https://mattkeeter.com/blog/2017-05-13-implicit-zeros</link><description/><author>Matt Keeter</author><pubDate>Sat, 13 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2017-05-13-implicit-zeros</guid></item><item><title>The Abercrombie Farm</title><link>https://solomon.io/the-abercrombie-farm/</link><description>Photos from my last visit to my grandmother's house outside Greenville, SC.</description><author>Sam Solomon</author><pubDate>Sat, 13 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/the-abercrombie-farm/</guid></item><item><title>justAnExample – Newsletter email confirmation – Powazek</title><link>https://yasha.solutions/just-an-example-newsletter-email-confirmation-powazek/</link><description>justAnExample is a series where I share some interesting UX / UI and smart copy for your inspiration (and my archive of references).
Here today we have a newsletter done by Derek Powazek– veteran startup guy now growing vegetables in a farm.
      Why this is good :
 Transparency Empathy Humor   Transparency
Sharing his lack of clarity, being very honest from the beginning is a good way to get your people to trust you.</description><author>Yasha Solutions</author><pubDate>Fri, 12 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/just-an-example-newsletter-email-confirmation-powazek/</guid></item><item><title>Python Workload now officially supported in Visual Studio 2017</title><link>https://nicolaiarocci.com/python-workload-now-officially-supported-in-visual-studio-2017/</link><description>&lt;p&gt;Visual Studio 2017 just received an update (&lt;a href="https://www.visualstudio.com/en-us/news/releasenotes/vs2017-relnotes"&gt;version 15.2&lt;/a&gt;). Among other
nice things, this update brings full support for Python back into the official
release of VS2017. As you might recall (see my &lt;a href="https://nicolaiarocci.com/python-support-in-visual-studio-2017-or-the-lack-thereof/"&gt;old whiny post&lt;/a&gt;), previously
Python was only available with Visual Studio 2017 Preview (a separate install).&lt;/p&gt;
&lt;p&gt;I just upgraded my copy of Visual Studio, added the Python Development Workload
to it via the VS Installer, and finally (and very happily) uninstalled the
whole Visual Studio Preview thingie.  Alleluja!&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 11 May 2017 17:16:06 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/python-workload-now-officially-supported-in-visual-studio-2017/</guid></item><item><title>A better OMX Player Controller</title><link>https://peanball.net/2017/05/a-better-python-omxplayer-controller/</link><description>&lt;p&gt;I&amp;rsquo;m using &lt;code&gt;omxplayer&lt;/code&gt; on the Raspberry Pi for video playback because it utilizes the Raspberry Pi&amp;rsquo;s hardware video decoding.
Because the front-end is a separate application, I just need to remote control OMX Player to start and stop the video and figure out how far the video has played back already.&lt;/p&gt;</description><author>peanball.net</author><pubDate>Thu, 11 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://peanball.net/2017/05/a-better-python-omxplayer-controller/</guid></item><item><title>Call for testing: Nextcloud snap v11.0.3snap2</title><link>https://kyrofa.com/posts/call-for-testing-nextcloud-snap-v11-0-3snap2/</link><description>We&amp;rsquo;re getting ready to release a new version of the Nextcloud snap with a few new features, including:
 Supporting changing ports from the default 80/443. Supporting Samba shares.  We&amp;rsquo;d love this new version (particularly these new features) to get some exercise before we release it. Feel like helping? We&amp;rsquo;ve put together some smoke tests to get you started.
Please test all you can, but if you only have time to focus on the smoke tests covering the new features, that would still be very useful.</description><author>kyrofa's blog</author><pubDate>Thu, 11 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/call-for-testing-nextcloud-snap-v11-0-3snap2/</guid></item><item><title>VPN annoyances</title><link>https://peterlyons.com/problog/2017/05/vpn-annoyances/</link><description>&lt;p&gt;I've recently started using a VPN all the time (at least as much as possible). My more tinfoily nerd friends all recommended &lt;a href="https://www.privateinternetaccess.com/"&gt;PIA&lt;/a&gt; so I signed up for that. There are some issues and frustrations I wasn't expecting so here's what I've seen so far.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extra-annoying captchas from ReCaptcha. It seems being on a VPN exit IP automatically classifies you for the most-frustrating setting of ReCaptcha. I've seen this even on PIA's own tech support form submission.&lt;/li&gt;
&lt;li&gt;ReCaptcha on browsing CloudFlare HTTPS sites. This one really shocked me. Just to browse (HTTPS GET) a site on cloudflare, I'm prompted to complete a captcha. I can barely stand captchas when I need to submit an important form, but just to read a site? No thanks. ⌘-w.&lt;/li&gt;
&lt;li&gt;NameCheap wouldn't let me log in. Site loaded but gave me error messages AS IF my password was wrong, which it wasn't, which caused me to change it several times, which didn't work, which caused me to open a support case wherein they asked if I was using a VPN told me to disconnect. What. The. Actual. Fuck? They seem to have since made this less-terrible but still WTF?&lt;/li&gt;
&lt;li&gt;Craigslist just straight up blocks all PIA exit IPs. Total dead end.&lt;/li&gt;
&lt;li&gt;PIA seems to not be that good about reconnecting when you close your laptop and open it in a different wifi network. The icon still shows it is connected but it is in fact not and you have to manually disconnect and reconnect to get back online.&lt;/li&gt;
&lt;li&gt;Google Drive does not seem to sync/connect when the VPN is active&lt;/li&gt;
&lt;li&gt;NetFlix geolocates your IP and restricts your access to content based on that country. So you see different titles available when VPNed verses not.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any pro tips to help out with this?&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 10 May 2017 22:47:39 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/05/vpn-annoyances/</guid></item><item><title>How to convert a PCL (Portable) project to NetStandard</title><link>https://nicolaiarocci.com/how-to-convert-a-pcl-portable-project-to-netstandard/</link><description>&lt;p&gt;I have been upgrading a few projects from their original PCL profiles (now
deemed obsolete) to the &lt;a href="https://docs.microsoft.com/it-it/dotnet/articles/standard/library"&gt;Net Standard&lt;/a&gt; platform specification. It turned out
to be a relatively straightforward process, but it does have its small hurdles,
especially so if in the meantime you also want to transition to the new,
streamlined, &lt;code&gt;.csproj&lt;/code&gt; format as the migration will leave you with a now
obsolete &lt;code&gt;project.json&lt;/code&gt; project. In this article, I will cover upgrading
a project from Portable Class Library to NetStandard. In a follow-up post,
I plan to write about the switch from &lt;code&gt;project.json&lt;/code&gt; to the new &lt;code&gt;.csproj&lt;/code&gt;
format.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Wed, 10 May 2017 10:47:05 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/how-to-convert-a-pcl-portable-project-to-netstandard/</guid></item><item><title>Raspberry Pi 3 as an emergency router</title><link>https://caiustheory.com/raspberry-pi-3-as-an-emergency-router/</link><description>&lt;p&gt;Given a dead router, how do you get back online whilst you wait for the replacement part to arrive? Grab a Raspberry Pi 3 off the shelf, along with a USB to Ethernet adapter and hey presto the internet works again.&lt;/p&gt;
&lt;p&gt;This is with a fibre modem (FTTC), using PPPoE to connect out. Plug the modem (WAN) into the RPi&amp;rsquo;s ethernet port, and plug the LAN switch into the USB adapter.&lt;/p&gt;
&lt;p&gt;First thing is to get the WAN link working, get it talking PPPoE to the ISP. Usually this will be configured in &lt;code&gt;/etc/ppp/pppoe.conf&lt;/code&gt; (depends on your linux distro). (That&amp;rsquo;ll require your username/password for your ISP usually too.)&lt;/p&gt;
&lt;p&gt;Get it up &amp;amp; connected, and make sure you can ping the internet from the RPi. Then it&amp;rsquo;s time to get the LAN working. Give it a static IP in the range you want shared out.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# /etc/network/interfaces
iface eth0 inet static
address 192.168.1.1
netmask 255.255.255.0
gateway 192.168.1.1
auto eth1
iface eth1 inet dhcp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Get a dhcp server running on the LAN connection,&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# /etc/dhcpcd.conf
interface eth0
static ip_address=192.168.1.1
static routers=192.168.1.1
static domain_name_servers=8.8.8.8,8.8.4.4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then it&amp;rsquo;s time to handle WAN -&amp;gt; LAN traffic and the reverse. Make sure you have packet forwarding enabled, and then setup the firewall to handle NAT and also keep out undesirable traffic.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sysctl net.ipv4.ip_forward&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -F
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -X
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -t nat -F
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -t nat -X
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -i lo -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -i eth0 -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -f -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iptables -A INPUT -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hey presto, you have a working emergency router. In testing I found my fibre connection (80/20Mb) was slower than the traffic the RPi could push, so didn&amp;rsquo;t notice any difference vs my normal router. (Although I did disable a bunch of automated stuff, so there was less contention on the WAN link.)&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Tue, 09 May 2017 23:55:00 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/raspberry-pi-3-as-an-emergency-router/</guid></item><item><title>Finding cheap Microserver G8 memory</title><link>https://caiustheory.com/finding-cheap-microserver-g8-memory/</link><description>&lt;p&gt;I&amp;rsquo;ve been wanting to drop more memory in my &lt;a href="https://www.hpe.com/uk/en/product-catalog/servers/proliant-servers/pip.hpe-proliant-microserver-gen8.5379860.html"&gt;HP Microserver G8&lt;/a&gt;, but hoping to find a cheaper alternative to buying new sticks from &lt;a href="http://uk.crucial.com/gbr/en/"&gt;Crucial&lt;/a&gt;. I needed one or two 4GB sticks, but they had to be ECC of course.&lt;/p&gt;
&lt;p&gt;At the time of writing (May 2017), &lt;a href="http://uk.crucial.com/gbr/en/compatible-upgrade-for/HP-Compaq/proliant-microserver-gen8"&gt;Crucial&amp;rsquo;s offering for the G8&lt;/a&gt; shows a 4GB stick to be £43.19, and an 8GB stick to be £81.59. This was a little more than I wanted to pay, but I was struggling to find anything on eBay or Amazon UK that I could be sure was ECC, and also cheaper.&lt;/p&gt;
&lt;p&gt;Eventually I wondered what else had compatible memory, after all this isn&amp;rsquo;t a bespoke machine. It should share the same memory specifications as plenty of other machines. The spec I was looking for was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DDR3 240-Pin UDIMM&lt;/li&gt;
&lt;li&gt;ECC&lt;/li&gt;
&lt;li&gt;1600Mhz (or faster)&lt;/li&gt;
&lt;li&gt;4 or 8GB sticks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After a little while of searching, I happened to find the previous Mac Pro (ie. the tower, not the trashcan) also uses that specification of memory. One quick search on eBay and up turned someone selling off his 4GB sticks where he&amp;rsquo;d upgrade his Mac Pro to 8GB sticks across the board. £29 for 2x 4GB sticks is better than I was hoping for, and once fitted in the Microserver they work flawlessly.&lt;/p&gt;
&lt;p&gt;(The onboard management software warns me that some processor features are disabled because I&amp;rsquo;m not using HP Approved memory, but it also logged that warning when I &lt;em&gt;was&lt;/em&gt; using HP Approved memory previously and the machine worked perfectly then. No doubt it&amp;rsquo;s to make IT Managers who don&amp;rsquo;t like warnings spend more money with HP.)&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Tue, 09 May 2017 22:03:00 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/finding-cheap-microserver-g8-memory/</guid></item><item><title>Bash script setup</title><link>https://caiustheory.com/bash-script-setup/</link><description>&lt;p&gt;Recently I&amp;rsquo;ve been writing a bunch of bash scripts for various things. As some up-front safety checks I&amp;rsquo;ve taken to opening every script with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&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 class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TRACE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; -o xtrace
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o errexit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o nounset
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o noclobber
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Other things I&amp;rsquo;m also trying to be good about doing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;using &lt;code&gt;readonly&lt;/code&gt; when declaring variables which shouldn&amp;rsquo;t be mutated&lt;/li&gt;
&lt;li&gt;Trapping errors using an error function, and cleaning up anything temporary in there&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And some useful reading I ran across in my quest to level up bash-scripts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://redsymbol.net/articles/bash-exit-traps/"&gt;Bash Exit Traps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://redsymbol.net/articles/unofficial-bash-strict-mode/"&gt;Use the unofficial Bash Strict Mode&lt;/a&gt; (Yes, &lt;em&gt;two&lt;/em&gt; posts from &lt;a href="http://redsymbol.net/"&gt;http://redsymbol.net/&lt;/a&gt;. Well worth reading.)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jvns.ca/blog/2017/03/26/bash-quirks/"&gt;Bash scripting quirks &amp;amp; safety tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.bash-hackers.org/"&gt;Bash hackers wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Caius Theory</author><pubDate>Tue, 09 May 2017 21:23:58 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/bash-script-setup/</guid></item><item><title>How to build a solar panel</title><link>http://www.nuke24.net/plog/23.html</link><description>There's a recipe diagram and some notes on the superiority of GIMP over actual vector graphics software</description><author>TOGoS's Project Log</author><pubDate>Tue, 09 May 2017 21:13:37 GMT</pubDate><guid isPermaLink="true">http://www.nuke24.net/plog/23.html</guid></item><item><title>Finding an Edge</title><link>https://josh.works/finding-an-edge</link><description>&lt;p&gt;These last two weeks have been the hardest, or the most frustrating, of my time at Turing so far.&lt;/p&gt;

&lt;p&gt;I’ve been put a little off-balance by this difficulty, and I think I’m close to uncovering some useful tidbit or idea that will serve me well, and might serve someone else too.&lt;/p&gt;

&lt;p&gt;Several different people warned me that&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mod 3 is just like mod 1 in terms of difficulty&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wasn’t sure what to make of that, because Mod 1 wasn’t too bad of a struggle. I think I gave myself a bad case of the “mismatched expectations”.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id="expectations"&gt;Expectations&lt;/h2&gt;

&lt;p&gt;Often when something seems off, a good place to start is to check your assumptions. So, I figured I’d look through mine about how I thought the last two weeks would go. What were my assumptions?&lt;/p&gt;

&lt;h3 id="my-technical-understanding-is-sufficient-to-grasp-the-new-material-and-implement-in-a-project"&gt;My technical understanding is sufficient to grasp the new material and implement in a project&lt;/h3&gt;

&lt;p&gt;This week we’ve unpacked a few sizable new topics:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;oAuth/OmniAuth for user authentication (against Twitter and Github)&lt;/li&gt;
  &lt;li&gt;Using Figaro to protect sensitive environment variables&lt;/li&gt;
  &lt;li&gt;Using Faraday to handle all the HTTP traffic&lt;/li&gt;
  &lt;li&gt;OmniAuth’s stubs/testing tools&lt;/li&gt;
  &lt;li&gt;VCR to record API responses, so every time we run our tests we’re not pounding a remote API&lt;/li&gt;
  &lt;li&gt;Stubbing out all the necessary user information so we can write detailed tests, using OmniAuth config settings, VCRs, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Turns out picking up this all, weaving it together, and applying to a project is hard.&lt;/p&gt;

&lt;p&gt;I’ve not mastered this content the same that I feel like I’ve mastered other notions in the program.&lt;/p&gt;

&lt;p&gt;This is not the end of the world, but it didn’t match my (unreasonable) expectations.&lt;/p&gt;

&lt;h3 id="id-be-the-anchor-in-any-group-work"&gt;I’d be the “anchor” in any group work&lt;/h3&gt;

&lt;p&gt;I’ve tried to generally be the “strong” contributor to group projects, and so far in Turing, I have been.&lt;/p&gt;

&lt;p&gt;Then this last one around, I felt like I was dragging, holding my partner back. I learned a lot, but I’d hoped that there was less to learn along the way. To her credit (and in my defense) I think she’s one of the sharpest students in the cohort, so it’s &lt;em&gt;possible&lt;/em&gt; that if I were paired with someone else, my contributions would have seemed more significant.&lt;/p&gt;

&lt;p&gt;That whole first week I felt off. Sleep deprived (dumb!) and a bit off-kilter.&lt;/p&gt;

&lt;h2 id="learnings-from-the-weeks"&gt;Learnings from the weeks&lt;/h2&gt;

&lt;h3 id="trust-the-process"&gt;Trust the process&lt;/h3&gt;

&lt;p&gt;I’ve still got what seems to be a passable system for gaining new (and complex) information.&lt;/p&gt;

&lt;p&gt;I started feeling underwater when I stopped following it.&lt;/p&gt;

&lt;p&gt;I can step back, return to my colorful notes and diagrams, rely on repetition and memorization and playing with the same notion quite a bit until it clicks and I can fit it into the larger product.&lt;/p&gt;

&lt;p&gt;Feeling a few steps behind is nothing in the grand scheme of things.&lt;/p&gt;

&lt;p&gt;This week did not do irreparable damage to my employability (I don’t think) so there was no real penalty.&lt;/p&gt;

&lt;h2 id="lessons-to-retain-for-later"&gt;Lessons to retain for later&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Embrace uncertainty&lt;/li&gt;
  &lt;li&gt;Expect to learn a lot&lt;/li&gt;
  &lt;li&gt;Write it all down&lt;/li&gt;
  &lt;li&gt;Repetition repetition repetition&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Tue, 09 May 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/finding-an-edge</guid></item><item><title>On Cleaner Controllers</title><link>https://josh.works/cleaner-controllers</link><description>&lt;p&gt;A few days ago, I worked on a project that was mostly about serving up basic store data (modeled after Etsy) to an API.&lt;/p&gt;

&lt;p&gt;We had a few dozen end-points, and all responses were in JSON.&lt;/p&gt;

&lt;p&gt;Most of the action happened inside of our controllers, and as you might imagine, our &lt;code class="language-plaintext highlighter-rouge"&gt;routes.rb&lt;/code&gt; file was bananas.&lt;/p&gt;

&lt;p&gt;One of the instructors made an exceptionally simple suggestion, I was embarrassed to not have seen it.&lt;/p&gt;

&lt;p&gt;It was about nesting our controllers a bit better.&lt;/p&gt;

&lt;p&gt;For context, here’s our routes for our merchants objects, relationships, and analytics:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;defaults: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;format: :json&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:v1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:merchants&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"merchants/merchants"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchant_items#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchant_invoices#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"customers_with_pending_invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchant_pending_customers#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"favorite_customer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchant_favorite_customer#show"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchant_revenue#show"&lt;/span&gt;
        &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchants_most_items#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchants_most_revenue#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchants_revenue#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchants_find#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find_all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchants_find#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"random"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/merchants_random#show"&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nf"&gt;.&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;!--more--&gt;

&lt;p&gt;Look at all the references to &lt;code class="language-plaintext highlighter-rouge"&gt;merchant&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;merchants&lt;/code&gt;! Lets count: Twenty-Four uses of the word! Dang! And this is in JUST the endpoints related to merchants! This same replication exists in our items, customers, invoices, and more.&lt;/p&gt;

&lt;p&gt;It’s also clunky to read. Every single merchants controller in the collection starts the same. That lowers the ratio of signal to noise, as a developer. No good.&lt;/p&gt;

&lt;p&gt;Hopefully someone moving through Turing behind us will take this chance for a really easy fix.&lt;/p&gt;

&lt;p&gt;And what is the fix?&lt;/p&gt;

&lt;p&gt;Here’s the file structure of all of our merchants controllers:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;├── api
│   └── v1
│       ├── merchants
│       │   ├── merchant_favorite_customer_controller.rb
│       │   ├── merchant_invoices_controller.rb
│       │   ├── merchant_items_controller.rb
│       │   ├── merchant_pending_customers_controller.rb
│       │   ├── merchant_revenue_controller.rb
│       │   ├── merchants_controller.rb
│       │   ├── merchants_find_controller.rb
│       │   ├── merchants_most_items_controller.rb
│       │   ├── merchants_most_revenue_controller.rb
│       │   ├── merchants_random_controller.rb
│       │   └── merchants_revenue_controller.rb
│       └── .
├── application_controller.rb
└── concerns
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s a quick mockup of what it &lt;em&gt;should&lt;/em&gt; be:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;├── api
│   └── v1
│       ├── merchants
│       │   ├── favorite_customer_controller.rb
│       │   ├── invoices_controller.rb
│       │   ├── items_controller.rb
│       │   ├── pending_customers_controller.rb
│       │   ├── revenue_controller.rb
│       │   ├── find_controller.rb
│       │   ├── most_items_controller.rb
│       │   ├── most_revenue_controller.rb
│       │   ├── random_controller.rb
│       │   └── revenue_controller.rb
│       └── merchants_controller.rb
├── application_controller.rb
└── concerns
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I moved the &lt;code class="language-plaintext highlighter-rouge"&gt;merchants_controller&lt;/code&gt; &lt;em&gt;up&lt;/em&gt; one level, to be outside of the merchants folder, and then everywhere else, I can infer that if a controller is in &lt;code class="language-plaintext highlighter-rouge"&gt;merchants/&lt;/code&gt;, it is related to the merchants class. (Rocket science!)&lt;/p&gt;

&lt;p&gt;Lets see what this does to our routes from above:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;defaults: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;format: :json&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:v1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:merchants&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"merchants"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/items#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/invoices#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"customers_with_pending_invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/pending_customers#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"favorite_customer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/favorite_customer#show"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue#show"&lt;/span&gt;
        &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_items#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_revenue#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/find#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find_all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/find#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"random"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/random#show"&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nf"&gt;.&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That looks a lot better. Half the number of references to &lt;code class="language-plaintext highlighter-rouge"&gt;merchants&lt;/code&gt; in the routes. Now… this requires renaming all the controllers, etc, so lets make that happen and see if our tests still pass.&lt;/p&gt;

&lt;p&gt;We’ll have to update a few files for each of these changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;routes.rb&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;the associated controller (fixing the class name of the controller)&lt;/li&gt;
  &lt;li&gt;The associated view, since the expected path is determined by the controller class name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, swap everything around, and all the tests still pass, and our routes are way more readable:&lt;/p&gt;

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

&lt;p&gt;So someone suggested a way to refactor even more.&lt;/p&gt;

&lt;p&gt;&lt;img alt="DRY out routes" src="https://d3vv6lp55qjaqc.cloudfront.net/items/0u2z2e1g131u0z450Q0I/%EF%BC%B6%EF%BD%85%EF%BD%92%EF%BD%89%EF%BD%86%EF%BD%89%EF%BD%85%EF%BD%84_%EF%BC%A1%EF%BD%83%EF%BD%83%EF%BD%8F%EF%BD%95%EF%BD%8E%EF%BD%94_on_Twitter____josh_works__sehurlburt_Nice__Btw__to_make_it_more_DRY__you_can_omit_path_reference__Rails_will_use_the_route_name_by_default__.png?v=036b7b13" /&gt;&lt;/p&gt;

&lt;p&gt;What’s that? A chance for even &lt;em&gt;more&lt;/em&gt; refactoring?&lt;/p&gt;

&lt;p&gt;I’ll take it. Back to &lt;code class="language-plaintext highlighter-rouge"&gt;routes.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I immediately was able to get down to relying on Rails’ “convention over configuration”, which basically means Rails is going to look in specific places for specific things. Like in the &lt;code class="language-plaintext highlighter-rouge"&gt;/controllers/api/v1/merchants/&lt;/code&gt; directory for most of my merchants controllers.&lt;/p&gt;

&lt;p&gt;I was able to get down to THIS with all my tests still passing:&lt;/p&gt;
&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;defaults: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;format: :json&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:v1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:merchants&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"merchants"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"items#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"invoices#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"customers_with_pending_invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/pending_customers#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"favorite_customer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/favorite_customer#show"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue_by_merchant#show"&lt;/span&gt;
        &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_items#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_revenue#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"find#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find_all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"find#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"random"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"random#show"&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But look at these lines:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"favorite_customer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/favorite_customer#show"&lt;/span&gt;
&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue_by_merchant#show"&lt;/span&gt;
&lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_items#index"&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_revenue#index"&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue#show"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Tests fail when I pull out those paths.&lt;/p&gt;

&lt;p&gt;When I run &lt;code class="language-plaintext highlighter-rouge"&gt;rake routes&lt;/code&gt;, this is my output:&lt;/p&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;api_v1_merchant_items GET  /api/v1/merchants/:merchant_id/items&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                           api/v1/items#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                      api_v1_merchant_invoices GET  /api/v1/merchants/:merchant_id/invoices&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                        api/v1/invoices#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
api_v1_merchant_customers_with_pending_invoices GET  /api/v1/merchants/:merchant_id/customers_with_pending_invoices&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt; api/v1/merchants/pending_customers#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
             api_v1_merchant_favorite_customer GET  /api/v1/merchants/:merchant_id/favorite_customer&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;               api/v1/merchants/favorite_customer#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                       api_v1_merchant_revenue GET  /api/v1/merchants/:merchant_id/revenue&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                         api/v1/merchants/revenue_by_merchant#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                   most_items_api_v1_merchants GET  /api/v1/merchants/most_items&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                   api/v1/merchants/most_items#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                 most_revenue_api_v1_merchants GET  /api/v1/merchants/most_revenue&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                 api/v1/merchants/most_revenue#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                      revenue_api_v1_merchants GET  /api/v1/merchants/revenue&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                      api/v1/merchants/revenue#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                         find_api_v1_merchants GET  /api/v1/merchants/find&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                         api/v1/find#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                     find_all_api_v1_merchants GET  /api/v1/merchants/find_all&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                     api/v1/find#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                       random_api_v1_merchants GET  /api/v1/merchants/random&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                       api/v1/random#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                              api_v1_merchants GET  /api/v1/merchants&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                              api/v1/merchants#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                               api_v1_merchant GET  /api/v1/merchants/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                          api/v1/merchants#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                          api_v1_item_merchant GET  /api/v1/items/:item_id/merchant&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                api/v1/items/items_merchants#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
                       api_v1_invoice_merchant GET  /api/v1/invoices/:invoice_id/merchant&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                          api/v1/invoices/invoice_merchants#show &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lets pick apart the &lt;code class="language-plaintext highlighter-rouge"&gt;pending_customers&lt;/code&gt; path.&lt;/p&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;api_v1_merchant_customers_with_pending_invoices GET  /api/v1/merchants/:merchant_id/customers_with_pending_invoices&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt; api/v1/merchants/pending_customers#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;that is generated by:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"customers_with_pending_invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/pending_customers#index"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;lets see what happens with&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"customers_with_pending_invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"pending_customers#index"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;api_v1_merchant_customers_with_pending_invoices GET  /api/v1/merchants/:merchant_id/customers_with_pending_invoices&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt; api/v1/pending_customers#index &lt;span class="o"&gt;{&lt;/span&gt;:format&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;:json&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interesting. It dropped the &lt;code class="language-plaintext highlighter-rouge"&gt;/merchants/&lt;/code&gt; from the endpoint path. That is not what I expected, especially because it is still nested under &lt;code class="language-plaintext highlighter-rouge"&gt;merchants&lt;/code&gt; in my routes file. Hm.&lt;/p&gt;

&lt;p&gt;Well, on further investigation, looks like the &lt;code class="language-plaintext highlighter-rouge"&gt;PendingCustomersController&lt;/code&gt; didn’t even &lt;em&gt;need&lt;/em&gt; to be nested inside of /merchants. It relies on a parameter passed into it (the merchant ID) but the routes that we told it to live at doesn’t require a merchant object in the path.&lt;/p&gt;

&lt;p&gt;Rejigger some of the folder names and locations, and everything still passes.&lt;/p&gt;

&lt;p&gt;This was a really good thing for me to learn about how Rails assumes controllers and views should be organized. It feels better to not override it’s default behavior, or to be verbose in describing where controllers should go.&lt;/p&gt;

&lt;p&gt;Here’s the current routes structure, and all tests still pass:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;defaults: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;format: :json&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:v1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:merchants&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:controller&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"merchants"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"items#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"invoices#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"customers_with_pending_invoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"pending_customers#index"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"favorite_customer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"favorite_customer#show"&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue_by_merchant#show"&lt;/span&gt;
        &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_items"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_items#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"most_revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/most_revenue#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"revenue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"merchants/revenue#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"find#show"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"find_all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"find#index"&lt;/span&gt;
          &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"random"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="s2"&gt;"random#show"&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I didn’t pull out the last few references to merchants, because, well, I’m short on time. But this will be helpful going forward, next time I’m building out routes.&lt;/p&gt;

&lt;p&gt;&lt;img alt="tests pass" src="https://cl.ly/2w2R2D0s2s15/1__joshthompson_Joshs-MBP-55____turing_3mod_projects_rails_engine__zsh_.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Tests still pass! Wahoo&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Tue, 09 May 2017 15:18:52 GMT</pubDate><guid isPermaLink="true">https://josh.works/cleaner-controllers</guid></item><item><title>Converting a Javascript Dictionary To GET URL Parameters</title><link>https://www.mattcrampton.com/blog/convert_a_javascript_dictionary_to_get_url_parameters/</link><description>Converting a Javascript Dictionary To GET URL Parameters I've had serveral instances in the recent past where I needed to take a javascript dictionary and convert it into a set of GET parameters to be used in a URI. Usually this happens when I'm building an AJAX request. Anyway, since I've used this function over and over I thought I'd post it incase it helps any of you Googling for something similar. Here's the function... Javascript to convert a javascript dictionary to GET parameters function dictToURI(dict) { var str = []; for(var p in dict){ str.push(encodeURIComponent(p) + "=" + encodeURIComponent(dict[p])); } return str.join("&amp;amp;"); } You might use it in a case like this... var myKeyValues = { "key1" : "value1", "key2" : "value2", "key3" : "value3" } var ajaxURL = "http://api.mattcrampton.com/xyz?" + dictToURI(myKeyValues); Which sets ajaxURL to... http://api.mattcrampton.com/xyz?key1=value1&amp;amp;key2=value2&amp;amp;key3=value3 P.S. If you're pushing this to a static hosted site...</description><author>MattCrampton.com</author><pubDate>Tue, 09 May 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/convert_a_javascript_dictionary_to_get_url_parameters/</guid></item><item><title>Didact: Instances, reconciliation and virtual DOM</title><link>https://medium.com/hexacta-engineering/didact-instances-reconciliation-and-virtual-dom-9316d650f1d0</link><description>Build your own React series</description><author>Rodrigo Pombo</author><pubDate>Tue, 09 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/didact-instances-reconciliation-and-virtual-dom-9316d650f1d0</guid></item><item><title>Work&amp;amp;Co Tech Meetup Vol 6</title><link>https://muffinman.io/blog/work-co-tech-meetup-vol-6/</link><description>&lt;article class="article"&gt;&lt;p&gt;Another tech meetup coming up. This time we have three great talks about engineering and project planning. We also have a special guest - &lt;strong&gt;IT girls team&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The IT Girls team will share their advances in promoting the professional development of women in technology in Serbia.&lt;/p&gt;
&lt;p&gt;This one will be held on Tuesday, May 16th at &lt;a href="https://www.google.com/maps/place/Impact+Hub+Belgrade/@44.8157208,20.460881,17z/data=!3m1!4b1!4m5!3m4!1s0x475a7ab185427a37:0x2344b5ab238871dc!8m2!3d44.815717!4d20.463075"&gt;Impact Hub Belgrade&lt;/a&gt;.
See you there!&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Work&amp;amp;Co Meetup Tech Meetup Vol 6" height="400" src="./poster.jpg" width="600" /&gt;&lt;/figure&gt;
&lt;h3 id="talks"&gt;Talks &lt;a class="anchor-link" href="#talks"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Docker IRL, &lt;strong&gt;Miloš Pavlićević&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Find out how to incorporate Docker into your deployment/delivery process, with images! (pun intended)&lt;/p&gt;
&lt;p&gt;&lt;a href="/pdf/Milos%20-%20Docker-IRL.pdf"&gt;Slides&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Javascript Unit Testing, &lt;strong&gt;Sarah Mogin&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Learn the value of testing your Javascript applications and the tools and techniques for effective testing. We’ll focus on how to test React components, selectors, reducers, and sagas using the Jest and Enzyme libraries.&lt;/p&gt;
&lt;p&gt;&lt;a href="/pdf/Sarah%20-%20UnitTesting.pdf"&gt;Slides&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Introduction to React Native, &lt;strong&gt;Zeh Fernando&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We had last minute change, and replaced Nemanja&amp;#x27;s talk (Plan Smart) with Zeh&amp;#x27;s great introduction to React Native.&lt;/p&gt;
&lt;p&gt;&lt;a href="/pdf/Zeh%20-%20Introduction%20to%20React%20Native.pdf"&gt;Slides&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="photos"&gt;Photos &lt;a class="anchor-link" href="#photos"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Meetup audience" height="800" src="./audience.jpg" width="1200" /&gt;&lt;/figure&gt;
&lt;div class="grid"&gt;&lt;figure class="image__figure"&gt;&lt;img alt="Sarah speaking about JavaScript testing" height="1200" src="./sarah.jpg" width="800" /&gt;&lt;/figure&gt;&lt;figure class="image__figure"&gt;&lt;img alt="Milos AKA Docker overlord" height="1200" src="./milos.jpg" width="800" /&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="React Native introduction by Zeh" height="800" src="./zeh.jpg" width="1200" /&gt;&lt;/figure&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Tue, 09 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/work-co-tech-meetup-vol-6/</guid></item><item><title>Apache disable TLS_RSA_WITH_3DES_EDE_CBC_SHA after LetsEncrypt</title><link>https://andrewshay.me/blog/apache-disable-tls_rsa_with_3des_ede_cbc_sha-after-letsencrypt</link><description>&lt;p&gt;
&lt;i&gt;This guide is for Apache but might be similar for other web servers&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;
If you've just installed &lt;a href="https://letsencrypt.org/"&gt;Let's Encrypt&lt;/a&gt; certificates with &lt;a href="https://certbot.eff.org/"&gt;Certbot&lt;/a&gt; on your web server and ran &lt;a href="https://www.ssllabs.com/ssltest/"&gt;SSL Server Test&lt;/a&gt;, you might have warning saying your server supports &lt;span class="hightlight"&gt;TLS_RSA_WITH_3DES_EDE_CBC_SHA&lt;/span&gt;.  
&lt;/p&gt;

&lt;p&gt;
To drop support for this protocol you must
&lt;ul&gt;
&lt;li&gt; Open &lt;span class="hightlight"&gt;/etc/letsencrypt/options-ssl-apache.conf&lt;/span&gt;&lt;/li&gt;
&lt;li&gt; Delete &lt;span class="hightlight"&gt;:DES-CBC3-SHA&lt;/span&gt; from the &lt;span class="hightlight"&gt;SSLCipherSuite&lt;/span&gt; line&lt;/li&gt;
&lt;li&gt; Restart apache &lt;span class="hightlight"&gt;sudo service apache2 restart&lt;/span&gt;&lt;/li&gt;  
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
Also, here is the default conf file  
&lt;a href="https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/tls_configs/old-options-ssl-apache.conf"&gt;https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/tls_configs/old-options-ssl-apache.conf&lt;/a&gt;
&lt;/p&gt;</description><author>Andrew Shay's Blog and Digital Garden</author><pubDate>Tue, 09 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://andrewshay.me/blog/apache-disable-tls_rsa_with_3des_ede_cbc_sha-after-letsencrypt</guid></item><item><title>All About Recursion, PTC, TCO and STC in JavaScript</title><link>https://lucasfcosta.com/blog/All-About-Recursion-PTC-TCO-and-STC-in-JavaScript/</link><description>Recently everyone seems to be really excited about functional programming and its concepts. However, many people don't talk about recursion and, especially, about proper tail calls, which is really...</description><author>Lucas F. Costa - Blog</author><pubDate>Mon, 08 May 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/All-About-Recursion-PTC-TCO-and-STC-in-JavaScript/</guid></item><item><title>Urda’s PGP Key for Amazon</title><link>https://urda.com/blog/2017/05/08/amazon-key</link><description>I joined Amazon and now have a key for my e-mail there!</description><author>Writings of Urda</author><pubDate>Mon, 08 May 2017 11:00:00 GMT</pubDate><guid isPermaLink="true">https://urda.com/blog/2017/05/08/amazon-key</guid></item><item><title>How to identify software licenses using Python, Vector Space Search and Ngram Keywords</title><link>https://boyter.org/2017/05/identify-software-licenses-python-vector-space-search-ngram-keywords/</link><description>&lt;p&gt;&lt;strong&gt;EDIT&lt;/strong&gt; – I have since taken the ideas below improved them and released a command line application you can use to build software license reports &lt;a href="https://github.com/boyter/lc/"&gt;https://github.com/boyter/lc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The below is mostly a log of my thought process while building out some functionality that I wanted to add into &lt;a href="https://searchcodeserver.com/"&gt;searchcode server&lt;/a&gt;. I kept a record of progress and thoughts while doing this in the hopes that I get some sort of useful blog post out of it. It has been edited somewhat for clarity.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 08 May 2017 09:54:34 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/05/identify-software-licenses-python-vector-space-search-ngram-keywords/</guid></item><item><title>Roaming through Japan</title><link>https://ben.bolte.cc/posts/2017-05-08-japan</link><description>Exploring the Land of the Rising Sun for 19 days by train, through Tokyo, Nikko, Sendai, Sapporo, Kyoto, Osaka and Nagoya.</description><author>Ben Bolte</author><pubDate>Mon, 08 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ben.bolte.cc/posts/2017-05-08-japan</guid></item><item><title>Towards a four-day working week</title><link>http://michaelhoney.com/writing/2017/5/7/towards-a-four-day-working-week</link><description>&lt;p&gt;I wrote an &lt;a href="https://greenagenda.org.au/2017/05/towards-four-day-work-week/"&gt;article&lt;/a&gt; for Green Agenda.&lt;/p&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Sun, 07 May 2017 09:35:14 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2017/5/7/towards-a-four-day-working-week</guid></item><item><title>Repository management with ghq</title><link>https://alanpearce.eu/post/repository-management-with-ghq/</link><description>&lt;p&gt;I recently encountered &lt;a href="https://github.com/motemen/ghq"&gt;ghq&lt;/a&gt;, a tool for automatically organising VCS-backed
projects automatically.  Give it a repository URL, it will clone a project to
your projects dir (set by &lt;code&gt;$GHQ_ROOT&lt;/code&gt;) like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;$ ghq get https://github.com/motemen/ghq
# Runs `git clone https://github.com/motemen/ghq ~/.ghq/github.com/motemen/ghq`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don&amp;rsquo;t like the idea of having projects hidden away, so I set
&lt;code&gt;$GHQ_ROOT&lt;/code&gt; to &lt;code&gt;$HOME/projects&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From there, the &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;look&lt;/code&gt; subcommands allow listing
repositories and visiting them in the shell (actually a subshell).&lt;/p&gt;
&lt;p&gt;I wanted a nicer way to visit project directories.  Since I&amp;rsquo;m
using &lt;a href="https://github.com/junegunn/fzf"&gt;fzf&lt;/a&gt; as a fuzzy-finder, I thought it would be nice to use it
for this.  I created a simple function, &lt;code&gt;fp&lt;/code&gt; (find project) to do that:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;fp () {
  ghq look $(ghq list | fzf +m)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I ran into some issues with the subshell of &lt;code&gt;ghq look&lt;/code&gt; and wondered
whether it might be possible to create a zsh command to remove the
need for a subshell.&lt;/p&gt;
&lt;p&gt;I found that &lt;code&gt;fzf&lt;/code&gt; includes a &lt;a href="https://github.com/junegunn/fzf/blob/337cdbb37c1efc49b09b4cacc6e9ee1369c7d76d/shell/key-bindings.zsh#L40-L54"&gt;cd-widget function&lt;/a&gt; and created
something similar that uses &lt;code&gt;ghq&lt;/code&gt; instead of &lt;code&gt;find&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;cd-project-widget () {
  local cmd=&amp;quot;ghq list&amp;quot;
  setopt localoptions pipefail 2&amp;gt; /dev/null
  local dir=&amp;quot;$(eval &amp;quot;$cmd&amp;quot; | FZF_DEFAULT_OPTS=&amp;quot;--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS&amp;quot; fzf +m)&amp;quot;
  if [[ -z &amp;quot;$dir&amp;quot; ]]; then
    zle redisplay
    return 0
  fi
  cd $(ghq list --full-path | grep &amp;quot;$dir&amp;quot;)
  local ret=$?
  zle reset-prompt
  typeset -f zle-line-init &amp;gt;/dev/null &amp;amp;&amp;amp; zle zle-line-init
  return $ret
}
zle -N cd-project-widget
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It should be quite simple to modify it to work with other
fuzzy-finders.  The basic idea is to show the output of &lt;code&gt;ghq list&lt;/code&gt; for
selection, and use &lt;code&gt;ghq list --full-path&lt;/code&gt; with the selected candidate
to print the correct directory for &lt;code&gt;cd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s really nice about this, is that I can bind it to a key
sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;bindkey '\es' cd-project-widget
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I can press &lt;code&gt;M-s&lt;/code&gt; in a shell, start typing &amp;ldquo;nixfiles&amp;rdquo; and press enter to &lt;code&gt;cd&lt;/code&gt;
to my &lt;a href="https://git.alanpearce.eu/dotfiles"&gt;nixfiles&lt;/a&gt; project. Pretty neat!&lt;/p&gt;</description><author>Alan Pearce</author><pubDate>Sun, 07 May 2017 00:31:51 GMT</pubDate><guid isPermaLink="true">https://alanpearce.eu/post/repository-management-with-ghq/</guid></item><item><title>Back again</title><link>https://alanpearce.eu/post/back-again/</link><description>I'm back</description><author>Alan Pearce</author><pubDate>Sat, 06 May 2017 17:55:57 GMT</pubDate><guid isPermaLink="true">https://alanpearce.eu/post/back-again/</guid></item><item><title>Declarative vs. Imperative paradigms</title><link>https://purpleidea.com/blog/2017/05/05/declarative-vs-imperative-paradigms/</link><description>&lt;p&gt;Recently, while operating two different remote-controlled appliances, I realized that it was high time for a discussion about declarative and imperative paradigms. Let&amp;rsquo;s start by looking at the two remotes:&lt;/p&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="declarative-imperative.png"&gt;&lt;img alt="declarative-imperative" class="alignnone size-full wp-image-2110" height="100%" src="declarative-imperative.png" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Two different "remotes". The one on the left operates a television, and the one on the right controls a central heating and cooling system.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;At first glance you will notice that one of these remotes is dark, and the other is light. You might also notice that my photography skills are terrible. Neither of these facts is very important to the discussion at hand. Is there anything interesting that you can infer?&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Fri, 05 May 2017 20:35:17 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/05/05/declarative-vs-imperative-paradigms/</guid></item><item><title>What language should be taught as the first language on a university computer science degree course?</title><link>https://www.databasesandlife.com/first-language-at-university/</link><description>&lt;p class="intro"&gt;
A friend of mine asked me for my opinions on what programming language should be taught in the introductory class of computer science at university.
&lt;/p&gt;
&lt;p&gt;I remember this debate when I was at university 20 years ago, this debate has no doubt been raging for centuries. (This may not be literally true, or rather, it is just not yet literally true at the time of writing&amp;hellip;)
This is what I reckon. What do you reckon?&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Thu, 04 May 2017 13:11:43 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/first-language-at-university/</guid></item><item><title>ROS production: create an Ubuntu Core image with our snap preinstalled [5/5]</title><link>https://kyrofa.com/posts/ros-production-create-an-ubuntu-core-image-with-our-snap-preinstalled-5-5/</link><description>UPDATE: I&amp;rsquo;m leaving this series up for historical purposes, but please note that I no longer recommend Ubuntu Core or snaps for use in robotics.
This is the fifth (and final) blog post in this series about ROS production. In the previous post we created a gadget snap to allow confined access to the Turtlebot. In this post, we&amp;rsquo;re going to put all the pieces from this series together and create an Ubuntu Core image with our ROS snap preinstalled, ready to send to the factory for production.</description><author>kyrofa's blog</author><pubDate>Thu, 04 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-production-create-an-ubuntu-core-image-with-our-snap-preinstalled-5-5/</guid></item><item><title>The elearning (r)evolution</title><link>https://yasha.solutions/the-elearning-revolution/</link><description>Daphne Koller: What we’re learning from online education The lady from Courseratells you how it is done and what they have learned. Salman Khan: Let’s use video to reinvent education The guy who founded the Khan Academytalks to you about what online video can do for schooling and education.</description><author>Yasha Solutions</author><pubDate>Wed, 03 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/the-elearning-revolution/</guid></item><item><title>Didact: Element creation and JSX</title><link>https://medium.com/hexacta-engineering/didact-element-creation-and-jsx-d05171c55c56</link><description>Build your own React series</description><author>Rodrigo Pombo</author><pubDate>Tue, 02 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/didact-element-creation-and-jsx-d05171c55c56</guid></item><item><title>Didact: Rendering DOM elements</title><link>https://medium.com/hexacta-engineering/didact-rendering-dom-elements-91c9aa08323b</link><description>Build your own React series</description><author>Rodrigo Pombo</author><pubDate>Tue, 02 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/didact-rendering-dom-elements-91c9aa08323b</guid></item><item><title>How do you go from React to React Native?</title><link>https://goshacmd.com/how-do-you-go-from-react-to-react-native/</link><author>Gosha Spark</author><pubDate>Tue, 02 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/how-do-you-go-from-react-to-react-native/</guid></item><item><title>About me</title><link>https://blog.eutopian.io/about/</link><description>900 words, 3 minutes.
Arno Breker&amp;rsquo;s Dionysos. 1936.
20+ years as CTO, Founder, Investor, Product Manager, Consultant, Engineer &amp;amp; advisor to corporations, law enforcement, government, &amp;amp; NGOs. Cyber Security Éminence Grise.
Still a work in progress. This is how I got here:
From Internet Start-Up To Global Telecommunications Giant In 5 Years
I started researching computer and network security in the early 1990s and began my professional career in 1995 with one of the UK&amp;rsquo;s first Internet Service Providers.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 02 May 2017 00:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/about/</guid></item><item><title>Arrival</title><link>https://blog.eutopian.io/arrival/</link><description>1200 words, 4 1/2 minutes. Welcome to the first post of my blog. Here I explain the why, what, and how of everything else you will see on this site. If you want to know more about the who, then read this. Most of my professional life involves winning systems or processes I&amp;rsquo;ve already established, monitoring progress or performance against targets, solving recognised problems. Here is where I introduce a few new ideas in a less formal environment, and explore them with you in an atmosphere of constructive discussion so that we might test them and learn something.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 02 May 2017 00:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/arrival/</guid></item><item><title>Copyright</title><link>https://blog.eutopian.io/copyright/</link><description>220 words, 1 minute.
 Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)   Unless described otherwise, the contents of this site are provided under the terms of the Creative Commons CC BY-SA license.
I am the sole author of the text of the articles appearing on this site. Where direct quotations are used they are attributed to their originator. Where images are used they are:
 Original Work. Typically diagrams or sketches.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 02 May 2017 00:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/copyright/</guid></item><item><title>The Stack</title><link>https://blog.eutopian.io/the-stack/</link><description>360 words, about 1 minute.
The site is built and maintained by me using Hugo, a static site generator written in Go. It&amp;rsquo;s running on a FreeBSD nginx web server. By the time you read this nginx will probably be inside a jail. The theme is a port of Ghost/Casper. My criteria was low maintenance, good security, performance, and simplicity. The content is all written in Markdown in a text editor, Hugo&amp;rsquo;d, and uploaded to the server using rsync/ssh.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 02 May 2017 00:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/the-stack/</guid></item><item><title>Invalidate All Cloudfront Files</title><link>https://www.mattcrampton.com/blog/invalidating_all_files_from_a_cloudfront_distribution_cache_from_the_command_line/</link><description>Invalidate All Cloudfront Files From The Command Line As I mentioned before, this website is built using Jekyll which generates static html which is then hosted on AWS S3. This works great for me because it allows me to take advantage of the enormous capacity S3 offers while paying pennies per month for hosting and bandwidth. All the while I get to skip worrying about spinning up web servers, virtual machines, etc. I do love doing all that but not for a simple static website such as this one. Having said that, you still need to separately set up an AWS Cloudfront distribution in front of your S3 bucket to manage caching at AWS's edge locations around the world, and it's also required to allow you to use SSL certs generated from the AWS Certification Manager. One problem I was running into was that once I deployed a new set of static HTML to the S3 bucket that hosts this site, Cloudfront would not immediately pull the new data into it's cache at all its endpoints. You can set up reas...</description><author>MattCrampton.com</author><pubDate>Mon, 01 May 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/invalidating_all_files_from_a_cloudfront_distribution_cache_from_the_command_line/</guid></item><item><title>Carrizo Plain</title><link>https://faingezicht.com/photos/2017/05/01/carrizo/</link><description>Although I hate road trips, I love traveling and seeing new places. It didn't take much convincing after reading about the &lt;a href="https://www.washingtonpost.com/news/capital-weather-gang/wp/2017/04/13/californias-wildflower-superbloom-is-so-prolific-you-can-see-it-from-space/"&gt;flower bloom in Southern California&lt;/a&gt; to get me excited about renting a car and heading down the highway for 5 hours to see it.

We clearly did not do things right, though. Between missing the fine print on the rental agreement, getting to the campsite after the welcome center had closed, and forgetting to get firewood ahead of time, we were pretty stressed on our ride there. Luckily, getting out of the city and camping in the wilderness has its way of soothing even the most restless of Avys.</description><author>Avy Faingezicht</author><pubDate>Mon, 01 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/05/01/carrizo/</guid></item><item><title>Making arcade controls: Arduino Leonardo code</title><link>https://qubyte.codes/blog/making-arcade-controls-arduino-leonardo-code</link><description>&lt;p&gt;I recently got it into my head that I wanted to build an arcade control panel
from parts. Specifically, an 8 way digital joystick and a bunch of buttons. How
it'll look when finished isn't important at the moment. It's enough now to say
that there'll be a joystick, six regular buttons, and two buttons for start and
select use.&lt;/p&gt;
&lt;p&gt;I decided to use an Arduino Leonardo to accept inputs from the buttons and
stick. The Leonardo presents itself as a keyboard to the machine you plug it
into, which is perfect for this. The only thing I needed to do is to initialize
the pins on the Arduino as inputs with inline resistance, and bind them to the
desired keys.&lt;/p&gt;
&lt;p&gt;Usually when a programmer thinks &amp;quot;the only thing I need to do&amp;quot;, what follows is
three or four times as much effort as predicted. I was surprised this time that
the effort required was so low, particularly given that I've not written any
C/C++ in years. In addition to functions for setting key states, &lt;code&gt;keyboard.h&lt;/code&gt;
provides a bunch of useful constants for special keys.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-cpp"&gt;&lt;span class="hljs-meta"&gt;#&lt;span class="hljs-keyword"&gt;include&lt;/span&gt; &lt;span class="hljs-string"&gt;&amp;lt;Keyboard.h&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class="hljs-comment"&gt;// MAMEish. An array of pin-key pairs.&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;struct&lt;/span&gt; { &lt;span class="hljs-type"&gt;int&lt;/span&gt; pin; &lt;span class="hljs-type"&gt;int&lt;/span&gt; key; } pinkeys[] = {
  { &lt;span class="hljs-number"&gt;2&lt;/span&gt;,  KEY_LEFT_ARROW  },
  { &lt;span class="hljs-number"&gt;3&lt;/span&gt;,  KEY_UP_ARROW    },
  { &lt;span class="hljs-number"&gt;4&lt;/span&gt;,  KEY_RIGHT_ARROW },
  { &lt;span class="hljs-number"&gt;5&lt;/span&gt;,  KEY_DOWN_ARROW  },
  { &lt;span class="hljs-number"&gt;6&lt;/span&gt;,  KEY_LEFT_CTRL }, &lt;span class="hljs-comment"&gt;// Fire 1&lt;/span&gt;
  { &lt;span class="hljs-number"&gt;7&lt;/span&gt;,  KEY_LEFT_ALT  }, &lt;span class="hljs-comment"&gt;// Fire 2&lt;/span&gt;
  { &lt;span class="hljs-number"&gt;8&lt;/span&gt;,  &lt;span class="hljs-string"&gt;&amp;#x27; &amp;#x27;&lt;/span&gt; },           &lt;span class="hljs-comment"&gt;// Fire 3&lt;/span&gt;
  { &lt;span class="hljs-number"&gt;9&lt;/span&gt;,  &lt;span class="hljs-string"&gt;&amp;#x27;a&amp;#x27;&lt;/span&gt; },           &lt;span class="hljs-comment"&gt;// Fire 4&lt;/span&gt;
  { &lt;span class="hljs-number"&gt;10&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#x27;s&amp;#x27;&lt;/span&gt; },           &lt;span class="hljs-comment"&gt;// Fire 5&lt;/span&gt;
  { &lt;span class="hljs-number"&gt;11&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#x27;q&amp;#x27;&lt;/span&gt; },           &lt;span class="hljs-comment"&gt;// Fire 6&lt;/span&gt;
  { A0, &lt;span class="hljs-string"&gt;&amp;#x27;1&amp;#x27;&lt;/span&gt; },           &lt;span class="hljs-comment"&gt;// start&lt;/span&gt;
  { A1, KEY_ESC }        &lt;span class="hljs-comment"&gt;// select&lt;/span&gt;
};

&lt;span class="hljs-function"&gt;&lt;span class="hljs-type"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;setup&lt;/span&gt;&lt;span class="hljs-params"&gt;()&lt;/span&gt; &lt;/span&gt;{
  &lt;span class="hljs-comment"&gt;// Set all used pins to handle input&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// from arcade buttons.&lt;/span&gt;
  &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;auto&lt;/span&gt; &lt;span class="hljs-type"&gt;const&lt;/span&gt; &amp;amp;pinkey : pinkeys) {
    &lt;span class="hljs-built_in"&gt;pinMode&lt;/span&gt;(pinkey.pin, INPUT_PULLUP);
  }

  &lt;span class="hljs-comment"&gt;// Initialize keyboard.&lt;/span&gt;
  Keyboard.&lt;span class="hljs-built_in"&gt;begin&lt;/span&gt;();
}

&lt;span class="hljs-function"&gt;&lt;span class="hljs-type"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;loop&lt;/span&gt;&lt;span class="hljs-params"&gt;()&lt;/span&gt; &lt;/span&gt;{
  &lt;span class="hljs-comment"&gt;// For each pin-key pair, check the&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// state of the pin and set the&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// associated key state to match.&lt;/span&gt;
  &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;auto&lt;/span&gt; &lt;span class="hljs-type"&gt;const&lt;/span&gt; &amp;amp;pinkey : pinkeys) {
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (&lt;span class="hljs-built_in"&gt;digitalRead&lt;/span&gt;(pinkey.pin) == LOW) {
      Keyboard.&lt;span class="hljs-built_in"&gt;press&lt;/span&gt;(pinkey.key);
    } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; {
      Keyboard.&lt;span class="hljs-built_in"&gt;release&lt;/span&gt;(pinkey.key);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since the Arduino is programmed in a dialect of recent  C++, range-based for
loops are available, as is type inference with &lt;code&gt;auto&lt;/code&gt;. This meant I could use an
array of instances of an anonymous structure to express the pin-key pairs. Not a
&lt;code&gt;sizeof&lt;/code&gt; in sight!&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Mon, 01 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/making-arcade-controls-arduino-leonardo-code</guid></item><item><title>A Man for All Markets: From Las Vegas to Wall Street, How I Beat the Dealer and the Market</title><link>https://olshansky.info/book/a_man_for_all_markets/</link><description>Olshansky's review of A Man for All Markets: From Las Vegas to Wall Street, How I Beat the Dealer and the Market by Edward O. Thorp</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 01 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/a_man_for_all_markets/</guid></item><item><title>A fews things to pay attention to on LinkedIn</title><link>https://yasha.solutions/a-fews-things-to-pay-attention-to-on-linkedin/</link><description>#1 – Pay attention to your photo Your profile is 21 times more likely to be viewed if you have a profile photo.
That’s also the first thing people will use to get a first understanding of who you are.
So, make sure your photo is clean and broadcast the kind of feeling your want – not just the photo you had available while doing your account.
#2 – Pay attention to your headline Your LinkedIn headline matters because :</description><author>Yasha Solutions</author><pubDate>Mon, 01 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/a-fews-things-to-pay-attention-to-on-linkedin/</guid></item><item><title>Building the perfect audio visualization</title><link>https://captnemo.in/blog/2017/05/01/spectrumyzer-visualization/</link><description>&lt;p&gt;I made this as my animated wallpaper recently (Click to play/pause):&lt;/p&gt;

&lt;video class="center-content" poster="/img/spectrum/poster.jpg" src="/videos/spectrum_320.webm" title="Spectrum Visualization Demo." width="320"&gt;&lt;/video&gt;

&lt;p&gt;&lt;em&gt;above video has a audio component, click at your own peril&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What follows is the story and the tech behind making this.&lt;/p&gt;

&lt;h2 id="the-wallpaper"&gt;The Wallpaper&lt;/h2&gt;

&lt;p&gt;I have a long history of using custom wallpapers. This was my wallpaper from 2014-:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Old Wallpaper" src="https://cdn.rawgit.com/captn3m0/avatars/a8255290/wallpaper/1920x1080.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;When I asked &lt;a href="http://vikalpgupta.com/"&gt;Vikalp&lt;/a&gt; to design a new one, I knew I wanted something that
was slightly more softer. This is what he came up with, after a few iterations:&lt;/p&gt;

&lt;p&gt;&lt;img alt="New Wallpaper" src="https://cdn.rawgit.com/captn3m0/avatars/a8255290/wallpaper/minimal.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;This wasn’t the final iteration, and both of us agreed that there was something missing.&lt;/p&gt;

&lt;h2 id="visualizations"&gt;Visualizations&lt;/h2&gt;

&lt;p&gt;I saw a colleague using &lt;a href="https://github.com/karlstav/cava#arch" title="Console-based Audio Visualizer for ALSA (MPD and Pulseaudio)"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;cava&lt;/code&gt;&lt;/a&gt; and spent a bit of time trying out different
visualization software. The ones that I tried out:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;strong&gt;&lt;a href="https://github.com/karlstav/cava#arch" title="Console-based Audio Visualizer for ALSA (MPD and Pulseaudio)"&gt;cava&lt;/a&gt;&lt;/strong&gt;&lt;/dt&gt;
  &lt;dd&gt;works perfectly with i3, runs on a terminal. I couldn’t get it to work cleanly with transparency. &lt;img alt="Cava screenshot using tiling" class="center-content" id="cava:" src="https://rawcdn.githack.com/karlstav/cava/80d465ff2537abf030fa766bda281150c60ac162/example_files/cava.gif" /&gt;&lt;/dd&gt;
  &lt;dt&gt;&lt;strong&gt;&lt;a href="http://projectm.sourceforge.net/" title="MilkDrop was the hardware-accelerated music visualization plugin for Winamp. ProjectM is the port that doesn't need Winamp and works on linux"&gt;mildrop&lt;/a&gt;&lt;/strong&gt;&lt;/dt&gt;
  &lt;dd&gt;Winamp’s legacy. This works great for parties, but is not really an everyday-use visualizer. &lt;img alt="Milkdrop Running using projectM on Linux" class="center-content" id="milkdrop:" src="/img/milkdrop.jpg" /&gt;&lt;/dd&gt;
  &lt;dt&gt;&lt;strong&gt;&lt;a href="https://github.com/HaCk3Dq/spectrumyzer/"&gt;spectrumyzer&lt;/a&gt;&lt;/strong&gt;&lt;/dt&gt;
  &lt;dd&gt;Worked with transparency, but limited to bars visualization.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;I decided to go ahead with Spectrumyzer (This is the default config):&lt;/p&gt;

&lt;p&gt;&lt;img alt="Default Spectrum Config" class="center-content" src="/img/spectrum/default.jpg" title="Spectrumyzer Default Config" /&gt;&lt;/p&gt;

&lt;h2 id="the-traffic-jam"&gt;The Traffic Jam&lt;/h2&gt;

&lt;p&gt;The very same day, stuck in a traffic jam&lt;sup id="fnref:3"&gt;&lt;a class="footnote" href="#fn:3" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;, I asked Vikalp for some color ideas on the visualization.&lt;/p&gt;

&lt;p&gt;The obvious 2 were tried first:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Spectrum Dark Blue Config" class="center-content" src="/img/spectrum/darkblue.jpg" title="Spectrumyzer Dark Blue Config" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Spectrum Yellow Config" class="center-content" src="/img/spectrum/yellow.jpg" title="Spectrumyzer Yellow Config" /&gt;&lt;/p&gt;

&lt;p&gt;It finally dawned on us to use the light blue variant with padding set to zero:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Spectrum Light Blue" class="center-content" src="/img/spectrum/blue.jpg" title="Spectrumyzer Blue Config with zero padding" /&gt;&lt;/p&gt;

&lt;p&gt;Here is one showing the actual positioning (set using the offsets):&lt;/p&gt;

&lt;p&gt;&lt;img alt="Spectrum Offset" class="center-content" src="/img/spectrum/offset.jpg" title="Spectrumyzer offset configuration" /&gt;&lt;/p&gt;

&lt;h2 id="bezier-curves"&gt;Bezier Curves&lt;/h2&gt;

&lt;p&gt;With the padding set to zero, it already looked great. I ended up using this
as my wallpaper for the next one week. Vikalp wanted to make the bars
non-rectangular, and I spent some time figuring out how to make waveforms using
bezier curves&lt;sup id="fnref:1"&gt;&lt;a class="footnote" href="#fn:1" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;. The basic learning from my experiments were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cairo has methods for drawing cubic bezier curves.&lt;/li&gt;
  &lt;li&gt;Cubic bezier curves have 2 control points.&lt;/li&gt;
  &lt;li&gt;The control points must be symmetric (equidistant) as well as parallel to the origin points.&lt;/li&gt;
  &lt;li&gt;The parallel part ensures that the ending and starting line segments are always tangential giving a smooth joining.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is roughly what you want to do when drawing waveforms:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Waveform bezier curve" class="center-content" src="/img/bezier.waveform.gif" /&gt;&lt;/p&gt;

&lt;p&gt;If you are interested in playing around with Bezier curves, see &lt;a href="https://www.jasondavies.com/animated-bezier/" title="Animated Bézier Curves, Play with the control points to modify the curves!"&gt;Animated Bézier Curves&lt;/a&gt;. &lt;a href="https://pomax.github.io/bezierinfo/" title="A Primer on Bézier Curves, A free, online book for when you really need to know how to do Bézier things."&gt;A Primer on Bézier Curves&lt;/a&gt; is a math-heavy explanation if you want to read further&lt;sup id="fnref:2"&gt;&lt;a class="footnote" href="#fn:2" rel="footnote"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The code I wrote picks the midpoints of the bars and then connects them using bezier curves:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# control point cords
# Make sure these are symmetric
&lt;/span&gt;&lt;span class="n"&gt;c1x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rect_top_mid_x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="n"&gt;c2x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_rect_top_mid_x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="n"&gt;c1y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rect_top_mid_y&lt;/span&gt;
&lt;span class="n"&gt;c2y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_rect_top_mid_y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I also had to make the number of bars configurable (this is default=64, which doesn’t look great):&lt;/p&gt;

&lt;p&gt;&lt;img alt="Spectrum water 64" class="center-content" src="/img/spectrum/64water.jpg" title="Spectrumyzer curves config doesn't look that great with 64 bars" /&gt;&lt;/p&gt;

&lt;p&gt;Here is the complete final result in HD:&lt;/p&gt;



&lt;h2 id="what-i-learned"&gt;What I learned&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Bezier curves are not magic.&lt;/li&gt;
  &lt;li&gt;Drawing pixels on screen and filling them was quite easy with Cairo and Python.&lt;/li&gt;
  &lt;li&gt;Coding is wizardry. The things that I take for granted every day (take a multi-page website and get useful tabular data out of it, for eg) are unthinkable for most people. The idea of doing water waves was something I knew would be possible before I even looked at the codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’d like to replicate this setup, or build upon it, here is my &lt;a href="https://github.com/captn3m0/dotfiles/blob/master/files/audio/.config/spectrum.conf" title="Just ensure you have the latest spectrumyzer code before using this"&gt;spectrum.conf&lt;/a&gt; file.
I also &lt;a href="https://github.com/HaCk3Dq/spectrumyzer/pull/22" title="Configurable renderers"&gt;filed a PR&lt;/a&gt; (now merged!) to the spectrumyzer project adding support for curve based renders.&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:3"&gt;
      &lt;p&gt;&lt;a href="https://twitter.com/SonyWorldJn"&gt;Sony World Junction&lt;/a&gt; - Where startup ideas are born. &lt;a class="reversefootnote" href="#fnref:3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:1"&gt;
      &lt;p&gt;The Spectrumyzer codebase turned out to be fairly easy to understand. It was just cairo and pyGTK. &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;&lt;a href="https://pomax.github.io/bezierinfo/" title="A Primer on Bézier Curves, A free, online book for when you really need to know how to do Bézier things."&gt;A Primer on Bézier Curves&lt;/a&gt; was published on HN just a few days after I finished this project. &lt;a class="reversefootnote" href="#fnref:2"&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>Mon, 01 May 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/05/01/spectrumyzer-visualization/</guid></item><item><title>Why use Postgres (Updated for last 5 years)</title><link>/2017/04/30/why-postgres-five-years-later/</link><description>&lt;p&gt;Five years ago &lt;a href="http://www.craigkerstiens.com/2012/04/30/why-postgres/"&gt;I wrote a post&lt;/a&gt; that got some good attention on why you should use Postgres. Almost a year later I &lt;a href="http://www.craigkerstiens.com/2012/05/07/why-postgres-part-2/"&gt;added a bunch of things&lt;/a&gt; I missed. Many of those items bear repeating, and I&amp;rsquo;ll recap a few of those in the latter half of this post. But in the last 4-5 years there&amp;rsquo;s been a lot of improvements and more reasons added to the list of why you should use Postgres. Here&amp;rsquo;s the rundown of the things that make Postgres a great database you should consider using.&lt;/p&gt;
&lt;h3 id="datatypes-including-jsonb-and-range-types"&gt;
&lt;div&gt;
Datatypes, including JSONB and range types
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Postgres has long had an open and friendly attitude for adding datatypes. It&amp;rsquo;s had arrays, geospatical and more for some time. A few years ago it got two datatypes worth thinking about using:&lt;/p&gt;
&lt;h4 id="jsonb"&gt;
&lt;div&gt;
JSONB
&lt;/div&gt;
&lt;/h4&gt;
&lt;p&gt;JSONB is a binary representation of JSON. It&amp;rsquo;s capable of being indexed on with &lt;code&gt;GIN&lt;/code&gt; and &lt;code&gt;GIST&lt;/code&gt; index types. You can also query into your full JSON document for quick lookups.&lt;/p&gt;
&lt;h4 id="range-types"&gt;
&lt;div&gt;
Range types
&lt;/div&gt;
&lt;/h4&gt;
&lt;p&gt;While it didn&amp;rsquo;t arrive to the same fame as JSONB, &lt;a href="https://wiki.postgresql.org/images/7/73/Range-types-pgopen-2012.pdf"&gt;range types&lt;/a&gt; can be especially handy if they&amp;rsquo;re what you need. Within a single column you can have a range from one value to another–this is especially helpful for time ranges. If you&amp;rsquo;re building a calendaring application or often have a from and to of timestamps then range types can let you put that in a single column. The real benefit is that you can then have constraints that certain time stamps can&amp;rsquo;t overlap or other constraints that may make sense for your application.&lt;/p&gt;
&lt;h3 id="extensions"&gt;
&lt;div&gt;
Extensions
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;d be hard to talk about Postgres without all the ecosystem around it. Extensions are increasingly quite key when it comes to the community and growth of Postgres. Extensions allow you to hook into Postgres very natively without requiring them to be committed back to the core of Postgres. This means they can add rich functionality without being tied to a Postgres release and review cycle. Some great examples of this are:&lt;/p&gt;
&lt;h4 id="citus"&gt;
&lt;div&gt;
Citus
&lt;/div&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt; (who I work for) turns Postgres into a distributed database allowing you to easily shard your database across multiple nodes. To your application it still looks like a single database, but then under the covers it&amp;rsquo;s spread across multiple physical machines and Postgres instances.&lt;/p&gt;
&lt;h4 id="hyperloglog"&gt;
&lt;div&gt;
HyperLogLog
&lt;/div&gt;
&lt;/h4&gt;
&lt;p&gt;This is a personal favorite of mine that allows you to easily have close-enough distinct counts pre-aggregated, but then also do various operations on them across days such as unions, intersections, and more. &lt;a href="https://www.citusdata.com/blog/2017/04/04/distributed_count_distinct_with_postgresql/"&gt;HyperLogLog and other sketch algorithms&lt;/a&gt; can be extremely common across large datasets and distributed systems, but it&amp;rsquo;s especially exciting to find them pretty close to out of the box in Postgres.&lt;/p&gt;
&lt;h4 id="postgis"&gt;
&lt;div&gt;
PostGIS
&lt;/div&gt;
&lt;/h4&gt;
&lt;p&gt;PostGIS isn&amp;rsquo;t new, but it&amp;rsquo;s worth highlighting again. It&amp;rsquo;s commonly regarded as the most advanced geospatial database. PostGIS adds new advanced geospatial datatypes, operators, and makes it easy to do many of the location based activities you need if you&amp;rsquo;re dealing with mapping or routing.&lt;/p&gt;
&lt;h3 id="logical-replication"&gt;
&lt;div&gt;
Logical replication
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;For many years the biggest knock against Postgres was the difficulty in setting up replication. Originally this was any form of replication, but then streaming replication came along (this is streaming of the binary WAL or write-ahead-log format). Tools like &lt;a href="https://github.com/wal-e/wal-e"&gt;wal-e&lt;/a&gt; help leverage much of the Postgres mechanisms for things like disaster recovery.&lt;/p&gt;
&lt;p&gt;Then we had the foundation for logical replication in recent releases, though it still required an &lt;a href="https://github.com/2ndQuadrant/pglogical"&gt;extension&lt;/a&gt; to Postgres so it wasn&amp;rsquo;t 100% out of the box. And, then finally we got full logical replication. Logical replication allows the sending of more or less actual commands, this means you could replicate only certain commands or certain tables.&lt;/p&gt;
&lt;h3 id="scale"&gt;
&lt;div&gt;
Scale
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;In addition to all of the usability featuers we&amp;rsquo;ve seen Postgres continue to get better and better at &lt;a href="https://www.slideshare.net/fuzzycz/postgresql-performance-improvements-in-95-and-96"&gt;performance&lt;/a&gt;. In particular we now have the foundations for &lt;a href="https://www.postgresql.org/docs/current/static/parallel-query.html"&gt;parallelism&lt;/a&gt; and on some queries you&amp;rsquo;ll see much better performance. Then if you need even greater scale than single node Postgres (such as 122 or 244 GB of RAM on RDS or Heroku) you have options like &lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt; which was mentioned earlier that can help you scale out.&lt;/p&gt;
&lt;h3 id="richer-indexing"&gt;
&lt;div&gt;
Richer indexing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Postgres already had some pretty powerful indexing before with &lt;a href="https://www.postgresql.org/docs/9.5/static/textsearch-indexes.html"&gt;GIN and GiST&lt;/a&gt;, those are now useful for JSONB. But we&amp;rsquo;ve also seen the arrival of KNN indexes and Sp-GiST and have even more on the way.&lt;/p&gt;
&lt;h3 id="upsert"&gt;
&lt;div&gt;
Upsert
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Upsert was a work in progress for several years. It was one of those features that most people hacked around with &lt;a href="http://www.craigkerstiens.com/2013/11/18/best-postgres-feature-youre-not-using/"&gt;CTEs&lt;/a&gt;, but that could create race conditions. It was also one of the few features MySQL had over Postgres. And just over a year ago we got &lt;a href="http://www.craigkerstiens.com/2015/05/08/upsert-lands-in-postgres-9.5/"&gt;official upsert&lt;/a&gt; support.&lt;/p&gt;
&lt;h3 id="foreign-data-wrappers"&gt;
&lt;div&gt;
Foreign Data Wrappers
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Okay, yes foreign data wrappers did exist many years ago. If you&amp;rsquo;re not familiar with foreign data wrappers, they allow you map an external data system to tables directly in Postgres. This means could could for example interact and query your &lt;a href="http://www.craigkerstiens.com/2012/10/18/connecting_to_redis_from_postgres/"&gt;Redis&lt;/a&gt; database from directly in Postgres with SQL. They&amp;rsquo;ve continued to be improved more and more from what we had over 5 years ago. In particular we got support for write-able foreign data wrappers, meaning you can write data to other systems from directly in Postgres. There&amp;rsquo;s also now an official Postgres FDW which comes out of the box with Postgres and it by itself is quite useful when querying across various Postgres instances.&lt;/p&gt;
&lt;h3 id="much-more"&gt;
&lt;div&gt;
Much more
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;And if you missed the &lt;a href="http://www.craigkerstiens.com/2012/04/30/why-postgres/"&gt;earlier editions&lt;/a&gt; of this, please feel free to &lt;a href="http://www.craigkerstiens.com/2012/05/07/why-postgres-part-2/"&gt;check them out&lt;/a&gt;. The cliff notes of them include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Window functions&lt;/li&gt;
&lt;li&gt;Functions&lt;/li&gt;
&lt;li&gt;Custom languages (PLV8 anyone?)&lt;/li&gt;
&lt;li&gt;NoSQL datatypes&lt;/li&gt;
&lt;li&gt;Custom functions&lt;/li&gt;
&lt;li&gt;Common table expressions&lt;/li&gt;
&lt;li&gt;Concurrent index creation&lt;/li&gt;
&lt;li&gt;Transactional DDL&lt;/li&gt;
&lt;li&gt;Foreign Data Wrappers&lt;/li&gt;
&lt;li&gt;Conditional and functional indexes&lt;/li&gt;
&lt;li&gt;Listen/Notify&lt;/li&gt;
&lt;li&gt;Table inheritance&lt;/li&gt;
&lt;li&gt;Per transaction synchronous replication&lt;/li&gt;
&lt;/ul&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>Sun, 30 Apr 2017 23:55:56 GMT</pubDate><guid isPermaLink="true">/2017/04/30/why-postgres-five-years-later/</guid></item><item><title>Osmocom femtocell un-boxing</title><link>https://purpleidea.com/blog/2017/04/30/osmocom-femtocell-un-boxing/</link><description>&lt;p&gt;&lt;a href="https://twitter.com/LaF0rge"&gt;LaForge&lt;/a&gt; and the fine folks at &lt;a href="https://osmocom.org/"&gt;Osmocom&lt;/a&gt; (&lt;a href="https://www.sysmocom.de/"&gt;Sysmocom&lt;/a&gt;) &lt;a href="https://osmocom.org/news/62"&gt;recently had a femtocell giveaway&lt;/a&gt;. I didn&amp;rsquo;t expect to have much time to hack on things, but they were still quite generous in sending me one. It arrived, and I took some un-boxing photos for anyone who is curious.&lt;/p&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_211113.jpg"&gt;&lt;img alt="IMG_20170317_211113" class="alignnone size-full wp-image-2064" height="100%" src="IMG_20170317_211113.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;A box arrived in the mail...&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_211256.jpg"&gt;&lt;img alt="IMG_20170317_211256" class="alignnone size-full wp-image-2065" height="100%" src="IMG_20170317_211256.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Which recurses into an inner box...&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_211348.jpg"&gt;&lt;img alt="IMG_20170317_211348" class="alignnone size-full wp-image-2066" height="100%" src="IMG_20170317_211348.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Inner box is box like.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_211402.jpg"&gt;&lt;img alt="IMG_20170317_211402" class="alignnone size-full wp-image-2067" height="100%" src="IMG_20170317_211402.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Finally... The unit is displayed.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_211440.jpg"&gt;&lt;img alt="IMG_20170317_211440" class="alignnone size-full wp-image-2068" height="100%" src="IMG_20170317_211440.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Here it is in all its glory.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_211600.jpg"&gt;&lt;img alt="IMG_20170317_211600" class="alignnone size-full wp-image-2069" height="100%" src="IMG_20170317_211600.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;It came complete with all the cables and power adapters necessary.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="IMG_20170317_212813.jpg"&gt;&lt;img alt="IMG_20170317_212813" class="alignnone size-full wp-image-2070" height="100%" src="IMG_20170317_212813.jpg" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The sysmocom folks even included some special test sim cards so that you can use the femtocell with your own phones.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;m very excited about the work the project is doing in their efforts to create and support free software telephony. If you are a telecom, please check out the various &lt;a href="https://www.sysmocom.de/"&gt;Sysmocom products and services available&lt;/a&gt;.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Sun, 30 Apr 2017 20:56:13 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/04/30/osmocom-femtocell-un-boxing/</guid></item><item><title>JavaScript: From Workers to Shared Memory</title><link>https://lucasfcosta.com/blog/JavaScript-From-Workers-to-Shared-Memory/</link><description>Hi, everyone!

The new Shared Memory proposal has reached stage 4 recently and I got really excited about it after reading a few blog posts on this subject, such as Dr. Axel's excellent post on his...</description><author>Lucas F. Costa - Blog</author><pubDate>Sun, 30 Apr 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/JavaScript-From-Workers-to-Shared-Memory/</guid></item><item><title>When's My Code Going Out?</title><link>https://www.mikekasberg.com/blog/2017/04/30/whens-my-code-going-out.html</link><description>&lt;p&gt;At &lt;a href="https://www.spotx.tv"&gt;SpotX&lt;/a&gt;, we manage our codebase with Git. Our commits
flow from our develop branch to production, with a code-freeze branch
in-between. Like this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Git branching
diagram." src="https://www.mikekasberg.com/images/whens-my-code-going-out/git_dev-freeze-prod.png" /&gt;&lt;/p&gt;

&lt;p&gt;With any web application, it’s really important for developers to know when
their code is going out. So they want to know which branch it’s on. To help with
this, I created a few simple git aliases that show recent commits a developer
has made in any branch. Here are the commands to create them:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ git config --global alias.my-dev 'rev-list origin/develop ^origin/freeze --author=mike@mikekasberg.com --pretty'
$ git config --global alias.my-freeze 'rev-list origin/freeze ^origin/prod --author=mike@mikekasberg.com --pretty'
$ git config --global alias.my-prod 'rev-list origin/prod --author=mike@mikekasberg.com --pretty --after="14 days ago"'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using them is easy!&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ git fetch
$ git my-freeze
commit bebba3afb108719bbdc500cb3dce50ffc062f060
Author: Mike Kasberg &amp;lt;mike@mikekasberg.com&amp;gt;
Date:   Sun Apr 30 13:15:15 2017 -0600

    Write more code... Make another commit

commit 00a54a1d6cc80a7103389bc813c6d76c2014cd85
Author: Mike Kasberg &amp;lt;mike@mikekasberg.com&amp;gt;
Date:   Sat Apr 29 11:16:44 2017 -0600

    Write some code... Make a commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a really simple way to use a git alias to make branch management a
little easier. With slight modification, it will help with pretty much any
branching strategy - for example, you could get a list of commits written by you
on a feature branch that are not yet in master:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ git config --global alias.my-feature-commits 'rev-list origin/feature ^origin/master --author=mike@mikekasberg.com --pretty'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With a little customization, you can make an alias like this to help out with
your own projects.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sun, 30 Apr 2017 14:22:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/04/30/whens-my-code-going-out.html</guid></item><item><title>Didact: a DIY guide to build your own React</title><link>https://medium.com/hexacta-engineering/didact-learning-how-react-works-by-building-it-from-scratch-51007984e5c5</link><description>Build your own React series</description><author>Rodrigo Pombo</author><pubDate>Sun, 30 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/didact-learning-how-react-works-by-building-it-from-scratch-51007984e5c5</guid></item><item><title>Intermission</title><link>http://www.nuke24.net/plog/22.html</link><description>I've been working on a bunch of different stuff lately</description><author>TOGoS's Project Log</author><pubDate>Sat, 29 Apr 2017 21:13:37 GMT</pubDate><guid isPermaLink="true">http://www.nuke24.net/plog/22.html</guid></item><item><title>Directing Collegiate Acappella: Performance</title><link>https://bpev.me/notes/directing-collegiate-acappella-performance</link><author>bpev.me</author><pubDate>Sat, 29 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/directing-collegiate-acappella-performance</guid></item><item><title>Hugo: Create pages without a theme</title><link>https://www.wints.org/notes/hugo-templates/</link><description>&lt;p&gt;&lt;a href="https://hugodocs.info/"&gt;Official Hugo v0.20 docs&lt;/a&gt;&lt;/p&gt;
&lt;h5 id="a-pages-that-dont-list-lower-level-pages-eg-about"&gt;A. Pages that don&amp;rsquo;t list lower level pages (e.g. /about/) &lt;a href="#a-pages-that-dont-list-lower-level-pages-eg-about"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Assuming the current version (0.20), a default Hugo folder layout looks like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;archetypes
config.toml
content
data
layouts
static
themes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you&amp;rsquo;d like to generate a bare, one-page site, create an &amp;lsquo;index.html&amp;rsquo; in the layouts section. You can write HTML and CSS here, and voila, you have a site.
However, if you want to add more pages (e.g. About, Contact etc.) that are not blog posts or listing blog posts, the process is slightly more complicated.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Fri, 28 Apr 2017 22:56:46 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/hugo-templates/</guid></item><item><title>Peer-to-Peer Science: The Century-Long Challenge to Respond to Fukushima</title><link>https://stop.zona-m.net/2017/04/peer-to-peer-science-the-century-long-challenge-to-respond-to-fukushima/</link><description>&lt;p&gt;&lt;em&gt;(this is a guest post by &lt;a href="http://wiki.p2pfoundation.net/Layne_Hartsell"&gt;Layne Hartsell&lt;/a&gt; and &lt;a href="http://www.twitter.com/epastreich"&gt;Emanuel Pastreich&lt;/a&gt;, who are research fellow and, respectively, director of &lt;a href="http://asia-institute.org"&gt;The Asia Institute&lt;/a&gt;. The post, originally published at &lt;a href="http://fpif.org/peer-peer-science-century-long-challenge-respond-fukushima/"&gt;Foreign Policy In Focus, in September 2013&lt;/a&gt;, is now reposted here on invitation of the author, to whom I am grateful, because I consider it a useful complement to my &lt;a href="https://stop.zona-m.net/tag/open-data"&gt;previous work on Open Data&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 28 Apr 2017 18:42:35 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/peer-to-peer-science-the-century-long-challenge-to-respond-to-fukushima/</guid></item><item><title>Should I finally drop QWERTY?</title><link>https://honza.pokorny.ca/2017/04/should-i-finally-drop-qwerty/</link><description>&lt;p&gt;For years now, I have wanted to switch my keyboard layout from QWERTY to
something more ergonomic.  QWERTY was &lt;a href="http://discovermagazine.com/1997/apr/thecurseofqwerty1099"&gt;designed&lt;/a&gt; to prevent typewriters from
jamming.  Modern computers don&amp;rsquo;t have this problem.  So, why are we still using
QWERTY?&lt;/p&gt;
&lt;p&gt;So, for me, it&amp;rsquo;s a given that I should switch to something else.  But what?  The
Dvorak layout is the obvious choice.  Most people who switch from QWERTY end up
using Dvorak.  Then there is Programmer Dvorak, and Colemak, and Programmer
Colemak, and hosts of others.&lt;/p&gt;
&lt;p&gt;There are &lt;a href="http://patorjk.com/keyboard-layout-analyzer/#/main"&gt;websites&lt;/a&gt; that allow you analyze some text, and help you determine
which layout is best for you.  This is of limited utility because the text you
past in won&amp;rsquo;t be representative of your actually habits.&lt;/p&gt;
&lt;h2 id="getting-down-to-business"&gt;Getting down to business&lt;/h2&gt;
&lt;p&gt;So, how can I hack this?  I installed a &lt;a href="https://github.com/kernc/logkeys"&gt;keylogger&lt;/a&gt; on my laptop, and
collected data for many days.  Then, I wrote a little script to analyze the
data.  This is mostly because analysis websites won&amp;rsquo;t let you paste in more
than a few kilobytes of text.  The most basic measure of how good a keyboard
layout is is the percentage of keystrokes that are on the home row.  The idea
is that if you have to move your fingers less, you will be faster, less tired,
and experience less pain.&lt;/p&gt;
&lt;p&gt;The script takes the output of the keylogger and gives you percentages of
keystrokes that are on the home row for each layout.  Here is what I got:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-nil"&gt;qwerty: 38.69149%
colemak: 35.601215%
dvorak-programmer: 34.441067%
dvorak: 34.441067%
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Wait, what?  QWERTY is the most optimal keyboard layout for me?  That can&amp;rsquo;t be
right.  Surely, there must be a bug in my code somewhere.  I went over
everything several times, tested my functions with dummy data, and so on.
Everything seems to be correct.  You can head over to &lt;a href="https://github.com/honza/keylogger"&gt;GitHub&lt;/a&gt; and prove me
wrong.&lt;/p&gt;
&lt;p&gt;I have been thinking about why I got this bizarre result.  I think it&amp;rsquo;s because
most of my regular typing isn&amp;rsquo;t necessarily writing prose.  There is a lot of
vim-style navigation (in &lt;a href="https://github.com/syl20bnr/spacemacs"&gt;Spacemacs&lt;/a&gt;, in the &lt;a href="https://vimium.github.io/"&gt;browser&lt;/a&gt;, etc), I use &lt;a href="https://i3wm.org/"&gt;i3&lt;/a&gt; as
my window manager, &amp;hellip;  A lot of it is running commands, tab-completing things,
keyboard shortcuts.  Other layouts, like Colemak, are probably optimized for
long-form writing.  In those cases, it would probably win.  But for
programmer-centric typing, QWERTY is likely to be king because everything is
optimized for it.&lt;/p&gt;
&lt;p&gt;What do you think?&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Fri, 28 Apr 2017 16:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/04/should-i-finally-drop-qwerty/</guid></item><item><title>Checking if a variable is set in Jekyll</title><link>https://www.mattcrampton.com/blog/checking_if_a_variable_is_set_in_jekyll/</link><description>Checking if a variable is set in Jekyll This site is built using Jekyll which allows me to generate the entire thing as static html which can then be hosted on AWS S3. Working through the Jekyll documentation I couldn't find a way to check if a variable was set when coding in Jekyll's templating language Liquid. This is easy in python and javascript but after some digging I found this Github issue thread which (after a lengthy discussion) came up with the following as best practice... Script to check if a variable is set in Jekyll &amp;#x7b;&amp;#x25;&amp;#x20;&amp;#x69;&amp;#x66;&amp;#x20;&amp;#x70;&amp;#x61;&amp;#x67;&amp;#x65;&amp;#x2e;&amp;#x73;&amp;#x6f;&amp;#x6d;&amp;#x65;&amp;#x5f;&amp;#x76;&amp;#x61;&amp;#x72;&amp;#x69;&amp;#x61;&amp;#x62;&amp;#x6c;&amp;#x65;&amp;#x20;&amp;#x41;&amp;#x6e;&amp;#x64;&amp;#x20;&amp;#x70;&amp;#x61;&amp;#x67;&amp;#x65;&amp;#x2e;&amp;#x73;&amp;#x6f;&amp;#x6d;&amp;#x65;&amp;#x5f;&amp;#x76;&amp;#x61;&amp;#x72;&amp;#x69;&amp;#x61;&amp;#x62;&amp;#x6c;&amp;#x65;&amp;#x20;&amp;#x21;&amp;#x3d;&amp;#x20;&amp;#x22;&amp;#x22;&amp;#x20;&amp;#x41;&amp;#x6e;&amp;#x64;&amp;#x20;&amp;#x70;&amp;#x61;&amp;#x67;&amp;#x65;&amp;#x2e;&amp;#x73;&amp;#x6f;&amp;#x6d;&amp;#x65;&amp;#x5f;&amp;#x76;&amp;#x61;&amp;#x72;&amp;#x69;&amp;#x61;&amp;#x62;&amp;#x6c;&amp;#x65;&amp;#x2...</description><author>MattCrampton.com</author><pubDate>Fri, 28 Apr 2017 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/checking_if_a_variable_is_set_in_jekyll/</guid></item><item><title>Beer, Conversation and Bridging the Opinion Gap</title><link>https://yasha.solutions/beer-conversation-and-bridging-the-opinion-gap/</link><description>We are all different.
Color, Race, Religions.
Different brands of toothpaste.
Different opinions.
Lately, having different opinions is starting to turn into a real issue.
 Up to a point where people can’t even have a conversation about it.
(Arguably, this was always the case, just that now, it seems it is getting harder to just ignore others’ opinions)
 It is not always easy to to discuss.
Open conversations are hard.</description><author>Yasha Solutions</author><pubDate>Fri, 28 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/beer-conversation-and-bridging-the-opinion-gap/</guid></item><item><title>Flowers by Wendy Cope</title><link>https://ho.dges.online/words/commonplace/flowers-by-wendy-cope/</link><description>&lt;p&gt;Some men never think of it.&lt;br /&gt;
You did. You’d come along&lt;br /&gt;
And say, you’d nearly brought me flowers&lt;br /&gt;
But something had gone wrong.&lt;/p&gt;
&lt;p&gt;The shop was closed. Or you had doubts -&lt;br /&gt;
The sort that minds like ours&lt;br /&gt;
Dream up incessantly. You thought&lt;br /&gt;
I might not want your flowers.&lt;/p&gt;
&lt;p&gt;It made me smile and hug you then.&lt;br /&gt;
Now I can only smile.&lt;br /&gt;
But, look, the flowers you nearly brought&lt;br /&gt;
Have lasted all this while.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Fri, 28 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/flowers-by-wendy-cope/</guid></item><item><title>Follower by Seamus Heaney</title><link>https://ho.dges.online/words/commonplace/follower-by-seamus-heaney/</link><description>&lt;p&gt;My father worked with a horse-plough,&lt;br /&gt;
His shoulders globed like a full sail strung&lt;br /&gt;
Between the shafts and the furrow.&lt;br /&gt;
The horses strained at his clicking tongue.&lt;/p&gt;
&lt;p&gt;An expert. He would set the wing&lt;br /&gt;
And fit the bright steel-pointed sock.&lt;br /&gt;
The sod rolled over without breaking.&lt;br /&gt;
At the headrig, with a single pluck&lt;/p&gt;
&lt;p&gt;Of reins, the sweating team turned round&lt;br /&gt;
And back into the land. His eye&lt;br /&gt;
Narrowed and angled at the ground,&lt;br /&gt;
Mapping the furrow exactly.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Fri, 28 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/follower-by-seamus-heaney/</guid></item><item><title>Directing Collegiate Acappella: Rehearsals</title><link>https://bpev.me/notes/directing-collegiate-acappella-rehearsals</link><author>bpev.me</author><pubDate>Fri, 28 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/directing-collegiate-acappella-rehearsals</guid></item><item><title>Individual or collective clouds? Both, of course</title><link>https://stop.zona-m.net/2017/04/individual-or-collective-clouds-both-of-course/</link><description>&lt;p&gt;Yesterday, I presented what I consider a &lt;a href="http://stop.zona-m.net/2017/04/mastodon-has-no-users-nor-people.-but-people-can-have-mastodon/"&gt;perfect confirmation of my views on &amp;ldquo;Twitter replacements&amp;rdquo;&lt;/a&gt;. Today, I &amp;ldquo;defend&amp;rdquo; that position from &amp;ldquo;accusations&amp;rdquo; of individualism.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 27 Apr 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/individual-or-collective-clouds-both-of-course/</guid></item><item><title>Eve and Cerberus funding campaign</title><link>https://nicolaiarocci.com/eve-and-cerberus-funding-campaign/</link><description>&lt;p&gt;Last February I published &lt;a href="https://nicolaiarocci.com/the-state-of-the-eve-rest-framework-project/"&gt;The State of Eve REST Framework&lt;/a&gt;. Among other
things in that post, I mentioned that I was looking for ways that would allow
me to allocate more time to the project (and its satellites).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I really feel like I should put more effort into Eve, Cerberus and satellite
projects Eve-Swagger, Flask-Sentinel, Eve.NET, etc. I love working on these
projects and I know a lot of people rely on them. Also, I have big ideas that
I would like to play with. At this point in time however, I cannot afford
allocating more time to not-paying-the-bill activities.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 27 Apr 2017 12:23:05 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/eve-and-cerberus-funding-campaign/</guid></item><item><title>Directing Collegiate Acappella: Auditions</title><link>https://bpev.me/notes/directing-collegiate-acappella-auditions</link><author>bpev.me</author><pubDate>Thu, 27 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/directing-collegiate-acappella-auditions</guid></item><item><title>Mastodon has no users, nor people. But people (can) have Mastodon</title><link>https://stop.zona-m.net/2017/04/mastodon-has-no-users-nor-people.-but-people-can-have-mastodon/</link><description>&lt;p&gt;I just saw on Twitter and his &amp;ldquo;replacement&amp;rdquo;, that is Mastodon, something that in my opinion is a perfect, real-world confirmation that, as I recently said, certain worries about Mastodon flaws and alternative &amp;ldquo;platforms&amp;rdquo; are&amp;hellip; misplaced. Please have a look at this screenshot:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 26 Apr 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/mastodon-has-no-users-nor-people.-but-people-can-have-mastodon/</guid></item><item><title>Mental strength and resilience</title><link>http://dimitarsimeonov.com/2017/04/26/mental-strength-and-resilience</link><description>&lt;p&gt;It is easy to define physical strength.  It is the ability to move the
body to produce force. When that force is in a certain direction you
can measure it. Statements like “I squat 200lbs” or “I deadlift
300lbs” measure the physical strength of a person.&lt;/p&gt;

&lt;p&gt;But how about &lt;em&gt;mental&lt;/em&gt; strength? Not so easy to define. My definition
is to be able to make the right decision in a complex scenario. To
untie a clusterfuck. The more &lt;em&gt;complex&lt;/em&gt; the task and the knot, the
higher the mental strength.&lt;/p&gt;

&lt;p&gt;Whether it’s finding Waldo, designing a complex system, solving math
olympiad problems, playing challenging video games, playing chess,
flirting, handling relationships, showing leadership, writing an essay
like this one, or dealing with a loss, we are trying to find order in
complexity. We need to connect multiple different pieces of knowledge
and uncertainty in order to come with the best possible solution or
behavior.&lt;/p&gt;

&lt;p&gt;I define mental &lt;em&gt;strength&lt;/em&gt; to be about the complexity of the
situation. Computational complexity fits nicely to define mental
strength. If we need to find Waldo in a painting with 100 characters,
it takes 100 units of mental strength as we need to consider each
character. If we are playing chess, and we end up in a situation where
we only have two possible moves, such as when the opponent attacks our
king, the mental strength is not just two units. Because in order to
evaluate each option we need to imagine what could happen several
steps ahead. If we consider 20 possible scenarios to follow each
possible move, then we have 40 total units of mental work.&lt;/p&gt;

&lt;p&gt;When I was growing up by reading lots of books and competing in math
olympiads, I prided myself on being clever, on having that ability to
go into complex math problem and find the solution. My math biceps was
strong, and on a good day I’d “lift” multiple math problems.&lt;/p&gt;

&lt;p&gt;But I wasn’t every day at the same mental conditioning level. Some
days my mind was quick and I could see the connection between the
different parts of the problem. And I could go and solve multiple
problems without getting exhausted. Those were the great days. I felt
really motivated and calm, and present in the moment. I wasn’t
anticipating the way the results would affect me - I was just enjoying
solving the problems, having fun, and dedicating my fullest attention
to it.&lt;/p&gt;

&lt;p&gt;But there were also days when I could just not see the steps towards
the solution, even though I could have. It wasn’t that the solution
required an obscure unknown theorem. Instead, it required a slightly
ingenious way of combining the elements of the problem statement. In
those days my mental biceps would fail to lift 10 pounds, even though
I had previously lifted 20 pounds easily.&lt;/p&gt;

&lt;p&gt;Such variability continues to this day. But why? Why are some days
better than the other and some days worse? How can I know and prevent
it, so I am at my best when I need it?&lt;/p&gt;

&lt;p&gt;I’ll attempt answering this by drawing more parallels to physical
strength. And my answer is that this is due to fatigue and
injury. Mental fatigue and mental injury. And I define mental
&lt;em&gt;resiliency&lt;/em&gt; as the ability to muster mental strength even when
fatigued or injured.&lt;/p&gt;

&lt;p&gt;Mental fatigue, is when we don’t have the full capacity on our
disposal. For me it means thinking so hard and so often about a
problem that the brain runs out of energy and needs a break. The brain
needs energy to run, just like actual muscles and the energy reserve
can get depleted and take a while to replenish.  Glucose-heavy food
and caffeine might do the trick in the short term, but their effects
wont last.&lt;/p&gt;

&lt;p&gt;Mental injury, from my point of view, is having emotions which
wouldn’t let go. This emotion would distract us and redirect part of
our energy and strength towards it. And the emotion could be either
positive or negative, and either one can decrease the mental
strength. And those could be internal and caused by us, or external
and caused by other people and events. We could have a crush on
someone and not be able to forget them for the duration of the mental
task. We could have anticipation for the results of the task,
amplifying our perception of what’s at stake and getting stressed
about it.&lt;/p&gt;

&lt;p&gt;We could have lost someone. When I was nineteen and one of my best
friends died in a motorcycle crash. We had flown to USA on the same
flight and we lived door to door in college. After he died I was
stressed and had trouble falling asleep for months. I tried to keep up
with school and social life, and I did OK, except that I also got into
drinking a lot. I did show some mental resiliency, though it came at a
dear long term cost. And that is taking me a while to pay off, but at
least now I feel confident to say I’m not dependent on alcohol for my
happiness. Life went on and time healed me.&lt;/p&gt;

&lt;p&gt;Last Friday was the ten year anniversary of my friend’s death and I
didn’t even remember. I’m not proud of that. Actually I’m ashamed I
didn’t remember. But I find comfort in knowing that the ripples from
his death cannot cause a drowning tsunami for me, the way they did
initially.  And I got practice swimming in the high water and didn’t
drown. And I now remember the good times we shared and all I learned
from him.&lt;/p&gt;

&lt;p&gt;Two days ago another wave hit. My grandpa. And while I’m still ducking
under that wave, I already know that it will pass through and I’ll get
a gulp of fresh air and look at the sun. And I’ll remember the good
times. I’ll remember how my grandpa taught me to play chess, and how
he joked and he tried hard to recover for eighteen years after he had
a stroke and had his right side paralyzed. I’ll remember how he learned to do everything with half of his body, and how he learned to walk again and go for a walk every day the weather allowed. I’ll remember him for the
progress that he made and for his desire to live.&lt;/p&gt;

&lt;p&gt;For me, the answer to the complex mental problem of dealing with the
loss, is to have grattitude for the good things that &lt;em&gt;did&lt;/em&gt; happen, and
to move on. I’m grateful for the time I had with my grandpa and with
my late friend. I feel their loss, but I am growing my appreciation
for having them in my life.  I am also feeling gratefulness for my own
life, and a desire to live. And I want to develop mental and physical
strength and resilience to be &lt;em&gt;living&lt;/em&gt; as fully as I can while
alive.&lt;/p&gt;</description><author>D13V</author><pubDate>Wed, 26 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/04/26/mental-strength-and-resilience</guid></item><item><title>Constraints, Creativity, Startups, Funding</title><link>https://yasha.solutions/constraints-creativity-startups-funding/</link><description>When options are limited, people produce more solutions – not less.
When people are limited they try to improve and optimise.
 The opposite is true.
It is known as Parkinson’s Law :
“Work expands so as to fill the time available for it’s completion”
 Well, seems like what is true for time budget is also true for financial budget.
The more money there is available the more money you will use for your project.</description><author>Yasha Solutions</author><pubDate>Wed, 26 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/constraints-creativity-startups-funding/</guid></item><item><title>Directing Collegiate Acappella: Arranging</title><link>https://bpev.me/notes/directing-collegiate-acappella-arranging</link><author>bpev.me</author><pubDate>Wed, 26 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/directing-collegiate-acappella-arranging</guid></item><item><title>YAC - Some Kotlin Magic</title><link>https://prashamhtrivedi.in/yac_kotlin_example.html</link><description>In this post I will share some examples of how Kotlin helped me to overcome problems I have faced in Java</description><author>Prasham H Trivedi</author><pubDate>Wed, 26 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/yac_kotlin_example.html</guid></item><item><title>ROS production: obtaining confined access to the Turtlebot [4/5]</title><link>https://kyrofa.com/posts/ros-production-obtaining-confined-access-to-the-turtlebot-4-5/</link><description>UPDATE: I&amp;rsquo;m leaving this series up for historical purposes, but please note that I no longer recommend Ubuntu Core or snaps for use in robotics.
This is the fourth blog post in this series about ROS production. In the previous post we created a snap of our prototype, and released it into the store. In this post, we&amp;rsquo;re going to work toward an Ubuntu Core image by creating what&amp;rsquo;s called a gadget snap.</description><author>kyrofa's blog</author><pubDate>Wed, 26 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-production-obtaining-confined-access-to-the-turtlebot-4-5/</guid></item><item><title>Meaning in Technical Communication</title><link>https://peterlyons.com/problog/2017/04/meaning-in-technical-communication/</link><description>&lt;p&gt;Just a quick tip to be on the lookout for commonly-used words in technical discussions that are problematic due to being low on meaning and high on emotional weight. Watch out for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;secure&lt;/li&gt;
&lt;li&gt;easy&lt;/li&gt;
&lt;li&gt;flexible&lt;/li&gt;
&lt;li&gt;lightweight, heavyweight&lt;/li&gt;
&lt;li&gt;virtual, physical, logical&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If someone is using these and you are confused or trying to have a productive discussion, call them out and request for more specific, clearer words. Some better examples might be&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lower-latency&lt;/li&gt;
&lt;li&gt;longer startup time&lt;/li&gt;
&lt;li&gt;smaller network transfer size&lt;/li&gt;
&lt;li&gt;straightforward to add new endpoints in the future&lt;/li&gt;
&lt;li&gt;requires fewer processes&lt;/li&gt;
&lt;li&gt;lower annual cost&lt;/li&gt;
&lt;/ul&gt;</description><author>Pete's Points</author><pubDate>Tue, 25 Apr 2017 18:59:59 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/04/meaning-in-technical-communication/</guid></item><item><title>Genius: Einstein</title><link>https://olshansky.info/tv/genius_einstein/</link><description>Olshansky's review of Genius: Einstein</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 25 Apr 2017 03:59:45 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/genius_einstein/</guid></item><item><title>April</title><link>https://faingezicht.com/photos/2017/04/25/april/</link><description>For some reason, things have been quiet around here lately. I guess work has kept me busy, and I haven't been too motivated to either take photos or share links on my blog. That's how you get &lt;a href="/links/2017/04/24/the-great-link-dump/"&gt;The Great Link Dump of April 2017&lt;/a&gt;.

I wish I had more to share of my day at the races, of my walks through the city, and of these black and white shots. Especially the black and white shots.

This post feels jumbled up. A collection of collections, thrown together due to lack of better options. I'd apologize, but its better than not posting, and I'm hoping it gets the ball rolling again.</description><author>Avy Faingezicht</author><pubDate>Tue, 25 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/04/25/april/</guid></item><item><title>Building Gathering: a website for announcing group events</title><link>https://gilmi.me/post/2017/04/25/building-gathering</link><description>An experience report on building Gathering</description><author>λm.me</author><pubDate>Tue, 25 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://gilmi.me/post/2017/04/25/building-gathering</guid></item><item><title>LinkedIn – Social Media 101</title><link>https://yasha.solutions/linkedin-social-media-101/</link><description>Everyone knows LinkedIn – yet not everybody use it to its full power (and I totally include myself in this “everybody”).
Linkedin has a lot of potential and here are some interesting tips I would suggest you have a look at.
Some history &amp;amp; stats Founded in Dec, 2002 (When Windows XP was still at the top of its hype)
Launched in May, 2003 (yes, you were a couple of years younger…)</description><author>Yasha Solutions</author><pubDate>Tue, 25 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/linkedin-social-media-101/</guid></item><item><title>Up your LinkedIn skills with 3 talks on LinkedIn Strategy</title><link>https://yasha.solutions/up-your-linkedin-skills-with-3-talks-on-linkedin-strategy/</link><description>Paul Copcutt: LinkedIn -Where your sales and marketing meet And also how can piñada and LinkedIn help to sell accounting services… Become a LinkedIn Search Ninja Spend 3 days to find valuable information on LinkedIn search.
Found it. Social Selling by LinkedIn with LinkedIn This lady kicks ass.
Very good video on social selling.</description><author>Yasha Solutions</author><pubDate>Tue, 25 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/up-your-linkedin-skills-with-3-talks-on-linkedin-strategy/</guid></item><item><title>Nicer git log</title><link>https://muffinman.io/blog/nicer-git-log/</link><description>&lt;article class="article"&gt;&lt;p&gt;Just a short one. I want to share a simple command to display nicer &lt;code&gt;git log&lt;/code&gt; in the terminal. &lt;code&gt;git log&lt;/code&gt; has &lt;code&gt;--pretty=format&lt;/code&gt; option built-in, we are just going to pass formatting to it.&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;git&lt;/span&gt; log &lt;span class="token parameter variable"&gt;--graph&lt;/span&gt; &lt;span class="token parameter variable"&gt;--pretty&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;format:&lt;span class="token string"&gt;&amp;#x27;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it looks like this:&lt;/p&gt;
&lt;figure class="image__figure image__figure--transparent"&gt;&lt;img alt="Nicer git log" height="1680" src="./nicer-git-log.png" width="2630" /&gt;&lt;/figure&gt;
&lt;p&gt;Then add it to your &lt;code&gt;.bash_profile&lt;/code&gt; as an alias (I&amp;#x27;m using &lt;code&gt;glog&lt;/code&gt;) and that&amp;#x27;s it.&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token builtin class-name"&gt;alias&lt;/span&gt; &lt;span class="token assign-left variable"&gt;glog&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;quot;git log --graph --pretty=format:&amp;#x27;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset&amp;#x27;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Tue, 25 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/nicer-git-log/</guid></item><item><title>Use SaltStack as a Data Source in Grafana</title><link>https://btmiller.com/2017/04/24/use-saltstack-as-a-datasource-in-grafana.html</link><description>&lt;p&gt;For visualizing and alerting on your infrastructure and services, Grafana is awesome, and its power gets amplified when dashboards and alerts and be templated to work with your constantly evolving infrastructure. So how do we decide how to apply templates to the right set of servers and services? Well, of course you can preseed key-value pairs on your servers and have your collector agents like Telegraf work off of your seeded data. However, if you are familiar with or favor an externally managed source of record like node groups in Salt, templating in Grafana works a little different.&lt;/p&gt;

&lt;div class="bs-callout bs-callout-info"&gt;
  &lt;p&gt;In my latest personal experience, we chose to use node groups in Salt for defining the role of a server since we have no control over hostnames. Otherwise, this problem is solved already by using a naming scheme for server roles (web4, db1, cache3, lb2-west, etc.).&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Grafana comes built-in with support for InfluxDB, Graphite, Prometheus, OpenTSDB, Elasticsearch, and others, but non-traditional options like Salt are absent. Our solution is to create a custom Salt data source in Grafana such that dashboard values can be templated from node group membership.&lt;/p&gt;

&lt;p&gt;Salt exposes a REST API to which we can query node groups and node group membership. An important prerequisite to use Salt node groups as a data source is to enable &lt;code class="language-plaintext highlighter-rouge"&gt;pillar_opts&lt;/code&gt; on your master which will expose your master’s configuration as pillar data.&lt;/p&gt;

&lt;div class="bs-callout bs-callout-warning"&gt;
  &lt;p&gt;Please be sure you know what you’re doing by enabled &lt;code class="language-plaintext highlighter-rouge"&gt;pillar_opts&lt;/code&gt; on your Salt master. If you have any sensitive data stored in your master’s configuration, &lt;a href="https://docs.saltstack.com/en/latest/ref/configuration/master.html#pillar-opts"&gt;it will be readable by all of you minions&lt;/a&gt;. Consider moving your sensitive info into something like HashiCorp’s Vault.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;To feed Grafana with Salt data, we first need to install the &lt;a href="https://grafana.com/plugins/grafana-simple-json-datasource/installation"&gt;SimpleJson plugin&lt;/a&gt;. This plugin is generic and allows you to custom craft your own data source backend. The SimpleJson plugins requires backends to respond to 4 Grafana events: query API, annotation API, search API, and a connection test. Since all we’re doing with the Salt data source is retrieving a list from known keys, we’re only going to fully implement the search API.&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://github.com/bergquist/fake-simple-json-datasource"&gt;Bergquist’s&lt;/a&gt; project as a starting point and refactored/trimmed it to serve our narrower goal. Thank goodness for his example because I am not a JavaScript developer. In traditional JavaScript developer fashion, however, my code changes are sloppy and I’ll worry about it later.&lt;/p&gt;

&lt;p&gt;Start by installing &lt;a href="https://github.com/blaketmiller/Grafana-Salt-Backend"&gt;Grafana-Salt-Backend&lt;/a&gt;:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ npm -g install blaketmiller/grafana-salt-backend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="bs-callout bs-callout-info"&gt;
  &lt;p&gt;A global install isn’t required if you know what you’re doing. I prefer it because I like having things installed in system-default locations. If you included the &lt;code class="language-plaintext highlighter-rouge"&gt;-g&lt;/code&gt;, the project can be found in &lt;code class="language-plaintext highlighter-rouge"&gt;/usr/local/lib/node_modules/grafana-salt-backend&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Next, you’ll need to configure the app. Right now, the app supports username and password over LDAP for authentication:&lt;/p&gt;

&lt;div class="language-json highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blake"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"really_secure_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"saltmaster"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"saltmaster.example.net"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8000&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If there’s any traction with this, then perhaps I’ll add token auth, but this works for me right now. I would also happily accept a pull request from someone who enjoys JavaScript more than I do.&lt;/p&gt;



&lt;!-- inline --&gt;
&lt;p&gt;&lt;ins class="adsbygoogle" style="display: block;"&gt;&lt;/ins&gt;
&lt;/p&gt;

&lt;p&gt;Now, run the service in the foreground:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;node /usr/local/lib/node_modules/grafana-salt-backend/index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To test that the data source is working, try hitting it:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;curl -H 'Content-Type: application/json' -X POST -d '{"target": "list"}' http://localhost:3333/search
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If everything is good, you should see a list of all your node groups defined in Salt. It is also probably a good idea to run the backend as a service, so let’s put it behind Systemd with &lt;code class="language-plaintext highlighter-rouge"&gt;/etc/systemd/system/grafana-salt-backend&lt;/code&gt;:&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;[Unit]&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;Grafana Salt Backend&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;span class="nn"&gt;[Service]&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/node /usr/local/lib/node_modules/grafana-salt-backend/index.js&lt;/span&gt;
&lt;span class="py"&gt;KillMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;process&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-failure&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To have the process start at each system boot, run:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;systemctl enable grafana-salt-backend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, start the backend:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;systemctl start grafana-salt-backend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s go configure a new SimpleJson data source:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Configure the SimpleJson data source" class="img-responsive" src="/assets/grafana-datasource.png" /&gt;&lt;/p&gt;

&lt;p&gt;Note that I am running the app on the same server as Grafana, so localhost works for this tutorial, but if you installed Grafana-Salt-Backend anywhere else, make sure to use the correct URL.&lt;/p&gt;

&lt;p&gt;And voila! We are now able to query Salt for node groups! To see it in action go create a new dashboard. We will create two variables. Start by clicking on the gear icon to &lt;strong&gt;Manage dashboard&lt;/strong&gt; and selecting &lt;strong&gt;Templating&lt;/strong&gt;. On the &lt;strong&gt;Variables&lt;/strong&gt; menu, click &lt;strong&gt;New&lt;/strong&gt;. Then, fill out the first variable like:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Get list of node group names" class="img-responsive" src="/assets/grafana-nodegroups.png" /&gt;&lt;/p&gt;

&lt;p&gt;Once done, click &lt;strong&gt;Add&lt;/strong&gt;. We need a second variable, so from the Variable menu again, click &lt;strong&gt;New&lt;/strong&gt;. Then, fill out the second variable like:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Get list of hosts in node group" class="img-responsive" src="/assets/grafana-hosts.png" /&gt;&lt;/p&gt;

&lt;p&gt;Once done, click &lt;strong&gt;Add&lt;/strong&gt;. At the top of the dashboard you should now have two dropdown menus. The first menu allows you to select a node group and the second allows you to select hosts within that node group:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Menus allow you to select node groups and associated hosts" class="img-responsive" src="/assets/grafana-menu.png" /&gt;&lt;/p&gt;

&lt;p&gt;Throughout the template, the variable &lt;code class="language-plaintext highlighter-rouge"&gt;$host&lt;/code&gt; is used to fill in your selected hosts:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Use the $host variable in queries" class="img-responsive" src="/assets/grafana-query.png" /&gt;&lt;/p&gt;</description><author/><pubDate>Tue, 25 Apr 2017 00:34:00 GMT</pubDate><guid isPermaLink="true">https://btmiller.com/2017/04/24/use-saltstack-as-a-datasource-in-grafana.html</guid></item><item><title>AWS Lambda Object Mother</title><link>https://peterlyons.com/problog/2017/04/aws-lambda-object-mother/</link><description>&lt;p&gt;I've been coding a project build on AWS Lambda and I wanted to post a unit testing pattern that has been really helpful especially for input validation. The lambda function input starts with an "event" object which I'm sure in the first version of lambda was reasonably small and simple, but now it can get quite complex with many deeply nested properties when API Gateway authorizers and path parameters are involved. Thus I've been applying the "Object Mother" test pattern to create event objects I can pass to my lambda handler functions during unit testing.&lt;/p&gt;
&lt;p&gt;Here's a few key points before the code excerpt.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;My helper function by default will return a complete and valid event object. This is convenient, but it's also important to prove that if I alter only 1 property and the event is considered invalid, I know the property I altered did in fact cause the invalid state, and not some other missing or invalid property.&lt;/li&gt;
&lt;li&gt;I use the &lt;code&gt;dot2val&lt;/code&gt; module to allow me to consisely express a deeply nested value I want to override. I can also easily null out a nested value in the middle of the object structure with this technique.&lt;/li&gt;
&lt;li&gt;When integrated with API Gateway the &lt;code&gt;event.body&lt;/code&gt; property will unfortunately be an unparsed JSON string literal. Once this is stringified, it's a pain to modify. The pattern I have here allows tweaking of the body object before it gets stringified, which is nice.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here's what it ends up looking like.&lt;/p&gt;
&lt;pre class="language-js "&gt;&lt;code class="language-js"&gt;const dot2val = require(&amp;quot;dot2val&amp;quot;);
const myLambdaHandler = require(&amp;quot;.&amp;#x2f;my-lambda&amp;quot;).handler;
const schemas = require(&amp;quot;..&amp;#x2f;schemas&amp;quot;);
const tap = require(&amp;quot;tap&amp;quot;);

function mockEvent(path, value) {
  &amp;#x2f;&amp;#x2f; First, construct a fully valid mock object
  const event = {
    pathParameters: {
      sort: &amp;quot;asc&amp;quot;
    },
    body: {
      email: schemas.email.example,
      firstName: schemas.name.example,
      lastName: schemas.name.example
    },
    requestContext: {
      authorizer: {
        id: &amp;quot;42&amp;quot;
      }
    }
  };
  &amp;#x2f;&amp;#x2f; If any values need to change, override them here
  if (path) {
    dot2val.set(event, path, value);
  }
  &amp;#x2f;&amp;#x2f; Make body into a JSON string to match lambda environment
  event.body = JSON.stringify(event.body);
  return event;
}

const invalids = [
  [&amp;quot;body.email&amp;quot;, &amp;quot;@jdoe&amp;quot;],
  [&amp;quot;body.email&amp;quot;, &amp;quot;no at here&amp;quot;],
  [&amp;quot;body.email&amp;quot;, false],
  [&amp;quot;body.email&amp;quot;, null],
  [&amp;quot;body.email&amp;quot;, undefined],
  [&amp;quot;body.firstName&amp;quot;, &amp;quot;a&amp;quot;.repeat(51)],
  [&amp;quot;body.firstName&amp;quot;, 0],
  [&amp;quot;body.firstName&amp;quot;, false],
  [&amp;quot;body.firstName&amp;quot;, null],
  [&amp;quot;body.firstName&amp;quot;, undefined],
  [&amp;quot;body.lastName&amp;quot;, &amp;quot;a&amp;quot;.repeat(51)],
  [&amp;quot;body.lastName&amp;quot;, 0],
  [&amp;quot;body.lastName&amp;quot;, false],
  [&amp;quot;body.lastName&amp;quot;, null],
  [&amp;quot;body.lastName&amp;quot;, undefined],
  [&amp;quot;body&amp;quot;, undefined],
  [&amp;quot;pathParameters.sort&amp;quot;, 0],
  [&amp;quot;pathParameters.sort&amp;quot;, false],
  [&amp;quot;pathParameters.sort&amp;quot;, null],
  [&amp;quot;pathParameters&amp;quot;, undefined]
];

invalids.forEach(pair =&amp;gt; {
  tap.test(`createUser validates ${pair[0]}`, {skip: false}, test =&amp;gt; {
    const event = mockEvent(pair[0], pair[1]);
    myLambdaHandler(event, {}, (error, res) =&amp;gt; {
      tap.error(error, &amp;quot;should succeed without error&amp;quot;);
      tap.same(res.statusCode, 400, &amp;quot;should send 400 status&amp;quot;);
      test.end();
    });
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the pattern I use is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up my object mother function, which here I name &lt;code&gt;mockEvent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a list of invalid properties which pairs their object dot notation path string and the value. This is a pretty consice way to test a lot of cases.&lt;/li&gt;
&lt;li&gt;A tiny bit of metaprogramming if you will creates a tap unit test for each invalid property without repetition of the test code itself.&lt;/li&gt;
&lt;/ol&gt;</description><author>Pete's Points</author><pubDate>Mon, 24 Apr 2017 23:41:40 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/04/aws-lambda-object-mother/</guid></item><item><title>The Great Link Dump of April 2017</title><link>https://faingezicht.com/links/2017/04/24/the-great-link-dump/</link><description>It has been a linkless month, so here's a brain dump.</description><author>Avy Faingezicht</author><pubDate>Mon, 24 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/04/24/the-great-link-dump/</guid></item><item><title>Animating appearance &amp;amp; disappearance in React Native</title><link>https://goshacmd.com/react-native-animated-appearance-disappearance/</link><author>Gosha Spark</author><pubDate>Mon, 24 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/react-native-animated-appearance-disappearance/</guid></item><item><title>How to Clean Apple Watch Sport Bands</title><link>https://btmiller.com/2017/04/23/how-to-clean-apple-watch-bands.html</link><description>&lt;p&gt;If you’re like me and constantly tint everything around you a slight shade of indigo from your raw denim jeans, then your white Apple Watch Sport Band is starting to look a little shabby after 2 years of everyday use. Luckily, it only takes about 5-10 minutes of effort to restore your band to its original color.&lt;/p&gt;

&lt;h3 id="things-youll-need"&gt;Things You’ll Need&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://amzn.to/2ok5Uky"&gt;Mr. Clean Magic Eraser&lt;/a&gt; - we’ll be using this to remove the dye stains. Because I also have 2 years worth of dirt and debris also on my band, I use the &lt;a href="http://amzn.to/2pbrkzs"&gt;Extra Durable version&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Stained Apple Watch Sport Band (or similar polymer band).&lt;/li&gt;
  &lt;li&gt;A hard, flat, durable surface.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="lets-get-started"&gt;Let’s Get Started&lt;/h3&gt;

&lt;p&gt;How much cleaning you do is completely up to you, but it should not take more than a few minutes of your time.&lt;/p&gt;

&lt;h4 id="1-prepare-the-eraser"&gt;1. Prepare the eraser&lt;/h4&gt;

&lt;p&gt;&lt;img alt="Mr. Clean Magic Eraser" class="img-responsive" src="/assets/eraser.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Follow the instructions on the Mr. Clean Magic Eraser box for preparing the eraser. In case you throw out the box in haste: you’ll want to wet the eraser and then wring it dry. Be careful when squeezing the water out as too much force applied will tear the eraser (this will happen naturally, but let’s not accelerate the disintegration).&lt;/p&gt;

&lt;h4 id="2-prepare-the-band"&gt;2. Prepare the band&lt;/h4&gt;

&lt;p&gt;Remove the band from the watch body by pressing the release button and sliding out the strap for each one. Place each strap on a flat surface.&lt;/p&gt;

&lt;h4 id="3-clean-the-top-side"&gt;3. Clean the top side&lt;/h4&gt;

&lt;p&gt;&lt;img alt="Top side of bands" class="img-responsive" src="/assets/top-before.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Start with the side of the straps with the pin pointing up (the top side).&lt;/p&gt;

&lt;p&gt;Scrub your straps with the eraser. Depending on how old, stained, and dirty they are, you might need to apply more pressure. The fluoroelastomer straps are pretty hardy and can take a beating - the eraser will give up before the straps do.&lt;/p&gt;

&lt;p&gt;Be careful on the shorter strap with the large opening and pin. This is not an issue for me, but I imagine too much force applied around the opening might break the strap.&lt;/p&gt;

&lt;h4 id="4-clean-the-bottom-side"&gt;4. Clean the bottom side&lt;/h4&gt;

&lt;p&gt;&lt;img alt="Bottom side of bands" class="img-responsive" src="/assets/bottom-before.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Next, flip the straps over to the side that touches your skin (the bottom side). This side will probably have less indigo stain, but mine have plenty of miscellaneous dirt.&lt;/p&gt;

&lt;p&gt;Same process applies here, except for the shorter strap with the large opening and pin (now pointing down). While cleaning the shorter strap, be careful not to scratch or damage your underlying surface as you apply pressure to the material.&lt;/p&gt;



&lt;!-- inline --&gt;
&lt;p&gt;&lt;ins class="adsbygoogle" style="display: block;"&gt;&lt;/ins&gt;
&lt;/p&gt;

&lt;h3 id="results"&gt;Results&lt;/h3&gt;

&lt;p&gt;How much cleaning you do is completely up to you. After about 5-10 minutes of scrubbing my bands, I removed all of the indigo stain in addition to most of the built-up dirt.&lt;/p&gt;

&lt;p&gt;Top side with indigo stain removed:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Top side of bands" class="img-responsive" src="/assets/top-after.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Bottom side with residue removed:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Bottom side of bands" class="img-responsive" src="/assets/bottom-after.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;From a casual observation the straps appear to be pristine white, but it still retains an oily shine:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Cleaning did not remove oily shine" class="img-responsive" src="/assets/shiny.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Comparing the straps to my 4 month old midnight blue straps, you can see that the newer straps have a more matte finish:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Newer bands still have a matte finish" class="img-responsive" src="/assets/shine-comparison.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;The cleaned white straps retain a subtle sheen that picks up more light, so if that matters to you, consider picking up a new band. Nevertheless, a quick scrubbing allows me to put the white band back into circulation.&lt;/p&gt;</description><author/><pubDate>Mon, 24 Apr 2017 00:44:00 GMT</pubDate><guid isPermaLink="true">https://btmiller.com/2017/04/23/how-to-clean-apple-watch-bands.html</guid></item><item><title>Deconstructing an image</title><link>https://rjp.is/blogging/posts/deconstructing-an-image-2/</link><description>The iOS apps and processing steps used to make something moderately interesting from photos of a kitten and a spider.</description><author>infrequent oscillations</author><pubDate>Sun, 23 Apr 2017 17:29:41 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/deconstructing-an-image-2/</guid></item><item><title>Ignorance</title><link>https://blog.nawaz.org/posts/2017/Apr/ignorance/</link><description>&lt;p&gt;There are two types of people: Those who are uncomfortable with their
own ignorance, and those who aim to&amp;nbsp;understand.&lt;/p&gt;
&lt;p&gt;The former will be quick to fill the void with an explanation. The
latter will not stop there, but will seek to test the&amp;nbsp;explanation.&lt;/p&gt;
&lt;p&gt;Most people are of the …&lt;/p&gt;</description><author>Beetle Space</author><pubDate>Sun, 23 Apr 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2017/Apr/ignorance/</guid></item><item><title>Math bookmarks</title><link>https://xenodium.com/math-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.3blue1brown.com/#lessons"&gt;3Blue1Brown&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=14161876"&gt;Calculus Made Easy (1914) (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://math.stackexchange.com/questions/733754/visually-stunning-math-concepts-which-are-easy-to-explain"&gt;Visually stunning math concepts which are easy to explain&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 23 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/math-bookmarks</guid></item><item><title>GnuPG and macOS</title><link>https://xenodium.com/gnupg-and-macos</link><description>&lt;p&gt;Had problems installing and using GnuPG on macOS, primarily for Emacs use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;gpg: problem with the agent: Inappropriate ioctl for device
gpg: error creating passphrase: Operation cancelled
gpg: symmetric encryption of '[stdin]' failed: Operation cancelled
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basic installation required:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install gnupg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But worked around the error above by using pinentry-mac (UI), instead of Emacs prompts.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install pinentry-mac
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edited ~/.gnupg/gpg-agent.conf with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;pinentry-program path/to/homebrew/bin/pinentry-mac
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;May need to kill gpg-agent to reload config.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;gpgconf --kill gpg-agent
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 23 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/gnupg-and-macos</guid></item><item><title>Reciprocity and the Golden Rule</title><link>https://blog.nawaz.org/posts/2017/Apr/reciprocity-and-the-golden-rule/</link><description>&lt;p&gt;Lately I&amp;#8217;ve been reading the book
&lt;a class="reference external" href="https://www.amazon.com/Influence-Psychology-Persuasion-Robert-Cialdini/dp/006124189X"&gt;Influence&lt;/a&gt;
by Robert Cialdini. In it he talks about the &lt;em&gt;principle of reciprocity&lt;/em&gt;.
We tend to repay, in kind, what someone else has given us - even when we
did not want it, and even when we did not &lt;em&gt;take&lt;/em&gt;&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;If someone gives …&lt;/p&gt;</description><author>Beetle Space</author><pubDate>Sat, 22 Apr 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2017/Apr/reciprocity-and-the-golden-rule/</guid></item><item><title>BMW 328i crankshaft sensor issue</title><link>https://caiustheory.com/bmw-328i-crankshaft-sensor-issue/</link><description>&lt;p&gt;My 1996 e36 BMW 328i Convertible was having trouble starting, and it&amp;rsquo;s always broken up &lt;em&gt;slightly&lt;/em&gt; at idle since I took ownership of the car. On a couple of hot days last summer it also stalled during idle, then started doing it again recently (even though the ambient temperature was much colder.)&lt;/p&gt;
&lt;p&gt;The main sympton at the point I took notice was it struggling to start, then hunting at idle until warm, then promptly stalling when warm and idling. It would also cut out when coming to a stop at junctions.&lt;/p&gt;
&lt;p&gt;Reading the codes showed one related to the crankshaft sensor:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;53 Crankshaft Sensor&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;(Codes can also show up in hex, which would be &amp;ldquo;83 Crankshaft Sensor&amp;rdquo;.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I duly replaced both the Crankshaft Sensor (Part # 12141703277) and the Camshaft Sensor (Part # 12141703221), but it was still throwing the crankshaft sensor code.&lt;/p&gt;
&lt;p&gt;Upon closer inspection, the sensor wire in the plug for the crankshaft sensor wasn&amp;rsquo;t pushed fully into the socket under the intake manifold. This lead to the ECU not being able to get a signal from the sensor, so it quite correctly threw a code and didn&amp;rsquo;t run correctly.&lt;/p&gt;
&lt;p&gt;Made sure all the pins were seated in the plug correctly, and reconnected the plug under the intake manifold and she started up perfectly. Drives much better, and the engine pulls more smoothly all the way up the rev range.&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Sat, 22 Apr 2017 01:18:00 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/bmw-328i-crankshaft-sensor-issue/</guid></item><item><title>Teaching my son about computers</title><link>https://honza.pokorny.ca/2017/04/teaching-my-son-about-computers/</link><description>&lt;p&gt;Just over a year ago, my son Wyatt received his first computer for his sixth
birthday.  It&amp;rsquo;s a Raspberry Pi, and he has an old LCD monitor, and a
kid-friendly mouse and keyboard.  I purposely waited until he could read before
starting to teach him about computers.  He&amp;rsquo;s a pretty smart kid, reads a lot (a
Harry Potter book in a weekend), and is somewhat socially awkward.  Perfect for
a programmer.&lt;/p&gt;
&lt;p&gt;The Raspberry Pi doesn&amp;rsquo;t have a cover on it.  The first thing I did was teach
him what each of the parts on the board is.  This is the brain, this is the
memory, this is where power comes in, etc.  His very first task was to plug
everything in.  He had lots of fun trying to figure out where the HDMI cable
goes, where the mouse and keyboard need to be plugged, etc.  To this day, I
teach him about debugging hardware issues by randomly unplugging cables when
he&amp;rsquo;s not around.&lt;/p&gt;
&lt;p&gt;Then we turned it on.  He was very excited about LED lights coming to life.&lt;/p&gt;
&lt;p&gt;Then we were greeted by a headless login screen.  I made him a proper hacker
handle, &lt;code&gt;wjp&lt;/code&gt;, which he was very excited about, and I allowed him to select a
password.  Then, the computer was ready.&lt;/p&gt;
&lt;p&gt;We started out by learning to use bash.  You type in a command and hit &amp;ldquo;enter&amp;rdquo;
to run it.  We explored basic unix commands like &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;echo&lt;/code&gt;, and
&lt;code&gt;date&lt;/code&gt;.  Somewhat annoyingly, the hardest concept to explain to a child is
what a file and a directory are.  It tooks us a few tries over many days for the
concept to really sink in.&lt;/p&gt;
&lt;p&gt;I taught him to use &lt;code&gt;nano&lt;/code&gt; to write simple text documents.  He had fun writing
down a list of all the superheroes he could think of, a list of countries, a
list of his classmates, and so on.  I installed &lt;code&gt;cowsay&lt;/code&gt; which he loved.&lt;/p&gt;
&lt;p&gt;I taught him how to use pipes.  He thought it was hilarious to pipe his
superhero list to &lt;code&gt;cowsay&lt;/code&gt;.  We also experimented with &lt;code&gt;espeak&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, I installed and configured &lt;code&gt;mutt&lt;/code&gt; for him.  He has his own email address
and can now communicate with his grandparents in Europe on his own.  He still
makes mistakes with the proper email syntax and etiquette but overall does email
well.  More than anything, it&amp;rsquo;s limited by his typing speed.&lt;/p&gt;
&lt;p&gt;Wyatt also loves his XMPP client, &lt;code&gt;profanity&lt;/code&gt;.  The great thing is that most
people that he wants to chat with have Google phones and can interact with him
without having to install anything.&lt;/p&gt;
&lt;p&gt;Annoyingly and most frustratingly, Wyatt has an iPad teacher this year at
school.  They do literally everything on iPads.  Every single story he tells
from school involves an iPad.  He wants us to buy him an iPad.  Many of the
other parents are annoyed about this because it makes children less attentive,
less creative, and much more easily bored.  And I hate it because it messes up
his head about Linux.  No, child, &lt;code&gt;ls&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; an app, dammit.  Shut up.  But
we make do.&lt;/p&gt;
&lt;p&gt;Then one blessed day, I showed him the &lt;code&gt;startx&lt;/code&gt; command to start the X window
system.  He was amazed at the colors and buttons, and everything.  Then, we
started exploring windows, menus, and of course Minecraft.  Yes, kids and their
Minecraft.  He likes to draw in Tuxpain, play chess, tetris, and write books in
Libreoffice.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago, I started teaching him basic programming with Python.  He
was very disappointed when he saw the kinds of programs I was going to teach him
to write.  He was under the impression that he was going to write a program that
could turn a movie into a book.  And instead, I suggested we start with &amp;ldquo;Hello
world!&amp;rdquo; and leave AI for later.&lt;/p&gt;
&lt;p&gt;We started with a simple &amp;ldquo;Hello world!&amp;rdquo;.  We switched from &lt;code&gt;nano&lt;/code&gt; to &lt;a href="https://github.com/zyedidia/micro"&gt;micro&lt;/a&gt;
which is very similar and has syntax highlighting.  Writing a Hello world
program might seem dumb to experienced programmers but it&amp;rsquo;s great at showing the
novice how to connect everything together: the file, the interpreter, the
command to run the program, etc.&lt;/p&gt;
&lt;p&gt;Then, we wrote a simple &amp;ldquo;Die toss&amp;rdquo; program.  He was excited about it because it
did something different each time, and not just say the same thing like the
first program.&lt;/p&gt;
&lt;p&gt;Yesterday, we wrote a simple quiz.  This time, he wrote all the code by himself
with my telling him how.  Print a question and answers, use &lt;code&gt;raw_input()&lt;/code&gt; to
ask for the user&amp;rsquo;s selection, and then a simple &lt;code&gt;if&lt;/code&gt; statement to determine if
they were correct.  It&amp;rsquo;s amazing how easy Python makes this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;answer &lt;span style="color: #81a1c1;"&gt;=&lt;/span&gt; raw_input&lt;span style="color: #eceff4;"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #81a1c1; font-weight: bold;"&gt;if&lt;/span&gt; answer &lt;span style="color: #81a1c1; font-weight: bold;"&gt;is&lt;/span&gt; &lt;span style="color: #a3be8c;"&gt;'b'&lt;/span&gt;&lt;span style="color: #eceff4;"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #81a1c1;"&gt;print&lt;/span&gt; &lt;span style="color: #a3be8c;"&gt;'You are correct'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It reads like English.  He very quickly got the concept of if statements, and
started writing more and more questions.  Then, of course, every family member
had to take the quiz.&lt;/p&gt;
&lt;p&gt;Later that day, he told his mother that he wanted to be a programmer.  He wants
to write &amp;ldquo;apps&amp;rdquo;.  His mother suggested that he can ask me to get him a job at
Red Hat, or that he could work at Google.  He scoffed at that and said he didn&amp;rsquo;t
want to work on one project for a year like his Dad, and that, please, there are
no computers or programmers at Google.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Thu, 20 Apr 2017 16:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/04/teaching-my-son-about-computers/</guid></item><item><title>Art is about creating perspective</title><link>https://yasha.solutions/art-is-about-creating-perspective/</link><description>Design is about solving problem
Art is about creating perspective
Both place the human dimension at the center of their craft
It is never about the tool or the medium per se
It is always about the experience
Imagination is the trigger
Pulling the trigger take you out of this world
Use text – images – sound – video – animation – sculpture – theatre – anything.
Take the weapon of your choice.</description><author>Yasha Solutions</author><pubDate>Thu, 20 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/art-is-about-creating-perspective/</guid></item><item><title>Tour of D3 for Clueless Folk Like Me</title><link>https://josh.works/tour-of-d3</link><description>&lt;p&gt;D3 stands for &lt;a href="https://en.wikipedia.org/wiki/D3.js"&gt;Data Driven Documents&lt;/a&gt;, and it’s the coolest thing ever.&lt;/p&gt;

&lt;p&gt;Check out a few examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.jasondavies.com/animated-bezier/"&gt;Animated, interactive curves&lt;/a&gt;(dynamic)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bl.ocks.org/mbostock/9539958"&gt;OMG Particles II&lt;/a&gt;(dynamic)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bl.ocks.org/mbostock/885fffe88d72b2a25c090e0bbbef382f"&gt;simple map of the us&lt;/a&gt;(static) &amp;lt;= very little code&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bl.ocks.org/mbostock/4739610f6d96aaad2fb1e78a72b385ab"&gt;Radial Dendrogram&lt;/a&gt;(static)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bl.ocks.org/mbostock/2d466ec3417722e3568cd83fc35338e3"&gt;circle wave&lt;/a&gt;(dynamic)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bl.ocks.org/mbostock/95aa92e2f4e8345aaa55a4a94d41ce37"&gt;Force-directed tree&lt;/a&gt;(dynamic) &amp;lt;= super cool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, this is the kind of stuff you can do with D3. The Front-end track at Turing gave a short lesson on D3, and I was one of two back-end folks participating. This was actually really encouraging, because they didn’t know much about d3 either.&lt;/p&gt;

&lt;p&gt;So, lets dig into D3 a bit, and do two things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Get a running d3 map running locally (we’re gonna use &lt;a href="https://bl.ocks.org/mbostock/2d466ec3417722e3568cd83fc35338e3"&gt;circle wave&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Deconstruct a simple d3 project to it’s minimum components, expecting that we’ll learn something along the way.&lt;/li&gt;
&lt;/ol&gt;

&lt;!--more--&gt;
&lt;p&gt;&lt;em&gt;Note to the reader: I know _almost nothing&lt;/em&gt; about frontend tools. If you’re comfortable on the front-end, bear with my ignorance. If you, too, know nothing about the front-end, great! This should be at your level._&lt;/p&gt;

&lt;h1 id="running-circle-wave-locally"&gt;Running circle-wave locally&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;you’ll need a text editor and a browser. I’m using Chrome and Atom.&lt;/li&gt;
  &lt;li&gt;you’ll need to be able to open up various files on your computer in Chrome and your text editor. My tool of choice is the command line + iterm + zsh.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, have a folder you can stick this all in. I’ve got &lt;code class="language-plaintext highlighter-rouge"&gt;/d3/circle-wave/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, open up the &lt;a href="https://bl.ocks.org/mbostock/2d466ec3417722e3568cd83fc35338e3"&gt;circle wave project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;See where it says “index.html” on the page, followed by the code?&lt;/p&gt;

&lt;p&gt;Copy and paste all that into &lt;code class="language-plaintext highlighter-rouge"&gt;index.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Save the file, and open it in chrome. &lt;code class="language-plaintext highlighter-rouge"&gt;open -a "Google Chrome" index.html&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;open index.html&lt;/code&gt;, run from the folder holding the file, should get it opened up for you. If it’s opening it in finder or something, google around to figure out what works for you.&lt;/p&gt;

&lt;p&gt;At this point, you &lt;em&gt;should&lt;/em&gt; have opened up the file on your machine. You’ll know this because the URL is something like &lt;code class="language-plaintext highlighter-rouge"&gt;file:///Users/joshthompson/turing/2mod/self_study/d3/circle_wave/index.html&lt;/code&gt;, and you should see the circle-wave animation running.&lt;/p&gt;

&lt;h2 id="breaking-things"&gt;Breaking things&lt;/h2&gt;

&lt;p&gt;Lets deconstruct what’s going on a bit. Open up Chrome’s Dev Tools (cmd+shift+i) and look at the code. Tab over to &lt;code class="language-plaintext highlighter-rouge"&gt;elements&lt;/code&gt;, and it should look pretty simple, pretty static.&lt;/p&gt;

&lt;p&gt;Next, lets &lt;em&gt;inspect&lt;/em&gt; just the circle wave itself. Open up the “selection tool” (it’s the mouse icon in a box on the top left side of your dev-tools toolbar. The shortcut is &lt;code class="language-plaintext highlighter-rouge"&gt;cmd+shft+c&lt;/code&gt; and mouseover &lt;em&gt;just&lt;/em&gt; the circle itself.&lt;/p&gt;

&lt;p&gt;Now it’s a bit strange. You should get a slowly-moving box with rapidly-changing x/y values:&lt;/p&gt;

&lt;p&gt;&lt;img alt="box doing stuff" src="https://cl.ly/3t2B3j0E450X/Screen%20Recording%202017-04-01%20at%2003.17%20PM.gif" /&gt;&lt;/p&gt;

&lt;p&gt;When you click on it, you’ll see the values in your HTML going bananas:&lt;/p&gt;

&lt;p&gt;&lt;img alt="crazy scrolling values" src="https://cl.ly/0m1p151z0u0p/index_html.png" /&gt;&lt;/p&gt;

&lt;p&gt;it looks like all that is happening inside of the &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;path stroke="cyna" style="mix-blend-mode: darken;" d= {crazy values here}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets play with these values for a bit. In the browser, double-click on the “cyan” element. (you might not be seeing cyan, but have a different color. it depends on which line you managed to click on above.)&lt;/p&gt;

&lt;p&gt;Change it to red, or green, or whatever. When I changed it (a few times) at one point the element got centered way away from everything else, and looked super crazy.&lt;/p&gt;

&lt;p&gt;&lt;img alt="broke this line's centering" src="https://cl.ly/162A1j3O3d0O/index_html.png" /&gt;&lt;/p&gt;

&lt;h2 id="d3-docs-console-changing-values"&gt;D3 Docs, console, changing values&lt;/h2&gt;

&lt;p&gt;Looking through the code, there’s a few things that jump out at me:&lt;/p&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&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;What’s the &lt;code class="language-plaintext highlighter-rouge"&gt;.now&lt;/code&gt; method on d3? The &lt;a href="https://github.com/d3/d3-timer/blob/master/README.md#now"&gt;docs&lt;/a&gt; say it just picks the current time value, sorta like &lt;code class="language-plaintext highlighter-rouge"&gt;Time.now&lt;/code&gt; in Ruby.&lt;/p&gt;

&lt;p&gt;Popping into the dev tools console, lets try &lt;code class="language-plaintext highlighter-rouge"&gt;d3.now()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ah, interesting. values. And in the code, it’s calling &lt;code class="language-plaintext highlighter-rouge"&gt;d3.now() / 1000;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Looks like that returns a random number between (maybe) 1..100, with many decimal points.&lt;/p&gt;

&lt;p&gt;I’m gonna try “hardcoding” the &lt;code class="language-plaintext highlighter-rouge"&gt;t&lt;/code&gt; value in the code I’ve copied into Atom.&lt;/p&gt;

&lt;p&gt;When I changed&lt;/p&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&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;to&lt;/p&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;44.328915&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;the animation is frozen. It just starts and doesn’t move. So I think d3.now is pulling an &lt;em&gt;always new&lt;/em&gt; value for time. This must be what makes the circle move at a consistent pace. (Or I’m totally wrong. who knows)&lt;/p&gt;

&lt;p&gt;That makes sense, though. Here’s where that time variable is being used:&lt;/p&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&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;PI&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;32&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;So &lt;code class="language-plaintext highlighter-rouge"&gt;t&lt;/code&gt; is talking to both &lt;code class="language-plaintext highlighter-rouge"&gt;cos&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;Digging into that &lt;code class="language-plaintext highlighter-rouge"&gt;cos&lt;/code&gt; function, I looked in the D3 docs, and it doesn’t have a Math module. Turns out that’s just JavaScript. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cos"&gt;JavaScript’s Math.cos()&lt;/a&gt; for the curious.&lt;/p&gt;

&lt;h2 id="d3curvelinearclosed"&gt;d3.curveLinearClosed&lt;/h2&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;radialLine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;curve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;curveLinearClosed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&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;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&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;PI&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;32&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;That &lt;code class="language-plaintext highlighter-rouge"&gt;curveLinearClosed&lt;/code&gt; is interesting. D3’s docs indicate that &lt;code class="language-plaintext highlighter-rouge"&gt;curveLinear&lt;/code&gt; is also a valid option. Lets try it out.&lt;/p&gt;

&lt;p&gt;&lt;img alt="non-connected lines" src="https://cl.ly/2S153W1b1N36/index_html.png" /&gt;&lt;/p&gt;

&lt;p&gt;Makes sense. The &lt;a href="https://github.com/d3/d3-shape/blob/master/README.md#curveLinear"&gt;docs&lt;/a&gt; say the difference between curveLinear and curveLinearClosed is if there’s a line drawn between the first and last element in the line.&lt;/p&gt;

&lt;p&gt;the first var block looks interesting:&lt;/p&gt;

&lt;div class="language-js highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;angles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;2&lt;/span&gt; &lt;span class="o"&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;PI&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;PI&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;200&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;I’m curious about that &lt;code class="language-plaintext highlighter-rouge"&gt;angles&lt;/code&gt; value. d3.range(something complicated) gives… what exactly?&lt;/p&gt;

&lt;p&gt;Over to the console:&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;d3.range(0, 2 * Math.PI, Math.PI / 200);
=&amp;gt; Array[400]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well, what’s in the array?&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;x.forEach(
    console.log)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(pardon my bad JavaScript syntax. I’ve not done much with it before today…)&lt;/p&gt;

&lt;p&gt;And that printed a &lt;em&gt;ton&lt;/em&gt; of stuff to the console.&lt;/p&gt;

&lt;p&gt;Turns out theres a better way to see what’s in an array. Just click the arrow next to it, and you can open it up.&lt;/p&gt;

&lt;p&gt;So, looks like this array is composed of four ranges: &lt;code class="language-plaintext highlighter-rouge"&gt;[0...99],[100...199],[200...299],[300...399]&lt;/code&gt;. Each of those has a bunch more values inside, like:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;1: 0.015707963267948967
2: 0.031415926535897934
3: 0.0471238898038469
4: 0.06283185307179587
5: 0.07853981633974483
6: 0.0942477796076938
7: 0.10995574287564278
8: 0.12566370614359174
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Crazy. There’s some mad mathing going on in here.&lt;/p&gt;

&lt;p&gt;OK, in &lt;code class="language-plaintext highlighter-rouge"&gt;svg.append("g")&lt;/code&gt;, that’s how D3 talks to (or about) SVGs. it’s “Grouping”, I believe.&lt;/p&gt;

&lt;p&gt;Lets see how much we can delete and still have something working:&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Wed, 19 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/tour-of-d3</guid></item><item><title>ROS production: our prototype as a snap [3/5]</title><link>https://kyrofa.com/posts/ros-production-our-prototype-as-a-snap-3-5/</link><description>UPDATE: I&amp;rsquo;m leaving this series up for historical purposes, but please note that I no longer recommend Ubuntu Core or snaps for use in robotics.
This is the third blog post in this series about ROS production. In the previous post we came up with a simple ROS prototype. In this post we&amp;rsquo;ll package that prototype as a snap. For justifications behind why we&amp;rsquo;re doing this, please see the first post in the series.</description><author>kyrofa's blog</author><pubDate>Wed, 19 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-production-our-prototype-as-a-snap-3-5/</guid></item><item><title>Go channels</title><link>https://www.danielcorin.com/posts/2017/2017-04-18-go-channels/</link><description>Go channels</description><author>Thought Eddies</author><pubDate>Wed, 19 Apr 2017 00:30:00 GMT</pubDate><guid isPermaLink="true">https://www.danielcorin.com/posts/2017/2017-04-18-go-channels/</guid></item><item><title>secrets in zsh history</title><link>https://peterlyons.com/problog/2017/04/secrets-in-zsh-history/</link><description>&lt;p&gt;I've been trying to get a manageable system for dealing with projects that need a lot of settings, some of which are secrets such as credentials. In general, environment variables are the most widely-supported mechanism. They have many shortcomings: they are exposed by the OS to other processes running as your user or root via the &lt;code&gt;/proc&lt;/code&gt; filesystem (at least on linux), don't have data types other than strings, can't express nesting or arrays easily, etc. However, they can get the job done if you keep things simple.&lt;/p&gt;
&lt;p&gt;Anyway one of my main concerns was keeping these secrets relatively secret but also not massively inconvenient for actual development work. My approach so far has been to keep them encrypted in 1password as a multiline notes field that is just some shell syntax to export them as environment variables. It looks something like this:&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;export AWS_ACCESS_KEY_ID=&amp;#x27;blah blah blah&amp;#x27;
# Use this for dev
export AWS_REGION=&amp;#x27;us-west-2&amp;#x27;
# Use this to test the standby region
export AWS_REGION=&amp;#x27;us-east-1&amp;#x27;
# etc etc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So I feel pretty good that this is securely off disk. I would copy and paste this into my shell and go about my work. However, these commands then get put into my shell history which are clear text files. I wanted something this convenient but keeping secrets out of my shell history.&lt;/p&gt;
&lt;p&gt;What I came up with is this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;eval $(pbpaste;echo)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Which I set up as a keyboard macro so I type &lt;code&gt;epb,,&lt;/code&gt;, keyboard maestro detects the double comma and looks up the proper snippet to expand the text. The eval tells the shell to execute the code and the pbpaste bit outputs the text I just copied from 1password.&lt;/p&gt;
&lt;p&gt;So this is better. Some shells allow omitting a command from history by typing a leading space in front of it, just FYI but I felt that was too error prone to use consistently.&lt;/p&gt;
&lt;p&gt;It's still not ideal as stuff lives in memory probably longer than it should, and the mechanism to clear things is to exit the shell, which I don't do regularly enough because there's usually state in the shell I don't want to have to re-setup like activating python virtualenvs, etc. It's also possible to unintentionally copy some other text before you paste it into the terminal, thus shooting yourself with your&lt;code&gt; eval&lt;/code&gt; footgun.&lt;/p&gt;
&lt;p&gt;Got something better to suggest?&lt;/p&gt;
&lt;p&gt;Side note for zsh: &lt;code&gt;setopt interactivecomments&lt;/code&gt; will avoid annoying errors when you paste snippets with comments into an interactive shell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE (2017-09-12)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It looks like &lt;a href="https://github.com/99designs/aws-vault"&gt;aws-vault&lt;/a&gt; is a handy tool for this as well. I've started using it on 2 projects and so far so good, but it only handles the AWS creds, not randow other project vars.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Mon, 17 Apr 2017 03:25:00 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/04/secrets-in-zsh-history/</guid></item><item><title>The dystopian future of Virtual Reality and Augmented Reality</title><link>https://yasha.solutions/the-dystopian-ar-vr/</link><description>I am a big believer that technology is neither bad nor good.
Technology is just a tool than enable our capacity to be more of what we are already.
We can use technology to solve problems.
Potentially, we can create a better society.
But it is not up to technology but how we use it.
 Recently – Virtual Reality (VR) Augmented Reality (AR) are more and more trendy.
Everyone is super excited about where all this is going.</description><author>Yasha Solutions</author><pubDate>Mon, 17 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/the-dystopian-ar-vr/</guid></item><item><title>2017-04-17</title><link>https://ho.dges.online/pictures/2017-04-17/</link><description/><author>ho.dges.online</author><pubDate>Mon, 17 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-04-17/</guid></item><item><title>Better Call Saul: Season 3</title><link>https://olshansky.info/tv/better_call_saul_season_3/</link><description>Olshansky's review of Better Call Saul: Season 3</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 16 Apr 2017 16:17:23 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/better_call_saul_season_3/</guid></item><item><title>The Founder</title><link>https://olshansky.info/movie/the_founder/</link><description>Olshansky's review of The Founder</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 15 Apr 2017 05:11:58 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_founder/</guid></item><item><title>Pragmatic Programmer</title><link>https://www.craigpardey.com/post/2017-04-15-andy-hunt/</link><description>&lt;p&gt;&lt;a href="https://www.amazon.ca/dp/020161622X"&gt;The Pragmatic Programmer&lt;/a&gt; is one of the most influential books that I have read as a software developer. It is right up there with Software Craftsmanship and Clean Code.  Andy Hunt recently gave &lt;a href="http://bestprogrammingbooks.com/interview-andy-hunt-coauthor-pragmatic-programmer-journeyman-master/"&gt;an interview&lt;/a&gt; that was peppered with several poignent quotes that struck a chord with me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You need to understand how to work with other people, both with teammates and with those pesky users&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the single piece of advice that I&amp;rsquo;d give to anyone looking to get into software development.  A team that works well together can accomplish anything even if it is only staffed with &amp;ldquo;intermediate&amp;rdquo; developers. In contrast, I&amp;rsquo;ve seen teams stacked with &amp;ldquo;rock stars&amp;rdquo; that have failed to produce anything meaningful due to poor team dynamics and toxic attitudes.&lt;/p&gt;</description><author>Craig Pardey</author><pubDate>Sat, 15 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.craigpardey.com/post/2017-04-15-andy-hunt/</guid></item><item><title>Make shit happen</title><link>https://yasha.solutions/make-shit-happen/</link><description>#Make shit happen Get out and shout your truth to the world
You might be wrong but you will never know until you get it out
Breaking news: the world will go on with or without you – so better you become an active part of it.
#Just do it Just move on and create.
Make new things happen.
Try out.
Produce.
Experiment.
Throw things out to the world and see what sticks.</description><author>Yasha Solutions</author><pubDate>Sat, 15 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/make-shit-happen/</guid></item><item><title>Make your own iPhone – a crazy and fascinating experiment</title><link>https://yasha.solutions/make-your-own-iphone-a-crazy-and-fascinating-experiment/</link><description>Ever wonder if you can build your own phone?
Well this guy did.   Last time I checked how to make a phone myself, the only thing I could find always seemed very hard and not very practical (just have a look at this DIY Smartphonebased on a rasperry-pi)
But the Strange Parts’s project is really impressive and give plenty of hopes for a different future of DIY-phones.
While I am probably not going to that myself, it is still rather instructive and inspiring.</description><author>Yasha Solutions</author><pubDate>Sat, 15 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/make-your-own-iphone-a-crazy-and-fascinating-experiment/</guid></item><item><title>WTF is Shenzhen</title><link>https://yasha.solutions/wtf-is-shenzhen/</link><description>Ok, if you have never heard of Shenzhen, China you might want to get yourself up to date with this quick article – because really, it is getting more and more attention lately, as it has turned into a major platform of electronic hardware manufacturing of the past 15 years.
 Located north of Hong Kong, Shenzen is the center of the supply chain hub for electronics. All of the major contract manufacturers working for Apple, HP, Microsoft and all the big guys all are there.</description><author>Yasha Solutions</author><pubDate>Sat, 15 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/wtf-is-shenzhen/</guid></item><item><title>2017-04-15</title><link>https://ho.dges.online/pictures/2017-04-15/</link><description/><author>ho.dges.online</author><pubDate>Sat, 15 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-04-15/</guid></item><item><title>Neural Network Poetry</title><link>https://mbutler.org/neural-network-poetry/</link><description>As you may know, April is national poetry month, an annual series of events by the Academy of American Poets to help support the appreciation of American poetry. If you&amp;#8217;re looking for great book-length collections of poems, you might be interested in the Iowa Poetry Prize winners. Many of the previous years&amp;#8217; winners are made [&amp;#8230;]</description><author>mbutler</author><pubDate>Fri, 14 Apr 2017 22:09:10 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/neural-network-poetry/</guid></item><item><title>Rick and Morty: Season 3</title><link>https://olshansky.info/tv/rick_and_morty_season_3/</link><description>Olshansky's review of Rick and Morty: Season 3</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 14 Apr 2017 16:47:07 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/rick_and_morty_season_3/</guid></item><item><title>Linux Mint Disable "Recently Used"</title><link>https://thomashunter.name/posts/2017-04-14-linux-mint-disable-recently-used</link><author>Thomas Hunter II</author><pubDate>Fri, 14 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-04-14-linux-mint-disable-recently-used</guid></item><item><title>Handling C++ exceptions in Go</title><link>https://artem.krylysov.com/blog/2017/04/13/handling-cpp-exceptions-in-go/</link><description>&lt;p&gt;Cgo is a mechanism that allows Go packages call C code. The Go compiler enables cgo for every &lt;span class="docutils literal"&gt;.go&lt;/span&gt; source file that imports a special pseudo package &lt;span class="docutils literal"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;. The text in the comment before the &lt;span class="docutils literal"&gt;import &amp;quot;C&amp;quot;&lt;/span&gt; line is treated as a C code. You can include headers, define functions, types and variables - everything a normal C code can do:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="cm"&gt;/*
#include &amp;lt;stdio.h&amp;gt;

void foo(int x) {
    printf(&amp;quot;x: %d\n&amp;quot;, x);
}
 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;func&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;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// x: 123&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The identifiers declared in the embedded C code can be accessed using the &lt;span class="docutils literal"&gt;&amp;quot;C&amp;quot;&lt;/span&gt; package - e.g. write &lt;span class="docutils literal"&gt;C.foo(C.int(123))&lt;/span&gt; to call the function &lt;span class="docutils literal"&gt;foo&lt;/span&gt;. Pretty straightforward, right? This opens the door to a huge amount of code that was written in C or was written in any other language and provides C bindings.&lt;/p&gt;
&lt;p&gt;Almost all libraries play by the rules, but some libraries that are written in C++ may throw exceptions. C doesn't support exceptions, therefore there is no way to catch them in C or Go/cgo. C function &lt;em&gt;should&lt;/em&gt; never throw an exception, but nothing stops a developer from writing code that does it. A good example of such a library is a machine learning project &lt;a class="reference external" href="https://github.com/JohnLangford/vowpal_wabbit" target="_blank"&gt;Vowpal Wabbit&lt;/a&gt; - it's written in C++ and provides a C interface, which may throw an exception from time to time:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;// #cgo LDFLAGS: -lvw_c_wrapper&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// #include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// #include &amp;lt;vowpalwabbit/vwdll.h&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unsafe&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;func&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;cArgs&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;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;invalid args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cArgs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VW_InitializeA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// exception&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unhandled C++ exception on &lt;span class="docutils literal"&gt;VW_InitializeA&lt;/span&gt; call just crashes the program:&lt;/p&gt;
&lt;pre class="literal-block"&gt;SIGABRT: abort
PC=0x7efc793a7428 m=0 sigcode=18446744073709551610
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4500b0, 0xc420049f58, 0xc420049f58)
    /usr/lib/go-1.8/src/runtime/cgocall.go:131 +0xe2 fp=0xc420049f28 sp=0xc420049ee8
main._Cfunc_VW_InitializeA(0x193c620, 0x0)&lt;/pre&gt;
&lt;p&gt;While cgo lets us call only C code, we still can link any C++ file to our program. This gives us an ability to create a C wrapper for &lt;span class="docutils literal"&gt;VW_InitializeA&lt;/span&gt; that handles the exceptions. We can use a structure to return both the original return value and a pointer to the exception message (good old C doesn't support tuples or multiple return values):&lt;/p&gt;
&lt;pre class="code cpp literal-block"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vw_wrapper.h
&lt;/span&gt;&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&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="cp"&gt;#endif
&lt;/span&gt;&lt;span class="w"&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;stdlib.h&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;vowpalwabbit/vwdll.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;VWW_HANDLE_ERR&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;VW_HANDLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pstrErr&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;VWW_HANDLE_ERR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;VW_DLL_MEMBER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VWW_HANDLE_ERR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VW_CALLING_CONV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VWW_InitializeA&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="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pstrArgs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="cp"&gt;#endif&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The wrapper code is only a few lines, save it in the project directory as a &lt;span class="docutils literal"&gt;.cpp&lt;/span&gt; file:&lt;/p&gt;
&lt;pre class="code cpp literal-block"&gt;&lt;code&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.h&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;exception&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;quot;vw_wrapper.h&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;VW_DLL_MEMBER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VWW_HANDLE_ERR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VW_CALLING_CONV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VWW_InitializeA&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="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pstrArgs&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;VWW_HANDLE_ERR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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="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;try&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle&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;VW_InitializeA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pstrArgs&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;catch&lt;/span&gt;&lt;span class="p"&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;exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;e&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pstrErr&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;strdup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;what&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;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;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Go compiler will compile and link the C++ source with the program. Don't forget to explicitly free the &lt;span class="docutils literal"&gt;strErr&lt;/span&gt; pointer if its value is not &lt;span class="docutils literal"&gt;nil&lt;/span&gt; - Go garbage collector doesn't know how to deal with C pointers:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;// #cgo LDFLAGS: -lvw_c_wrapper&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// #include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// #include &amp;quot;vw_wrapper.h&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kn"&gt;import&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="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unsafe&amp;quot;&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;func&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;cArgs&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;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;invalid args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cArgs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;ret&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;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VWW_InitializeA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cArgs&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="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pstrErr&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="kc"&gt;nil&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;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pstrErr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;VW error: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GoString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pstrErr&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, whenever the original &lt;span class="docutils literal"&gt;VW_InitializeA&lt;/span&gt; throws an exception, the C++ wrapper will catch it and return the error message as a part of the &lt;span class="docutils literal"&gt;VWW_HANDLE_ERR&lt;/span&gt; structure.&lt;/p&gt;</description><author>Artem Krylysov</author><pubDate>Thu, 13 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://artem.krylysov.com/blog/2017/04/13/handling-cpp-exceptions-in-go/</guid></item><item><title>Facebook and the Future of Global Governance</title><link>https://stop.zona-m.net/2017/04/facebook-and-the-future-of-global-governance/</link><description>&lt;p&gt;&lt;em&gt;(this is a guest post by &lt;a href="http://www.twitter.com/epastreich"&gt;Emanuel Pastreich&lt;/a&gt;, director of &lt;a href="http://asia-institute.org"&gt;The Asia Institute&lt;/a&gt;, and Professor at &lt;a href="http://kic.khu.ac.kr/faculty-directory/pastreich-emanuel"&gt;Kyung Hee University&lt;/a&gt;. The post, originally published at &lt;a href="http://www.truth-out.org/opinion/item/22838-facebook-and-the-future-of-global-governance"&gt;Truthout, in April 2014&lt;/a&gt;, is now reposted here on invitation of the author, to whom I am grateful. My own proposal for a better alternative to Facebook and similar services is &lt;a href="http://per-cloud.com"&gt;here&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 12 Apr 2017 20:42:35 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/facebook-and-the-future-of-global-governance/</guid></item><item><title>Matlab Metaprogramming</title><link>https://bastibe.de/2017-04-12-matlab-metaprogramming.html</link><description>&lt;p&gt;Why is it, that I find Matlab to be a fine teaching tool and a fine tool for solving engineering problems, but at the same time, extremely cumbersome for my own work? Recently, the answer struck me: &lt;em&gt;metaprogramming in Matlab sucks&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Matlab is marketed as a tool for engineers to solve engineering problems. There are convenient data structures for numerical data (arrays, tables), less convenient data structures for non-numeric data (cells, structs, chars), and a host of expensive but powerful functions and methods for working with this kind of data. This is the happy path.&lt;/p&gt;
&lt;p&gt;But don't stray too far from the happy path; horrors lurk where The Mathworks don't dare going. Basic stuff like talking to sockets or interacting with other programs is very cumbersome in Matlab, and sometimes even downright impossible for the lack of threads, pipes, and similar infrastructure. But this is common knowledge, and consistent with Matlab's goals as an engineering tool, not a general purpose programming language. These are first-order problems, and they are rarely insurmountable.&lt;/p&gt;
&lt;p&gt;The more insidious problem is metaprogramming, i.e. when the objects of your code are code objects themselves. The first order use of programming is to solve real-world problems. If these problems are numeric in nature, Matlab has got you covered. But as every programmer discovers at some point, the second order use of programming is to solve programming problems. And by golly, will Matlab let you down when you try that!&lt;/p&gt;
&lt;p&gt;As soon as you climb that ladder of abstraction, and the objects of your code become code objects themselves, you will enter weird country. You think &lt;code&gt;exist&lt;/code&gt; will tell you whether a variable name is taken? Try calling it on a method. You think &lt;code&gt;nargout&lt;/code&gt; will always give you a number? Again, methods will enlighten you. Quick, how do you capture all output arguments of a function call in a variable? &lt;code&gt;x = cell(nargout(fun), 1); [x{:}] = fun(...)&lt;/code&gt;, obviously (this sometimes fails). And don't even think of trying to overload &lt;code&gt;subsref&lt;/code&gt; to create something generic. Those &lt;code&gt;subsref&lt;/code&gt; semantics are &lt;a href="https://mathworks.com/help/matlab/matlab_oop/code-patterns-for-subsref-and-subsasgn-methods.html"&gt;crazy talk&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I could go on. The real power of code is abstraction. We use programming to repeatedly and reliably solve similar problems. The logical next step is to use those same programming tools to solve similar &lt;em&gt;kinds&lt;/em&gt; of problems. This happens to all of us, and Matlab makes it extremely hard to deal with. Thus, it puts a ceiling on the level of abstraction that is reasonably achievable, and limits engineers to first-order solutions. And after a few years of acclimatization, it will put that same ceiling on those engineers' thinking, because you can't reason about what you can't express.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Wed, 12 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2017-04-12-matlab-metaprogramming.html</guid></item><item><title>Unit testing code that needs data in a database</title><link>https://www.databasesandlife.com/unit-test-databases/</link><description>&lt;p&gt;If you write a method like &amp;ldquo;add product to user&amp;rsquo;s cart&amp;rdquo;, you want to test that that method works.&lt;/p&gt;
&lt;p&gt;That method may require state to exist e.g. in a database (e.g. that the user exists, to whose cart the product shall be added), and testing it automatically e.g. with JUnit may require querying the new state (e.g. that the product is now in the user&amp;rsquo;s cart).&lt;/p&gt;
&lt;p&gt;You have these options:&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Wed, 12 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/unit-test-databases/</guid></item><item><title>My Top 5 ’90s Hip-Hop Tracks</title><link>https://huphtur.nl/my-top-5-90s-hip-hop-tracks/</link><description>&lt;p&gt;My friend &lt;a href="https://twitter.com/MattBochneak"&gt;Matt Bochneak&lt;/a&gt; sent me a link to &lt;a href="http://www.self-titledmag.com/2017/04/05/hauschka-top-5-90s-hip-hop-tracks/"&gt;Hauschka’s Top 5 ’90s Hip-Hop Tracks&lt;/a&gt;. He thought the picks weren’t that great. I replied that it’s actually pretty hard to make picks because that era is so good. Which got me thinking, could I pick 5 tracks?&lt;/p&gt;
&lt;p&gt;Here’s the list of artists I looked at (pretty sure I still forgot a bunch):
2Pac,
A Tribe Called Quest,
Arrested Development,
Beastie Boys,
Big L,
Big Pun,
Black Sheep,
Black Star,
Bone Thugs-n-Harmony,
Busta Rhymes,
Casual,
Cypress Hill,
DJ Jazzy Jeff &amp;amp; The Fresh Prince,
DMX,
Dead Prez,
Del the Funky Homosapien,
Digable Planets,
Dr. Dre,
Eminem,
Eric B. &amp;amp; Rakim,
Fugees,
GZA,
Gang Starr,
House Of Pain,
Ice Cube,
Jay-Z,
Jeru The Damaja,
KRS-One,
LL Cool J,
Lauryn Hill,
Method Man,
Missy Elliott,
Mobb Deep,
Mos Def,
N.W.A.,
Nas,
Naughty By Nature,
Outkast,
Pharoahe Monch,
Public Enemy,
Redman,
Scarface,
Sir Mix-A-Lot,
Snoop Dogg,
Souls of Mischief,
The Notorious B.I.G.,
The Pharcyde,
and Wu-Tang Clan.&lt;/p&gt;
&lt;p&gt;After a week of internal debating, I was able to narrow it down to 5, but I failed in ranking them 😥. Here are my picks, sorted by release date…&lt;/p&gt;
&lt;h2&gt;Eric B. &amp;amp; Rakim - Don’t Sweat The Technique (1992)&lt;/h2&gt;
&lt;p&gt;Rakim, the greatest MC ever? &lt;em&gt;“Pencils and pens are swords / Letters put together from a key to chords.”&lt;/em&gt;. Eric B.’s beats on this track are amazing. The way the song starts with the bass line (sampled from Young-Holt Unlimited - &lt;a href="https://www.youtube.com/watch?v=Fcj1JHxq5fk"&gt;Queen Of The Nile&lt;/a&gt;), followed by a saxophone (from Kool &amp;amp; the Gang - &lt;a href="https://www.youtube.com/watch?v=YAcYoAyPdVM"&gt;Give It Up&lt;/a&gt;), Rakim’s voice and then that heavy bass drum 👍. The video clip is classic too, so many girls! DJ Cam Quartet did a great &lt;a href="https://www.youtube.com/watch?v=V24qn18dW1Q"&gt;jazz cover&lt;/a&gt; of the song.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/6Y1Emb7Jyks"&gt;https://youtu.be/6Y1Emb7Jyks&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;The Pharcyde - Passin’ Me By (1992)&lt;/h2&gt;
&lt;p&gt;I could leave it at &lt;a href="https://www.youtube.com/watch?v=6xN3KOY2kbg"&gt;Summer in the City&lt;/a&gt;, but did you know about there’s all kinds of behind-the-scenes drama related to this song? According to most resources, J-Swift (originally from Spain) produced &lt;em&gt;Passin’ Me By&lt;/em&gt;. But, Imani and Bootie Brown (two members from The Pharcyde) claim that J-Swift &lt;a href="http://revive-music.com/2012/06/11/imani-bootie-brown-are-the-pharcyde-celebrities-on-the-brink-of-insanity-part-1/#.V5FryLgrK00"&gt;did not&lt;/a&gt; produce &lt;em&gt;Passin’ Me By&lt;/em&gt;. After the release of the album, J-Swift gained some success (even did some remixes for Prince and Massive Attack) but  fell into depression and a gnarly drug addiction. In 2007, a documentary movie, &lt;em&gt;&lt;a href="https://www.youtube.com/watch?v=HUCAhmsap_w"&gt;1 More Hit&lt;/a&gt;&lt;/em&gt;, was made about his path to sobriety. In 2015, J-Swift relapsed, got caught with some substances and got deported to Spain. He recently &lt;a href="https://www.youtube.com/watch?v=MghX_KCmnUY"&gt;made a video&lt;/a&gt; directed at (then) president Obama in hopes of returning home to his family in the US.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/a-mAK3uB2_0"&gt;https://youtu.be/a-mAK3uB2_0&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Jeru The Damaja - Come Clean (1993)&lt;/h2&gt;
&lt;p&gt;DJ Premiere made the beat specifically for Jeru. That wood block sound (Shelly Manne - &lt;a href="https://www.youtube.com/watch?v=fox8MliHOeA"&gt;Infinity&lt;/a&gt;) is what drew me in to this track. I guess it symbolizes: “Chinese water torture”. Works for me! Complex did a great &lt;a href="https://www.youtube.com/watch?v=XHyQ14zEZls"&gt;mini-doc&lt;/a&gt; about the making of this song. And how sick is that opening line? &lt;em&gt;“You wanna front, what, jump up and get bucked”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/4lVH8wkp6J4"&gt;https://youtu.be/4lVH8wkp6J4&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;GZA - Cold World (1995)&lt;/h2&gt;
&lt;p&gt;The darkest and most sinister track of the &lt;em&gt;Liquid Swords&lt;/em&gt; album. Unfortunately not shown in the official video, but on the album the song start with a sample from the movie, &lt;a href="https://en.wikipedia.org/wiki/Shogun_Assassin"&gt;Shogun Assasin&lt;/a&gt;. &lt;em&gt;“I had a bad dream. Don’t be afraid, bad dreams are only dreams. What a time you chose to be born.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/s48GO6tBm3A"&gt;https://youtu.be/s48GO6tBm3A&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Fugees - Ready or Not (1996)&lt;/h2&gt;
&lt;p&gt;Let’s not kid ourselves, &lt;em&gt;The Score&lt;/em&gt;, is filled with bangers. This track did not do so well in the US, but in Europe it did. I think it’s because it contained an &lt;a href="https://www.youtube.com/watch?v=JKQwgpaLR6o"&gt;Enya sample&lt;/a&gt;. Yankees seem to not dig Enya as much as we Euros do, so therefor I pick &lt;em&gt;Ready or Not&lt;/em&gt; as my favorite Fugees track. Vibe reported that the video started the era of big budget, movie-like hip hop videos. The video features 🚁 🦈 🚗 🔫 🏍 💥, and cost $1.3 million to produce. In justifying the price tag, Pras &lt;a href="https://books.google.com/books?id=CywEAAAAMBAJ&amp;amp;pg=PA28&amp;amp;dq=fugees+ready+or+not+video+cost#v=onepage&amp;amp;q=fugees%20ready%20or%20not%20video%20cost&amp;amp;f=false"&gt;told Vibe&lt;/a&gt; &lt;em&gt;“People want to see drama, man. You figure: A kid pays sixteen dollars for your CD. Let him see a good video.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/aIXyKmElvv8"&gt;https://youtu.be/aIXyKmElvv8&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Did I make the right picks? &lt;a href="https://twitter.com/huphtur"&gt;Hollar at me&lt;/a&gt; on the Twitter!&lt;/p&gt;</description><author>huphtur</author><pubDate>Wed, 12 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://huphtur.nl/my-top-5-90s-hip-hop-tracks/</guid></item><item><title>ROS production: our prototype [2/5]</title><link>https://kyrofa.com/posts/ros-production-our-prototype-2-5/</link><description>UPDATE: I&amp;rsquo;m leaving this series up for historical purposes, but please note that I no longer recommend Ubuntu Core or snaps for use in robotics.
This is the second blog post in this series about ROS production. In the previous post we discussed why Ubuntu Core was a good fit for production robotics. In this post we&amp;rsquo;ll be on classic Ubuntu, creating the example ROS prototype that we&amp;rsquo;ll use throughout the rest of the series as we work toward using Ubuntu Core.</description><author>kyrofa's blog</author><pubDate>Wed, 12 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-production-our-prototype-2-5/</guid></item><item><title>The Unbearable Lightness of Being</title><link>https://apurva-shukla.me/bookshelf/the-unbearable-lightness-of-being/</link><description>⭐ ⭐ ⭐ ⭐ ⭐ circa 2019

This novel never fails to question how we live our lives. It explores many characters, with their equally many…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Tue, 11 Apr 2017 13:39:14 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/the-unbearable-lightness-of-being/</guid></item><item><title>Mastodon is a problem only if you want it to be a platform</title><link>https://stop.zona-m.net/2017/04/mastodon-is-a-problem-only-if-you-want-it-to-be-a-platform/</link><description>&lt;p&gt;I just found online what is, in my opinion, another proof that certain concerns about the &amp;ldquo;Twitter replacement&amp;rdquo; called Mastodon are solid&amp;hellip; but the solutions that get the most attention right now may be dead ends.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 11 Apr 2017 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/mastodon-is-a-problem-only-if-you-want-it-to-be-a-platform/</guid></item><item><title>Infrastructure Survey Results</title><link>https://justingarrison.com/blog/2017-04-11-infrastructure-survey-results/</link><description>I recently ran a survey about infrastructure and applications for some research.</description><author>Justin Garrison's Homepage</author><pubDate>Tue, 11 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2017-04-11-infrastructure-survey-results/</guid></item><item><title>YAC - Why? Lollipop And Kotlin</title><link>https://prashamhtrivedi.in/yac_why_kotlin.html</link><description>In second part of the series I talk about why I decided to choose Lollipop as Min SDK and why I developed the app in kotlin</description><author>Prasham H Trivedi</author><pubDate>Tue, 11 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/yac_why_kotlin.html</guid></item><item><title>Nobody cares about online identities? Really?</title><link>https://stop.zona-m.net/2017/04/nobody-cares-about-online-identities-really/</link><description>&lt;figure&gt;
  &lt;img alt="Nobody cares about online identities? Really? /img/online-identities.png" src="https://stop.zona-m.net//img/online-identities.png" width="100%" /&gt;
&lt;/figure&gt;
&lt;p&gt;Reading my recent posts about &lt;a href="http://stop.zona-m.net/2017/04/on-mastodon-flaws-and-decentralized-services/"&gt;&amp;ldquo;Mastodon flaws&amp;quot;that are NOT flaws&lt;/a&gt; and &lt;a href="http://stop.zona-m.net/2017/04/no-you-dont-need-another-twitter-or-medium"&gt;online identities in general&lt;/a&gt;, an online contact of mine replied with several comments, whose main points I believe may be synthesized as follows (any error here is mine, of course):&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 10 Apr 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/nobody-cares-about-online-identities-really/</guid></item><item><title>The Inside-Out Corporation</title><link>https://www.danstroot.com/posts/2017-04-7-the-inside-out-corporation</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/citadel.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Most companies still have a separate corporate network, protected by firewalls, intrusion prevention/detection, dedicated administrators, VPNs, etc. Why is it that I can access information which is the most important, private, and precious to me, from any computer, via any network, without all that extra cost, complexity, overhead, and effort?&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2017-04-7-the-inside-out-corporation"&gt;The Inside-Out Corporation&lt;/a&gt; first appeared on &lt;a href="https://www.danstroot.com"&gt;Dan Stroot's Blog&lt;/a&gt;</description><author>Dan Stroot</author><pubDate>Mon, 10 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2017-04-7-the-inside-out-corporation</guid></item><item><title>A Quick Link Previewer for Mattermost</title><link>https://bfontaine.net/2017/04/09/a-quick-link-previewer-for-mattermost/</link><description>&lt;p&gt;&lt;a href="https://about.mattermost.com/"&gt;Mattermost&lt;/a&gt; is a &lt;a href="https://slack.com/"&gt;Slack&lt;/a&gt;-like self-hosted and open-source alternative. We
use it at work but for some reason link previews don’t work. Before diving into
Mattermost’s internals I wanted to see if I could write a quick workaround
using the fact that Mattermost does show an image if you post a link ending
with &lt;code class="language-plaintext highlighter-rouge"&gt;.png&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;.jpg&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="the-current-situation"&gt;The Current Situation&lt;/h2&gt;

&lt;p&gt;When you post an image link, Mattermost makes a request to show it in the
application. It detects those images using a &lt;a href="https://github.com/mattermost/platform/blob/3aaf71fdea914af1a7f2b2fb97bb6ae44132fcc4/webapp/components/post_view/components/post_body_additional_content.jsx#L74"&gt;regexp&lt;/a&gt;; not by e.g.
sending a &lt;code class="language-plaintext highlighter-rouge"&gt;HEAD&lt;/code&gt; request to get the content type. If you have an image URL that
doesn’t end with common extentions Mattermost won’t show it.&lt;/p&gt;

&lt;p&gt;Mattermost doesn’t serve you a preview of the image; it rather gives you an
&lt;code class="language-plaintext highlighter-rouge"&gt;img&lt;/code&gt; with the original URL. That means every single person reading the channel
will request the image from its original location. Slack, on the other hand,
fetch images, cache them, and serves them from its own domain,
&lt;code class="language-plaintext highlighter-rouge"&gt;https://slack-imgs.com&lt;/code&gt;. Slack uses a custom user-agent for its request so you
know where it comes from.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;User-Agent: Slackbot-LinkExpanding 1.0 (…)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mattermost, on the other hand, can’t use a custom user-agent because the
request is done by &lt;em&gt;your&lt;/em&gt; browser. The only thing distinguishing Mattermost’s
request for a preview and any other request is it asks for an image:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Accept: image/webp,image/*,*/*;q=0.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The header above is Chrome telling the Web server it can deal with &lt;a href="https://developers.google.com/speed/webp/"&gt;WebP&lt;/a&gt;
images, then images in any format, then anything; in that order. Note
&lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=169182"&gt;it explicitly says it accepts WebP images&lt;/a&gt; because some
browsers don’t support the format.&lt;/p&gt;

&lt;p&gt;Unfortunately not all browsers are explicit. Firefox sends &lt;code class="language-plaintext highlighter-rouge"&gt;Accept: */*&lt;/code&gt; since
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values"&gt;Firefox 47&lt;/a&gt; and so did IE8 and earlier versions. In those cases we can’t
really do anything beside complicated rules based on the user-agent and other
headers.&lt;/p&gt;

&lt;h2 id="proxying-requests"&gt;Proxying Requests&lt;/h2&gt;

&lt;p&gt;If we know how to tell if a request comes from Mattermost asking for an image
preview rather than a “normal” user we can serve different contents to them: a
link preview as an image to Mattermost, and the normal content to the user.&lt;/p&gt;

&lt;p&gt;All we have to do is to make some sort of intelligent proxy. Using &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; we
can make something like this:&lt;/p&gt;

&lt;div class="language-python highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&amp;lt;path:path&amp;gt;/p.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&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="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;m an image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a small web application that takes any route in the form of
&lt;code class="language-plaintext highlighter-rouge"&gt;/&amp;lt;url&amp;gt;/p.png&lt;/code&gt; and either redirects you to that URL if your &lt;code class="language-plaintext highlighter-rouge"&gt;Accept&lt;/code&gt; header
doesn’t start with &lt;code class="language-plaintext highlighter-rouge"&gt;image/&lt;/code&gt;; either serves you a &lt;code class="language-plaintext highlighter-rouge"&gt;Hello, I'm an image&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;All we have to do now is to return an actual image in lieu of that placeholder
text. I used &lt;a href="http://docs.python-requests.org/en/master/"&gt;Requests&lt;/a&gt; and &lt;a href="https://www.crummy.com/software/BeautifulSoup/"&gt;Beautiful Soup&lt;/a&gt; to fetch and parse
webpages, and &lt;a href="https://pillow.readthedocs.io/en/4.1.x/"&gt;Pillow&lt;/a&gt; to generate images.&lt;/p&gt;

&lt;p&gt;When one requests &lt;code class="language-plaintext highlighter-rouge"&gt;http://example.com/http://...some...url.../p.png&lt;/code&gt;, the
app fetches that URL; parses it to extract its title and some excerpt; write
that on a blank image; and serves it.&lt;/p&gt;

&lt;p&gt;Extracting the title is as easy as grabbing that &lt;code class="language-plaintext highlighter-rouge"&gt;title&lt;/code&gt; HTML tag. If
available, I also try the &lt;code class="language-plaintext highlighter-rouge"&gt;og:title&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;twitter:title&lt;/code&gt; &lt;code class="language-plaintext highlighter-rouge"&gt;meta&lt;/code&gt; tags. If none
of those are available, I fallback on the first &lt;code class="language-plaintext highlighter-rouge"&gt;h1&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;h2&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;Getting an usable excerpt is not too hard; here again I search for common
&lt;code class="language-plaintext highlighter-rouge"&gt;meta&lt;/code&gt; tags: &lt;code class="language-plaintext highlighter-rouge"&gt;description&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;og:description&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;twitter:description&lt;/code&gt;. If I can’t
get any of them I take the first &lt;code class="language-plaintext highlighter-rouge"&gt;p&lt;/code&gt; that looks long enough.&lt;/p&gt;

&lt;p&gt;You can check that code on &lt;a href="https://github.com/bfontaine/previewer/blob/7e2172de36aa9832bfd71097a760a5d64087dc19/previewer/page.py#L38-L80"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="generating-images"&gt;Generating Images&lt;/h2&gt;

&lt;p&gt;The Pillow library makes it easy to write text on an image. I replaced the
(ugly) default font with &lt;a href="https://www.fontsquirrel.com/fonts/alegreya"&gt;Alegreya&lt;/a&gt;. The tricky part is mostly to fit the
text on the image. I used &lt;a href="https://github.com/bfontaine/previewer/blob/7e2172de36aa9832bfd71097a760a5d64087dc19/previewer/text.py"&gt;a combination&lt;/a&gt; of &lt;a href="https://pillow.readthedocs.io/en/latest/reference/ImageDraw.html#PIL.ImageDraw.PIL.ImageDraw.Draw.textsize"&gt;Draw#textsize&lt;/a&gt;
to get the dimensions of some text as if it were written on the image and
Python’s &lt;a href="https://docs.python.org/3/library/textwrap.html"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;textwrap&lt;/code&gt;&lt;/a&gt; module to cut the title and excerpt so that
they wouldn’t cross the right side of the image.&lt;/p&gt;

&lt;p&gt;I used fixed dimensions for all images (400×70) and kept a small padding along
their sides. Previews with small or missing excerpts get some unused white
space at the bottom; this could be fixed by pre-computing the final size of the
image &lt;em&gt;before&lt;/em&gt; creating it.&lt;/p&gt;

&lt;figure class="center"&gt;
&lt;img alt="Google.com preview" class="squared" src="/blog/images/preview-google.png" /&gt;
&lt;figcaption&gt;Google.com’s generated preview&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class="center"&gt;
&lt;img alt="Mattermost's GitHub repo preview" class="squared" src="/blog/images/preview-github.png" /&gt;
&lt;figcaption&gt;GitHub repos have a very small excerpt&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;On most websites the preview works fine. We could tweak the text size as well
as add a favicon or an extracted image.&lt;/p&gt;

&lt;figure class="center"&gt;
&lt;img alt="This post's preview" class="squared" src="/blog/images/preview-post.png" /&gt;
&lt;figcaption&gt;This post’s generated preview&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In the end it took a couple hours to have a working prototype. Most of that
time was spent dealing with encoding issues and trying various webpages to find
edge cases.&lt;/p&gt;

&lt;p&gt;The result is acceptable; it has the issue of not being accessible at all but
that’s still better than nothing.&lt;/p&gt;

&lt;p&gt;The source code is on &lt;a href="https://github.com/bfontaine/previewer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</description><author>Baptiste Fontaine’s Blog</author><pubDate>Sun, 09 Apr 2017 16:11:00 GMT</pubDate><guid isPermaLink="true">https://bfontaine.net/2017/04/09/a-quick-link-previewer-for-mattermost/</guid></item><item><title>Sometimes, In the Forest</title><link>https://one.mikro2nd.net/pages/sometimes-in-the-forest/</link><description>And sometimes in the Forest you find a fairy and sometimes, seldom, so very, very rarely, one is slow enough to catch and so you catch it and eat it, all crunchy and sticky and thinly sweet like nectar, and never enough to satisfy and not enough substance to really nourish, but still a seldom treat in the forest.
And they go well with the Mushrooms that sometimes you find, off in the far ends of Winter after some rain and tucked away in the deeper gloom where the trees grow thick and not much light reaches the ground so almost nothing grows but what takes hold on the crumbling and dusty mouldering and falling apart logs that litter the floor of the forest.</description><author>one mikro2nd</author><pubDate>Sun, 09 Apr 2017 15:59:24 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/sometimes-in-the-forest/</guid></item><item><title>An anecdotic tour on the history of programming languages</title><link>https://nutcroft.mataroa.blog/blog/an-anecdotic-tour-on-the-history-of-programming-languages/</link><description>&lt;blockquote&gt;
&lt;p&gt;Disclaimer: The following 2514 words might not be wholly accurate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once upon a time, in 1972, the year of the last manned Moon landing, a programming language was born:&lt;/p&gt;
&lt;p&gt;C, a general purpose, procedural language was designed by Dennis Ritchie, one of the two Unix legends, at Bell Labs (which as of 2016 are a subsidiary of Nokia).&lt;/p&gt;
&lt;p&gt;It was named C because it was an improved B, a previous programming language, which was a simplified BCPL (hence its name).&lt;/p&gt;
&lt;p&gt;After they wrote C, they decided to re-write Unix to it. This venture was completed steadily and in parts.&lt;/p&gt;
&lt;p&gt;During the end of the decade, and in the next one (80s) versions of C were implemented for a wide variety of computers, including the IBM PC. This resulted in C becoming ubiquitous and the go-to language for systems.&lt;/p&gt;
&lt;p&gt;Many people worshipped C. They created religions, cults, sects. Mind control techniques were discovered in old journals, and then, it happened.&lt;/p&gt;
&lt;p&gt;An old tomb was discovered in Mesopotamia with its walls covered in C code. How could it be? A language for computers written in 1972 being a part of an ancient religion?&lt;/p&gt;
&lt;p&gt;Only joking.&lt;/p&gt;
&lt;p&gt;But really, many people loved C, like the creator of the Linux kernel, Linus Torvalds. Others didn’t like it so much, maybe they felt that something was missing. Such is the case of Bjarne Stroustrup, the man behind C++.&lt;/p&gt;
&lt;p&gt;Bjarne was into Object Oriented Programming, so one sunny day in 1982 he thought:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Maybe I should create a language like C, but with classes. I’ll name it ‘C with Classes’.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When one year later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Maybe that was not such a good name. I’ll rename it to C++. Yeah. That’s better.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Linus was not thrilled at all by C++. To be precise, he resented it. Mainly because of lack of portability and &lt;em&gt;inefficient abstracted programming models&lt;/em&gt;, as he says.&lt;/p&gt;
&lt;p&gt;Five years later, in 1987, Larry Wall started working on Perl and at the end of the year version 1.0 was ready. Unfortunately, Larry, like all programmers, was more interested in writing code than its documentation, so it took 4 years and the wide adoption of the language for the Camel Book, the classic Perl book, to be written.&lt;/p&gt;
&lt;p&gt;At the same year, in Portland, OR, the &lt;a href="https://en.wikipedia.org/wiki/International_Conference_on_Functional_Programming"&gt;Functional Programming Languages and Computer Architecture&lt;/a&gt; (FPCA ’87) conference was held. It was an academic conference. One of its outcomes was the participants’ decision that they really like &lt;em&gt;Miranda&lt;/em&gt; (a proprietary lazy functional language) and its descendants, and they should better create a committee to define an open standard for all these languages.&lt;/p&gt;
&lt;p&gt;It took them three years, and in 1990 the &lt;em&gt;Haskell Language and Library Committee&lt;/em&gt; announced version 1.0.&lt;/p&gt;
&lt;p&gt;Due to this history, Haskell is considered an academic language and does not have much adoption in the industry. However, there are various companies across the world that do use it.&lt;/p&gt;
&lt;p&gt;One year later, only in 1991, Guido van Rossum released the first version of Python. 🎉. He really enjoyed Monty Python, so he thought to use half their name. After all, it’s also a snake.&lt;/p&gt;
&lt;p&gt;Guido didn’t want to just create a language. He had a vision, and a mantra. &lt;a href="https://www.python.org/dev/peps/pep-0020/"&gt;The Zen of Python&lt;/a&gt;, as they call it, is the core philosophy of the language. It includes abstract comparisons between concepts such as beauty, simplicity, and complexity, and it is adored by all Pythoneers.&lt;/p&gt;
&lt;p&gt;Despite and along with all that, a lot of people came to like Python. It is also very multi-paradigm. It is imperative, object-oriented and with multiple Lisp-like functional features. It was the first language to put first the intuitiveness of the user in contrast of the underlying mechanisms of the compiler.&lt;/p&gt;
&lt;p&gt;Four years later, in 1995, NASA’s Galileo Probe entered Jupiter’s atmosphere and the &lt;a href="https://en.wikipedia.org/wiki/Phytophthora_ramorum"&gt;Sudden Oak Death&lt;/a&gt; (SOD) was first reported. &lt;em&gt;Phytophthora ramorum&lt;/em&gt;, the oomycete plant pathogen behind SOD, is the reason that many oak populations in California and Oregon died. It is also believed that this organism is the cause of a proportionally large number of successful programming languages being created this year, both in California and in other areas too.&lt;/p&gt;
&lt;p&gt;The spotlight on Java, JavaScript, PHP, and Ruby.&lt;/p&gt;
&lt;p&gt;Yukihiro Matsumoto was writing mostly Perl and he was happy about it. He was also quite intrigued by Python, but with some complaints present:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It seems to me that Python is not a true object oriented language. I’d say it’s an imposter. OOP features appear to be some kind of add-on. As if they said, “yeah, throw that inside too”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It was obvious that Guido wanted to support many paradigms, so object-oriented concepts were not top priority in the language design process.&lt;/p&gt;
&lt;p&gt;But Matz really believed that OOP is the future, and not one of the features. And thus, Ruby was born, with its name, of course, paying homage to Perl.&lt;/p&gt;
&lt;p&gt;In Ruby everything is a function call, even arithmetic operations with &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;-&lt;/code&gt;. And thus, parenthesis in function calls are in most cases optional.&lt;/p&gt;
&lt;p&gt;The above decisions polarized the software community to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh my god! This is so beautiful! I’ll write everything in Ruby now!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh my god! This is fucking insane! How could one think of such atrocity?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Features such as &lt;code&gt;5.times { do_this }&lt;/code&gt; contributed to further polarization, even in the UK:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ruby lover: Oh my god! This is so expressive! Even more expressive than Python! I love it!&lt;/p&gt;
&lt;p&gt;Ruby skeptic: Oh my god! This is bloody mental! Oh, the horror…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Evidently, apart from successful, 1995 programming languages were also very contentious.&lt;/p&gt;
&lt;p&gt;It was a fine day of 1995 when Rasmus Lerdorf thought:&lt;/p&gt;
&lt;p&gt;Why not extract all those CGIs written in C that I have for my home page in something separate? I’ll add web forms integrations and db libs and I’ll call it Personal Home Page/Forms Interpreter, or just PHP/FI!&lt;/p&gt;
&lt;p&gt;In hindsight, it was one of the most controversial ideas of the web. PHP was unique in the development speed of a dynamic website, and that made a lot of people choose it even though Rasmus didn’t like that his fast hack became one of the most used programming languages. It still lacked good design and its independent development resulted in various inconsistencies inside the language. Undeniably, &lt;a href="https://en.wikipedia.org/wiki/Worse_is_better"&gt;worse is better&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Sudden Oak Disease took effect even in large companies, like Sun Microsystems. They somehow got the idea that they should create a new &lt;em&gt;write-once run-everywhere&lt;/em&gt; programming language. They would do that by creating a virtual machine for all platforms, with a common API. Its name: &lt;em&gt;Oak&lt;/em&gt;; named after an oak tree that stood outside its creator’s, James Gosling’s, office. This, of course, verifies the theory that the Sudden Oak Disease is accountable for the creation and success of the four languages of 1995.&lt;/p&gt;
&lt;p&gt;Oak was later renamed to &lt;em&gt;Green&lt;/em&gt; and finally &lt;em&gt;Java&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Java follows a classical inheritance object oriented paradigm. This, according to James, was not a good idea after all and had he been asked to re-create Java he would throw the inheritance hierarchy idea under a tree (probably an Oak) in favor of object delegation.&lt;/p&gt;
&lt;p&gt;This is quite interesting as it turns out, because the language that does fulfill Java’s dream for write-once run-everywhere turned out to be JavaScript, which has object delegation.&lt;/p&gt;
&lt;p&gt;And thus, we reach the final item on the 1995 list. JavaScript.&lt;/p&gt;
&lt;p&gt;There are many programming languages in this world, and their distribution with respect to language design is &lt;a href="https://en.wikipedia.org/wiki/Normal_distribution"&gt;Gaussian&lt;/a&gt;. The majority has a good design; some have somewhat good or somewhat bad design; and very few have an outstanding design or a horrifying one. Had you been asked to choose from one of those categories for the language that would run to the greatest number of computers ever, which would you pick? As it turns out, we did end up beyond three sigma, just not the positive edge. The spread was gradual, few noticed.&lt;/p&gt;
&lt;p&gt;It was a cold afternoon of 1995, at the Netscape Communications HQ in Mountain View, CA, when the company hired Brendan Eich to embed Scheme inside their browser, Netscape Navigator. It was only Scheme, a Lisp dialect; what could go wrong? However, as fast a developer as he was, he wasn’t able to start working on it until something, well… everything changed.&lt;/p&gt;
&lt;p&gt;It took Brendan ten days to create a prototype of a language called &lt;em&gt;Mocha&lt;/em&gt;. &lt;em&gt;Another&lt;/em&gt; coffee related word you might think? Might there be an off chance they are related? Indeed, Netscape made a deal with Sun Microsystems to include a lightweight scripting Java-like language to compete with Microsoft. Mocha seemed an appropriate name. It was a beautiful name, but it was deemed as a missed opportunity to advertise Java; so after a brief stint with &lt;em&gt;LiveScript&lt;/em&gt;, &lt;em&gt;JavaScript&lt;/em&gt; was conceived.&lt;/p&gt;
&lt;p&gt;Brendan had a vision with Mocha, and JavaScript is influenced by a wide variety of different paradigms of languages. Features like first class functions, prototypal inheritance, and event driven are what make JavaScript such an interesting language to work with. Furthermore, JavaScript due to its quirks and design flaws is a difficult language to master given its simple (yet elusive) features. Some say this perpetual challenge motivates them; others stay away while appreciating their lack of masochism.&lt;/p&gt;
&lt;p&gt;After 1995 and until the end of the decade not much happened.&lt;/p&gt;
&lt;p&gt;Then in 2000, Microsoft decided to create its own Java. The outcome was C#.&lt;/p&gt;
&lt;p&gt;Java’s creator James Gosling noticed that and didn’t refrain from giving voice to his thoughts&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;C# is sort of Java with reliability, productivity and security deleted.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thankfully, C# diverged from Java with its subsequent versions and with the introduction of a wide variety of features. It is, also, the main language of the .NET platform, Microsoft’s web platform.&lt;/p&gt;
&lt;p&gt;2004 came and Martin Odersky’s resolve to make his vision a blissful reality was being accomplished. His dream was to merge the old philosophy of functional programming and the new of object orienticism. The result: Scala, a programming language that encapsulates the functional paradigm inside object orienticism. Scala has a strong type system like Java, though very concise, unlike Java. It has many other connections with it, like the fact that Scala can be compiled to JVM bytecode and also, quite predictably, call Java libraries directly from Scala code.&lt;/p&gt;
&lt;p&gt;Three years later, in 2007, Rich Hickey, who, like Martin liked the JVM and functional things, published his 2½-years&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt; work on creating a modern Lisp. &lt;em&gt;Clojure&lt;/em&gt; has acquired a following over the last years, and there is a variety of companies that use it on production web environments. Along with the implementation for the JVM, there is also ClojureScript, which compiles to JavaScript. This means you can write Clojure for the frontend. 🎊.&lt;/p&gt;
&lt;p&gt;Then, in 2009, at Google, something of eminent importance happened. Ken Thompson (the second Unix legend), Rob Pike, and another person on whom there is no Wikipedia article, Robert Griesemer, created Go. These gentlemen were also in the C++ hate club&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt; because C++’s complexity served as a &lt;em&gt;primary&lt;/em&gt; (!) &lt;em&gt;motivation for the initiative&lt;/em&gt;. It is speculated that the colloquy at Google at that time was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ken: “Oh man, I just hate C++!”&lt;br /&gt;
Rob: “I know. It sucks…”&lt;br /&gt;
Robert: “Hey, let’s create our own language that would be super simple. It won’t have classes. Or destructors. Or-”&lt;br /&gt;
Ken: “Or generics!”&lt;br /&gt;
Rob: “Or exceptions!”&lt;br /&gt;
Robert: “Or operator overloading!”&lt;br /&gt;
Ken: “Or inheritance.”&lt;br /&gt;
Rob: “Or malloc.”&lt;br /&gt;
Robert: “Or while.”&lt;br /&gt;
Rob: “Not even while? Neat :wink:”&lt;br /&gt;
Ken: “Or variables!”&lt;br /&gt;
&lt;em&gt;(all three look puzzled)&lt;/em&gt;&lt;br /&gt;
Ken continues: “OK, let’s have variables. But we’ll have type inference.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Go has been widely criticized that it threw some decades of programming experience out of the window, and did not include the above — and many other — features. This decision, however, had the effect of having a gradual learning curve while over-protecting you from making common mistakes.&lt;/p&gt;
&lt;p&gt;As far as concurrency is concerned, there are two primitives in Go, namely goroutines and channels, which implement what is known as &lt;em&gt;Communicating Sequential Processes&lt;/em&gt;, an idea first described by &lt;a href="https://en.wikipedia.org/wiki/Tony_Hoare"&gt;Tony Hoare&lt;/a&gt; (the human who invented &lt;em&gt;quicksort&lt;/em&gt;, and other important CS theories). This is considered one of the strong points of Go.&lt;/p&gt;
&lt;p&gt;One year later, in 2010, a personal project of Graydon Hoare’s was announced by Mozilla that it is being sponsored. The beautifully named &lt;em&gt;Rust&lt;/em&gt; lang was quietly born in 2006 and it took only 9 years to reach 1.0, in 2015. Since then, it has been one of the most loved&lt;sup id="fnref:4"&gt;&lt;a class="footnote-ref" href="#fn:4"&gt;4&lt;/a&gt;&lt;/sup&gt; programming languages.&lt;/p&gt;
&lt;p&gt;It is fascinating how much thought has been poured into the design of this language, and particularly the design of its type system, its unique feature. Rust is designed to be memory safe. It achieves this through concepts such as &lt;em&gt;owned variables&lt;/em&gt;, &lt;em&gt;borrowed pointers&lt;/em&gt; and &lt;em&gt;variable lifetime management&lt;/em&gt;. In addition, it does not support classical inheritance but it has a &lt;em&gt;trait&lt;/em&gt; system, inspired by Haskell.&lt;/p&gt;
&lt;p&gt;Then in 2011, something exciting happened. Ruby and Erlang had an offspring. It’s called &lt;em&gt;Elixir&lt;/em&gt;, and many people think very highly of it.&lt;/p&gt;
&lt;p&gt;Before talking about Elixir, though, let’s do a background check on its less known procreator.&lt;/p&gt;
&lt;p&gt;Erlang is a language from 1986, created at Ericsson, and remaining proprietary until 1998. Erlang is not just a language, it’s a cult. People who believe in Erlang have a specific worldview&lt;sup id="fnref:5"&gt;&lt;a class="footnote-ref" href="#fn:5"&gt;5&lt;/a&gt;&lt;/sup&gt; which includes arcane decrees such as &lt;em&gt;Everything is a process&lt;/em&gt; and &lt;em&gt;Error handling is non-local&lt;/em&gt;. Joe Armstrong, one of the three inventors, has said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If Java is ‘write once, run anywhere’, then Erlang is ‘write once, run forever’.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Given that he said this in 2013 can we hold him accountable for Erlang if Java doesn’t turn out to be “run everywhere”? 😏&lt;/p&gt;
&lt;p&gt;Erlang has a proven track record of large scale, distributed, high availability web services. Furthermore, it has some magnificent characteristics like fault tolerance, hot code swapping, and pattern matching. José Valim decided to merge these breathtaking features with some other, friendlier ones, along with some Ruby ideas. The result is Elixir.&lt;/p&gt;
&lt;p&gt;Elixir is fully compatible with Erlang’s VM, &lt;em&gt;BEAM&lt;/em&gt;. It also provides nice tooling, which Erlang does not have, and it has successfully won over people, mainly from the Ruby community. Its flagship web framework is &lt;em&gt;Phoenix&lt;/em&gt; which has accumulated rave reviews.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Chris_Lattner"&gt;Chris Lattner&lt;/a&gt;, the legend behind LLVM, while at Apple, invented and led the development of &lt;em&gt;Swift&lt;/em&gt;. It began in 2010 but it wasn’t until 2014 that we learnt about it. Swift has both influenced and been influenced by Rust. It is a compiled language with a strong static type system while it adheres to protocol-oriented programming, an idea also known as interfaces.&lt;/p&gt;
&lt;p&gt;The memory management is done using &lt;em&gt;Automatic Reference Counting&lt;/em&gt; (ARC), which includes compile-time memory deallocation decisions, a Rust resemblance. Swift, a year after its announcement became open source, which enabled developers to extend it beyond Apple’s interfaces. Its use on other domains like the web is rising, as does the adoption from other companies.&lt;/p&gt;
&lt;p&gt;The history of programming languages is very interesting to read about. It urges you to make predictions for the future. My bet is that Swift, Rust, and Go will win over many domains, with the largest one being that of C and C++.&lt;/p&gt;
&lt;p&gt;Hopefully, after 45 years, C will pass the scepter and let us prove to ourselves that we now know software better.&lt;/p&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://hackernoon.com/an-anecdotic-tour-on-the-history-of-programming-languages-928bc6e9a9a8"&gt;HackerNoon&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://www.cnet.com/news/why-microsofts-c-isnt/"&gt;Why Microsoft's C# isn't&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a href="https://download.clojure.org/papers/clojure-hopl-iv-final.pdf"&gt;A History of Clojure&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a href="https://www.drdobbs.com/open-source/interview-with-ken-thompson/229502480"&gt;Interview with Ken Thompson&lt;/a&gt;: &lt;em&gt;The creator of UNIX discusses writing UNIX, the Go language, and collaborating with Dennis Ritchie&lt;/em&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/insights/survey/2017#most-loved-dreaded-and-wanted"&gt;Stack Overflow Developer Survey 2017&lt;/a&gt;: &lt;em&gt;Most Loved, Dreaded, and Wanted&lt;/em&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;Chapter 3.1 Overview (p. 39/51) from &lt;a href="http://erlang.org/download/armstrong_thesis_2003.pdf"&gt;Making reliable distributed systems in the presence of software errors&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:5" title="Jump back to footnote 5 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><author>nutcroft</author><pubDate>Sun, 09 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nutcroft.mataroa.blog/blog/an-anecdotic-tour-on-the-history-of-programming-languages/</guid></item><item><title>No, you don't need another Twitter. Or another Medium</title><link>https://stop.zona-m.net/2017/04/no-you-dont-need-another-twitter-or-medium/</link><description>Last year, we had the &amp;ldquo;buy Twitter&amp;rdquo; campaign. Now, the arrival of Mastodon, the last &amp;ldquo;Twitter replacement&amp;rdquo;, has caused a lot of renewed talks about what we&amp;rsquo;d need to replace this or that digital platform. I argue that many of these proposals, wishes and plans may be misplaced, or looking in the wrong directions.
Two good examples of what I mean are in this post about Mastodon, and in this thread on mastodon.</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 08 Apr 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/no-you-dont-need-another-twitter-or-medium/</guid></item><item><title>On Mastodon flaws, and decentralized services</title><link>https://stop.zona-m.net/2017/04/on-mastodon-flaws-and-decentralized-services/</link><description>Mastodon is the latest &amp;ldquo;Twitter replacement&amp;rdquo;. Yesterday I said on Twitter that something described as its &amp;ldquo;bigger flaw&amp;rdquo; seems no big deal to me. Here I explain why.
  I had never heard of Mastodon until 2 days ago, when I wrote that yes, even Nazis can use it. Yesterday I found this comment on BoingBoing to a more complete article by Sean Bonner. The Boingboing comment ends with this quote:</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 07 Apr 2017 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/on-mastodon-flaws-and-decentralized-services/</guid></item><item><title>Playing with the HTTP send/response cycle in Ruby, without Faraday ("HTTP Yeah You Know Me" project)</title><link>https://josh.works/playing-with-http-send-response</link><description>&lt;p&gt;As part of the &lt;a href="http://backend.turing.io/module1/projects/http_yeah_you_know_me"&gt;HTTP Server&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;First, I’m working through &lt;a href="http://practicingruby.com/articles/implementing-an-http-file-server"&gt;Practicing Ruby’s “Implementing an HTTP File Server”&lt;/a&gt; for general practice and understanding.&lt;/p&gt;

&lt;p&gt;I’m going to use &lt;a href="https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en"&gt;Postman&lt;/a&gt; to capture traffic and try to replicate some of the things the guides reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lastly, I just found Jeff Casamir’s walkthrough of almost everything I’ve discovered in the last week. Save yourself the time, and go read &lt;a href="https://github.com/turingschool/curriculum/blob/master/source/projects/http_yeah_you_know_me-addendum.markdown"&gt;it here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id="finding-get-requestsresponses-in-the-wild"&gt;Finding GET requests/responses in the wild&lt;/h2&gt;

&lt;p&gt;First, I need to configure postman to show request/response headers, like what the guides indicate:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;# HTTP Request
GET /file.txt HTTP/1.1
User-Agent: ExampleBrowser/1.0
Host: example.com
Accept: */*

# HTTP Response
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 13
Connection: close

hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Turns out Postman cannot do this caputuring by default.&lt;/p&gt;

&lt;p&gt;So, follow &lt;a href="http://stackoverflow.com/questions/33793629/postman-how-to-see-request-with-headers-and-body-data-with-variables-substitut"&gt;these instructions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets first look at some get requests in the wild:&lt;/p&gt;

&lt;p&gt;Using Postman, I made a get request for &lt;code class="language-plaintext highlighter-rouge"&gt;turing.io&lt;/code&gt;. I get back lots of HTML, etc. But I want to see the headers. The “Headers” tab in the Postman request isn’t really helpful.&lt;/p&gt;

&lt;p&gt;&lt;img alt="What does all this mean? Doesn't seem to correspond at all to the guides I'm working through" src="https://d3vv6lp55qjaqc.cloudfront.net/items/1p0H3m1L0o3O231x0L2V/Postman.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;So, we’ll look at “network traffic” per the following:&lt;/p&gt;

&lt;p&gt;right click inside postman &amp;gt; “inspect” &amp;gt; Network tab &amp;gt; “clear” the screen, if anything is in it, &amp;gt; switch back to postman, re-send the GET request &amp;gt; switch back to “inspect window”.&lt;/p&gt;

&lt;p&gt;Looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="this looks much better" src="https://d3vv6lp55qjaqc.cloudfront.net/items/0J1a3G1d0T2E1B120H0O/Screen%20Recording%202017-02-11%20at%2008.24%20AM.gif" /&gt;&lt;/p&gt;

&lt;p&gt;OK, cool. This stuff looks promising: 
&lt;img alt="a hah!" src="https://d3vv6lp55qjaqc.cloudfront.net/items/3d0E0O3s0D2H3w400N3d/Developer_Tools_-_chrome-extension___fhbjgbiflinjbdggehcddcbncdddomop_html_requester_html.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Everything I highlighted corresponds to items mentioned in the instructions. This is approaching “interesting”, and I feel like there might be an insight around the corner.&lt;/p&gt;

&lt;h2 id="setting-up-my-own-requests-in-ruby-seeing-headers-in-postman"&gt;Setting up my own requests in Ruby, seeing headers in Postman&lt;/h2&gt;

&lt;p&gt;So, I can find the headers for any GET request I might make in the wild, so now I’m going to try to do the same setup with my own little ruby server, per &lt;a href="http://practicingruby.com/articles/implementing-an-http-file-server"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m following the author’s instructions to:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To begin, let’s build the simplest thing that could possibly work: a web server that always responds “Hello World” with HTTP 200 to any request&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m writing everything in the http_yeah_you_know_me directory. I’ll delete it before pushing a final project version to Github.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2345&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;Turns out TCPServer is a &lt;a href="http://ruby-doc.org/stdlib-2.4.0/libdoc/socket/rdoc/TCPServer.html"&gt;Ruby class&lt;/a&gt;, just like an enumerable or array or hash or Fixnum or NilClass, etc. Cool.&lt;/p&gt;

&lt;p&gt;It’s got some methods that I won’t worry about right now.&lt;/p&gt;

&lt;p&gt;Moving on:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
  &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;

  &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

  &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello World!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"HTTP/1.1 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
               &lt;span class="s2"&gt;"Content-Type: text/plain&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; 
               &lt;span class="s2"&gt;"Content-Length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bytesize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; 
               &lt;span class="s2"&gt;"Connection: close&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The loop seems interesting. I tested the simple_server.rb file before writing this, and it seemed that the socket closed as soon as a single request was made. (I.E. I’d start the “server”, and as soon as I interacted with it in any way, it would do something and close. So I wonder if this loop will keep the server open.&lt;/p&gt;

&lt;p&gt;Please read through the commented version of what I’m writing above. It’s a good explenation, but I’ve noticed something interesting. We’re printing a HTTP Response. See the &lt;code class="language-plaintext highlighter-rouge"&gt;HTTP/1.1 200OK&lt;/code&gt; in the first line? Does that look familiar?&lt;/p&gt;

&lt;p&gt;&lt;img alt="looks like we're writing some of this header" src="https://cl.ly/3k3U291S0A3O/Developer_Tools_-_chrome-extension___fhbjgbiflinjbdggehcddcbncdddomop_html_requester_html.jpg" /&gt;&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;  &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
  &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That first line is, according to the comments, the required new-line to tell the server (or something) that the header is over and the body content is coming. The response references a previously defined variable of &lt;code class="language-plaintext highlighter-rouge"&gt;response = "Hello World!\n"&lt;/code&gt;, so we’re printing &lt;code class="language-plaintext highlighter-rouge"&gt;hello world&lt;/code&gt; as the content.&lt;/p&gt;

&lt;p&gt;Lets try to fire this thing up. Save file, run as a program from the command line, and visit &lt;code class="language-plaintext highlighter-rouge"&gt;http://localhost:2345/anything&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Looks like it worked:&lt;/p&gt;

&lt;p&gt;&lt;img alt="printed to the browser" src="https://cl.ly/1s2Y2X053e3y/localhost_2345_anything.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;But it’s not very exciting. Lets get back into Postman and try to dig deeper:&lt;/p&gt;

&lt;p&gt;Now we’re getting more. I can see every parameter passed through to the server, &lt;em&gt;and it is staying open&lt;/em&gt;! (Put a flag in that. The “simple server” we made for HTTP_yeah_you_know_me can be kept open with a loop. Cool.&lt;/p&gt;

&lt;p&gt;&lt;img alt="postman gif" src="https://cl.ly/291k1e3Q0740/Screen%20Recording%202017-02-11%20at%2008.51%20AM.gif" /&gt;&lt;/p&gt;

&lt;p&gt;And, as the author mentioned in the tutorial, this seems to be working:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# Log the request to the console for debugging&lt;/span&gt;
  &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt="STDERR printed to screen. I bet this is useful for later" src="https://cl.ly/1c3d1V1Q0i2Q/1____turing_module1_projects_http_yeah_you_know_me_experiments__ruby_.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;And, as recommended, open up another window and run &lt;code class="language-plaintext highlighter-rouge"&gt;curl --verbose -XGET http://localhost:2345/anything_you_want_to_put_here&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I like to understand shell commands when I run them, so if you look at the MAN pages for &lt;code class="language-plaintext highlighter-rouge"&gt;curl&lt;/code&gt;, you can find what each of those flags means.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;curl --verbose&lt;/code&gt; means “curl talks a lot”, and more importantly, lines beginning with &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;gt;&lt;/code&gt; is &lt;em&gt;header data sent by curl&lt;/em&gt;, and lines beginning with &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;&lt;/code&gt; is &lt;em&gt;header data received by curl&lt;/em&gt;. Lines beginning with &lt;code class="language-plaintext highlighter-rouge"&gt;*&lt;/code&gt; is additional info added by CURL.&lt;/p&gt;

&lt;p&gt;I suspect this will be important.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;-XGET&lt;/code&gt; is a flag that, according to the MAN page, “specifies custom request method”. the &lt;code class="language-plaintext highlighter-rouge"&gt;-X&lt;/code&gt; lives by itself, and whatever follows is what it makes as the request method, so &lt;code class="language-plaintext highlighter-rouge"&gt;-XGET&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;-XPOST&lt;/code&gt;, and &lt;code class="language-plaintext highlighter-rouge"&gt;-XDELETE&lt;/code&gt; are all probably valid uses of the flag.&lt;/p&gt;

&lt;p&gt;Here’s the output for &lt;code class="language-plaintext highlighter-rouge"&gt;curl --verbose -XGET htpp://localhost:23454/whatever_blah_blah_blah&lt;/code&gt;&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="o"&gt;[&lt;/span&gt;experiments &lt;span class="o"&gt;(&lt;/span&gt;setup&lt;span class="o"&gt;)]&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;-XGET&lt;/span&gt; http://localhost:2345/whatever_blah_blah_blah
Note: Unnecessary use of &lt;span class="nt"&gt;-X&lt;/span&gt; or &lt;span class="nt"&gt;--request&lt;/span&gt;, GET is already inferred.
&lt;span class="k"&gt;*&lt;/span&gt;   Trying ::1...
&lt;span class="k"&gt;*&lt;/span&gt; TCP_NODELAY &lt;span class="nb"&gt;set&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;::1&lt;span class="o"&gt;)&lt;/span&gt; port 2345 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET /whatever_blah_blah_blah HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: localhost:2345
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.52.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Content-Type: text/plain
&amp;lt; Content-Length: 13
&amp;lt; Connection: close
&amp;lt;
Hello World!
&lt;span class="k"&gt;*&lt;/span&gt; Curl_http_done: called premature &lt;span class="o"&gt;==&lt;/span&gt; 0
&lt;span class="k"&gt;*&lt;/span&gt; Closing connection 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Cool. We’ve got data sent by curl (prepended with &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;gt;&lt;/code&gt;), data received (prepended with &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;&lt;/code&gt;), what is actually passed through (the one line without any characters at the beginning) and of course, additional data returned by CURL. (begins with &lt;code class="language-plaintext highlighter-rouge"&gt;*&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Phew. Learning some stuff, eh? I still don’t know what most of this means, but it’s building out a mental model. So, keep experimenting. You’re typing all these commands yourself, right? no copy-pasta from here. That’ll keep you from learning as much.&lt;/p&gt;

&lt;h2 id="congrats"&gt;Congrats!&lt;/h2&gt;

&lt;p&gt;This is the end of the first section of the post, building a simple server. Now, moving along, gonna build a more complex one.&lt;/p&gt;

&lt;p&gt;This is where I look over my notes, take a walk, and get some coffee. This is a lot of work, so let it sink in and consolidate.&lt;/p&gt;

&lt;h1 id="serving-files-over-http"&gt;Serving files over HTTP&lt;/h1&gt;

&lt;p&gt;I’m now working through the second half of &lt;a href="http://practicingruby.com/articles/implementing-an-http-file-server"&gt;this tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;He says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For each incoming request, we’ll parse the &lt;code class="language-plaintext highlighter-rouge"&gt;Request-URI&lt;/code&gt; header and translate it into a path to a file within the server’s public folder.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What’s the request URI? How’s it different from a URL? I’m not sure, but I can infer some things. Mostly, looking at some of the results of poking around in different pages in Postman, and looking at the results, I think we can figure this out. (Googling around for “URI vs URL didn’t help a lot)&lt;/p&gt;

&lt;p&gt;We know that the first line of a HTTP Request looks like this: &lt;code class="language-plaintext highlighter-rouge"&gt;GET / HTTP/1.1&lt;/code&gt;. This is three things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;GET is the method.&lt;/li&gt;
  &lt;li&gt;/ is the “path”&lt;/li&gt;
  &lt;li&gt;HTTP/1.1 is the protocal (or possibly called the “scheme”).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, if I go to the root of a website (like www.turing.io) the header will be: &lt;code class="language-plaintext highlighter-rouge"&gt;GET / HTTP/1.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If I go to a specific page (or &lt;em&gt;resource&lt;/em&gt;) I’ll go to www.turing.io/our-team. What do you think the GET request would look like then? Here’s my guess:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;GET /our-team HTTP/1.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets fire it up in POSTMAN and see:&lt;/p&gt;

&lt;p&gt;&lt;img alt="looks promising" src="https://cl.ly/2s3P2z1e0J40/Developer_Tools_-_chrome-extension___fhbjgbiflinjbdggehcddcbncdddomop_html_requester_html.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Cool. So the path is just &lt;code class="language-plaintext highlighter-rouge"&gt;website.com/&amp;lt;the_path&amp;gt;&lt;/code&gt;. Or, to tie it into ruby-speak, when we &lt;code class="language-plaintext highlighter-rouge"&gt;require&lt;/code&gt; another file, we define its from the root directory. Similar idea with the URI.&lt;/p&gt;

&lt;p&gt;Onward.&lt;/p&gt;

&lt;p&gt;First bit of code in the second file. (I’d start a new file from scratch, and type every line…)&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'uri'&lt;/span&gt;

&lt;span class="no"&gt;WEB_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'./public'&lt;/span&gt;

&lt;span class="no"&gt;CONTENT_TYPE_MAPPING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s1"&gt;'html'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text/html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'txt'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'png'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'image/png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'jpg'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'image/jpeg'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="no"&gt;DEFAULT_CONTENT_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'application/octet-stream'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Makes sense, except I have no idea what an &lt;code class="language-plaintext highlighter-rouge"&gt;octet-stream&lt;/code&gt; is. Don’t really care, though. This just is mapping input values to something that our HTTP server can understand, I believe.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
  &lt;span class="no"&gt;CONTENT_TYPE_MAPPING&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DEFAULT_CONTENT_TYPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ve seen &lt;code class="language-plaintext highlighter-rouge"&gt;File.extname&lt;/code&gt; before, when doing FileIO stuff. So this is taking the file extension, splitting it from the file name, and trying to match it to the hash we just wrote. If it matches, it’ll pull and do something with the matching value. I.E. &lt;code class="language-plaintext highlighter-rouge"&gt;jpg&lt;/code&gt; =&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;image/jpeg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Onward, a bunch of other stuff that is explained in the commented out portions of the tutorial, and I barely understand it, so skipping them.&lt;/p&gt;

&lt;p&gt;We see this again:&lt;/p&gt;

&lt;p&gt;(You typed it out by hand, right?)&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
  &lt;span class="n"&gt;request_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;

  &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;request_line&lt;/span&gt;

  &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requested_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request_line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exist?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;directory?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"HTTP/1.1 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                  &lt;span class="s2"&gt;"Content-Type: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                  &lt;span class="s2"&gt;"Content-Length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                  &lt;span class="s2"&gt;"Connection: close&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

      &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

      &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"File not found&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"HTTP/1.1 404 Not Found&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s2"&gt;"Content-Type: text/plain&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s2"&gt;"Content-Length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s2"&gt;"Connection: close&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I was curious about all the &lt;code class="language-plaintext highlighter-rouge"&gt;\r\n&lt;/code&gt; characters. It’s obviously something to do with a line break.&lt;/p&gt;

&lt;p&gt;On &lt;a href="http://stackoverflow.com/questions/4415654/which-line-break-in-php-mail-header-r-n-or-n"&gt;stack overflow&lt;/a&gt;, I found this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The CRLF &lt;code class="language-plaintext highlighter-rouge"&gt;\r\n&lt;/code&gt;, should be used according to the php documentation. Also, to conform to the RFC 2822 spec lines must be delimited by the carriage return character, CR &lt;code class="language-plaintext highlighter-rouge"&gt;\r&lt;/code&gt; immediately followed by the line feed, LF &lt;code class="language-plaintext highlighter-rouge"&gt;\n&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Seems like it’s a &lt;em&gt;Carriage Return Line Feed&lt;/em&gt; symbol, native to PHP, that inserts a really “hard” line break. That makes since, since earlier in the guide, the author mentioned that HTTP request/responses are very sensitive to line breaks and white spaces. So, I’m flagging this as “important” for later use.&lt;/p&gt;

&lt;p&gt;And, keep following the instructions. I got it to serve up an /index.html page by default, and downloaded a few other files that I “stored” in a public directory in the same place as the server-generation script.&lt;/p&gt;

&lt;p&gt;So, I feel like I’ve got my head a little more wrapped around server stuff in Ruby. Writing it out helps me a bit, maybe will be helpful to others, too.&lt;/p&gt;

&lt;h1 id="play-around-with-building-your-own-http-response---live"&gt;Play around with building your own HTTP Response - LIVE!&lt;/h1&gt;

&lt;p&gt;I’m keeping notes for myself and my own understanding - I’m not good at teaching that which I barely can wrap my head around, so… I apologize for the upcoming disconnectedness or holes in reasoning.&lt;/p&gt;

&lt;p&gt;I’ve really, realy wanted to get a tool up and running that lets me talk, as a server, to something that’s expecting a given response. This is so I can get one level of abstraction lower to understand these HTTP requests/responses.&lt;/p&gt;

&lt;p&gt;I just figured out how to do it.&lt;/p&gt;

&lt;p&gt;We’ll use two tools, both already existing in your terminal:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;nc (Stands for “Net Cat”)&lt;/li&gt;
  &lt;li&gt;CURL (stands for C-URL? “see URL”?)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I strongly recommend downloading and installing &lt;a href="https://github.com/tldr-pages/tldr"&gt;tldr&lt;/a&gt;, as it will let you more quickly explore terminal commands. We’ll be using “flags” for both the above utilities. (a flag makes a program do something other than it’s default. Like &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt; vs &lt;code class="language-plaintext highlighter-rouge"&gt;ls -l&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;You’ll need two terminal windows side by side, like this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="side by side" src="https://cl.ly/0Y0K180V0Q3q/1____turing_module1_projects_http_yeah_you_know_me__nc_.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;On the left is netcat, on the right is CURL.&lt;/p&gt;

&lt;p&gt;I started the &lt;code class="language-plaintext highlighter-rouge"&gt;nc&lt;/code&gt; command on the left with &lt;code class="language-plaintext highlighter-rouge"&gt;nc -l 9090&lt;/code&gt;. If you’re reading this, please, please install the &lt;code class="language-plaintext highlighter-rouge"&gt;tldr&lt;/code&gt; tool and run (in your terminal) &lt;code class="language-plaintext highlighter-rouge"&gt;tldr nc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, look up what &lt;code class="language-plaintext highlighter-rouge"&gt;-l&lt;/code&gt; does.&lt;/p&gt;

&lt;p&gt;On the right, I’ve got CURL, running as &lt;code class="language-plaintext highlighter-rouge"&gt;curl -v localhost:9090&lt;/code&gt;. Look it up in TLDR, tell me what -v does. (Hint, i’ve outlines it above.)&lt;/p&gt;

&lt;p&gt;Here’s using them in tandem: 
&lt;img alt="gif of terminal utilities" src="https://cl.ly/1D3x2W1G3K3n/Screen%20Recording%202017-02-14%20at%2012.57%20PM.gif" /&gt;&lt;/p&gt;

&lt;p&gt;You can write, line by line, your own valid header. You’ll notice it ends whenever you add a new-line character, and when you DO try to send actual content, if you get the “content-length” figure wrong, it’ll cut you off.&lt;/p&gt;

&lt;p&gt;example:&lt;/p&gt;

&lt;p&gt;&lt;img alt="gif of building a header and getting cut off" src="https://cl.ly/44011q3R0r0E/Screen%20Recording%202017-02-14%20at%2012.59%20PM.gif" /&gt;&lt;/p&gt;

&lt;h1 id="i-want-to-talk-to-my-ruby-program-now"&gt;I want to talk to my ruby program now&lt;/h1&gt;

&lt;p&gt;I feel lik I can use Netcat to impersonate a client (or server? still not sure) and talk to my ruby program (which is operating as a server…) So… lets do that.&lt;/p&gt;

&lt;p&gt;Here’s the ruby I’m running:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'pry'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HTTP&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:server&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9090&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"server's up, capiTAN"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;receive_request_send_response&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
      &lt;span class="n"&gt;whole_response&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="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
        &lt;span class="n"&gt;whole_response&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;whole_response&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;holy what the fuck&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"&lt;/span&gt;
    
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive_request_send_response&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;When I run the ruby program, it just hangs. Which means it’s stuck in &lt;code class="language-plaintext highlighter-rouge"&gt;while client = server.accept&lt;/code&gt;. When I run &lt;code class="language-plaintext highlighter-rouge"&gt;curl -v localhost:9090&lt;/code&gt; it too just sits and waits. Everyone is waiting for a response, but not even a header is sent, else &lt;code class="language-plaintext highlighter-rouge"&gt;curl&lt;/code&gt; would have shown&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&amp;gt; header data
&amp;gt; sent by 
&amp;gt; curl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, CURL doesn’t have anything to send to. I wonder why.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;nc&lt;/code&gt; has an option. Checking out &lt;code class="language-plaintext highlighter-rouge"&gt;tldr nc&lt;/code&gt; the first option says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Connect to a certain port (you can then write to this port):
  nc ip_address port&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good enough for me.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;nc localhost 9090&lt;/code&gt; doesn’t do anything in either the ruby program or NC.&lt;/p&gt;

&lt;p&gt;Lets try submitting a well-formatted HTTP request, and see what happens&lt;/p&gt;

&lt;p&gt;I tried typing in exactly what CURL had sent last time:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&amp;gt; GET / HTTP/1.1
&amp;gt; Host: localhost:9090
&amp;gt; User-Agent: curl/7.52.1
&amp;gt; Accept: */*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and got nothing. but that’s OK, cuz my program (right now) isn’t showing me the captured HTTP request. Lets modify it to do that.&lt;/p&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;p&gt;still trying to get this to work. Rolling back to a “known good” state w/my ruby program that captures server data.&lt;/p&gt;

&lt;p&gt;Oh, worth noting:&lt;/p&gt;

&lt;p&gt;if you see something that has this:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;GET / HTTP/1.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What is it? A request or a response?&lt;/p&gt;

&lt;p&gt;How about this:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;HTTP/1.1 200 OK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first one is a &lt;em&gt;request&lt;/em&gt;, the latter a &lt;em&gt;response&lt;/em&gt;. I’m starting to not confuse them.&lt;/p&gt;

&lt;p&gt;Boom, did it. First, I rolled back to the “server” we wrote as part of the tutorial I linked above.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;

&lt;span class="n"&gt;tcp_server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tcp_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"ready for a request"&lt;/span&gt;

&lt;span class="n"&gt;request_lines&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="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
  &lt;span class="n"&gt;request_lines&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"I (the server) just got this request:"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;request_lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;


&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"I (the server) am sending response."&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;pre&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request_lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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;lt;/pre&amp;gt;"&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"http/1.1 200 ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"date: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%a, %e %b %Y %H:%M:%S %z'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"server: ruby"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"content-type: text/html; charset=iso-8859-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Wrote this response:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Response complete, exiting."&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I started that, and then in a different tab ran &lt;code class="language-plaintext highlighter-rouge"&gt;nc localhost 9292&lt;/code&gt; (please note I’m mixing up some port numbers here, so don’t just copy/paste and expect any of this to work.)&lt;/p&gt;

&lt;p&gt;&lt;img alt="it's working!" src="https://cl.ly/252a113I3B2A/1____turing_module1_projects_http_yeah_you_know_me_lib__bash_.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;So, now the server will capture correctly-formatted HTTP requests and print them. Now lets build our own HTTP request in Netcat&lt;/p&gt;

&lt;p&gt;Aww, yeah. Got it working. Check it out:&lt;/p&gt;

&lt;p&gt;&lt;img alt="built my own fake HTTP request" src="https://cl.ly/171O3E1b3b3u/1____turing_module1_projects_http_yeah_you_know_me_lib__bash_.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I’m slowly (very slowly) building a mental map of what’s going on behind the scenes, but this feels like a good realization.&lt;/p&gt;

&lt;h1 id="back-to-the-class-project-and-iteration-0"&gt;Back to the class project and iteration 0&lt;/h1&gt;

&lt;p&gt;So we now know exactly what this is doing:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
  &lt;span class="n"&gt;request_lines&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It’s taking in header data from the client making the HTTP &lt;em&gt;request&lt;/em&gt;, and ONLY header data. As soon as it gets a blank line (which is the universal sign for “end of header data”) it stops adding new lines to the header data.&lt;/p&gt;

&lt;p&gt;I’m restarting at Iteration 0, but this time putting everything in a class and methods. I’m not testing yet, that’ll come later.&lt;/p&gt;

&lt;p&gt;I’ve also not touched Faraday. ¯_(ツ)_/¯&lt;/p&gt;

&lt;p&gt;OK, got Iteration working, inside of a class:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'pry'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HTTP&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:server&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:client_response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:counter&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9090&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@client_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="vi"&gt;@counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# note to myself in terminal when this gets hit.&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"server's up, capiTAN"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_message&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
        &lt;span class="n"&gt;client_response&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="c1"&gt;# assign a big block of text to a string with %{text}. New lines get \n auto-added&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%{&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;
          #{client_response.join("\n")}
          this server has been (re)started #{counter} times
          &amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;\n}&lt;/span&gt;

        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s2"&gt;"HTTP/1.1 200 OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"date = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%Y-%B-%d, %l:%M %P"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"server: ruby"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"content-type: text/html; charset=UTF-8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
      &lt;span class="vi"&gt;@counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;my_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I can hit it in Postman or with CURL, and everything is expected. It’s ugly, but damnit, it works.&lt;/p&gt;

&lt;h1 id="iteration-1"&gt;Iteration 1&lt;/h1&gt;

&lt;p&gt;I’m thinking I just need to add the HTML &amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt; tags to pretty-format the returned text.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'pry'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HTTP&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:server&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:client_response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:counter&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9090&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@client_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="vi"&gt;@counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# note to myself in terminal when this gets hit.&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"server's up, capiTAN"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_message&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
        &lt;span class="n"&gt;client_response&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="c1"&gt;# assign a big block of text to a string with %{text}. New lines get \n auto-added&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%{&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;
          &amp;lt;pre&amp;gt;#{client_response.join("\n")}&amp;lt;/pre&amp;gt;
          this server has been (re)started #{counter} times
          &amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;\n}&lt;/span&gt;

        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s2"&gt;"HTTP/1.1 200 OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"date = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%Y-%B-%d, %l:%M %P"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"server: ruby"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"content-type: text/html; charset=UTF-8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
      &lt;span class="vi"&gt;@counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;my_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;When I do this, my @client_response array gets longer… and longer… and longer. because everytime I reload the server I re-add new diagnostic info to it. So, lemme fix that.&lt;/p&gt;

&lt;p&gt;Now, I’m having trouble getting the server to recognize the end of the header and the content.&lt;/p&gt;

&lt;p&gt;The problem is with my new-line characters in my header response, I believe.&lt;/p&gt;

&lt;p&gt;Editing my &lt;code class="language-plaintext highlighter-rouge"&gt;headers&lt;/code&gt; to:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;  &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HTTP/1.1 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"date = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%Y-%B-%d, %l:%M %P"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"server: ruby&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"content-type: text/html; charset=UTF-8"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s2"&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;and we’re almost back in action. Here’s the CURL output:&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="o"&gt;[&lt;/span&gt;http_yeah_you_know_me &lt;span class="o"&gt;(&lt;/span&gt;setup&lt;span class="o"&gt;)]&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; localhost:9090
&lt;span class="k"&gt;*&lt;/span&gt; Rebuilt URL to: localhost:9090/
&lt;span class="k"&gt;*&lt;/span&gt;   Trying ::1...
&lt;span class="k"&gt;*&lt;/span&gt; TCP_NODELAY &lt;span class="nb"&gt;set&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; Connection failed
&lt;span class="k"&gt;*&lt;/span&gt; connect to ::1 port 9090 failed: Connection refused
&lt;span class="k"&gt;*&lt;/span&gt;   Trying 127.0.0.1...
&lt;span class="k"&gt;*&lt;/span&gt; TCP_NODELAY &lt;span class="nb"&gt;set&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 9090 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: localhost:9090
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.52.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt; HTTP/1.1 200 OK
&amp;lt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 2017-February-14,  5:22 pm
&amp;lt; server: ruby
&amp;lt; content-type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UTF-8content-length: 215
&lt;span class="k"&gt;*&lt;/span&gt; no chunk, no close, no size. Assume close to signal end
&amp;lt;

          &amp;lt;html&amp;gt;&amp;lt;&lt;span class="nb"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;
          &amp;lt;pre&amp;gt;GET / HTTP/1.1
Host: localhost:9090
User-Agent: curl/7.52.1
Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;&amp;lt;/pre&amp;gt;
          this server has been &lt;span class="o"&gt;(&lt;/span&gt;re&lt;span class="o"&gt;)&lt;/span&gt;started 0 &lt;span class="nb"&gt;times&lt;/span&gt;
          &amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;



&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It thinks the content ended before the last line. (see how &lt;code class="language-plaintext highlighter-rouge"&gt;content-length: 215&lt;/code&gt; is directly following &lt;code class="language-plaintext highlighter-rouge"&gt;content-type&lt;/code&gt;? lets add an &lt;code class="language-plaintext highlighter-rouge"&gt;\r\n&lt;/code&gt; to the end of that line in my Header output.&lt;/p&gt;

&lt;p&gt;updated &lt;code class="language-plaintext highlighter-rouge"&gt;headers&lt;/code&gt; to:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;  &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HTTP/1.1 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"date = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%Y-%B-%d, %l:%M %P"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"server: ruby&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"content-type: text/html; charset=UTF-8&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&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;and it works! Iteration 1 done.&lt;/p&gt;

&lt;h1 id="iteration-2-supporting-paths"&gt;Iteration 2: supporting paths&lt;/h1&gt;

&lt;p&gt;well eff, my existing code is so horrible path support is a major PITA.&lt;/p&gt;

&lt;p&gt;Part of the problem is I cannot easily calculate my output length, so building my response, I cannot tell the server (easily) how many characters to expect.&lt;/p&gt;

&lt;p&gt;Time for some refactoring, I guess.&lt;/p&gt;

&lt;p&gt;I’m going to try to clean up my http response block. Here’s what I’ve got:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;helloworld_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"hello world, this has been reloaded &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; times."&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="vi"&gt;@counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

      &lt;span class="n"&gt;default_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;client_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"this server has been (re)started &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; times&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HTTP/1.1 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"date = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%Y-%B-%d, %l:%M %P"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"server: ruby&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"content-type: text/html; charset=UTF-8&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;helloworld_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"connection: close"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;notice I’ve hard-coded “helloworld_path”. That’s because trying to add path support revealed this little problem to me.&lt;/p&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;It’s a PITA, but… a few hours of work after ^^, I sorted it out. There’s a few pieces in play:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Pulling data from the GET request (like path)&lt;/li&gt;
  &lt;li&gt;building the FRAME if the server response. Hardcode some pieces, use variables for the stuff that changes&lt;/li&gt;
  &lt;li&gt;Build variables that hold the variable parts of the response. (seems obvious, right? That’s why I wanna smash through my desk with my head.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’ll add comments to the following code. This mostly handles iteration 2:&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_message&lt;/span&gt;

    &lt;span class="c1"&gt;# client_response holds all the received data, like `GET / HTTP/1.1`. The / is of particular interest.&lt;/span&gt;
    &lt;span class="n"&gt;client_response&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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
        &lt;span class="n"&gt;client_response&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="c1"&gt;# ^^ end of building the client response&lt;/span&gt;
      
      &lt;span class="c1"&gt;# pulling out the path, be it /, or /hello, or /datetime, etc.&lt;/span&gt;
      &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_response&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="nf"&gt;split&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="c1"&gt;# building variables to insert into my HTTP response block later&lt;/span&gt;
      
      &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%Y %B %d, %H:%M %z"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      
      &lt;span class="c1"&gt;# possible responses based on path&lt;/span&gt;
      &lt;span class="n"&gt;hello_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello world, this has been reloaded &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; times."&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;default_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;This is my default path&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;datetime_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;pre&amp;gt;The time is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/pre&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;shutdown_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Total requests: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Exiting..."&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;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;default_path&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"/hello"&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hello_path&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"/datetime"&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime_path&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"/shutdown"&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shutdown_path&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="c1"&gt;# building the server response. It'll always get wrapped the the following HTML. the `join` method fixes the fact that the parameters are currently wrapped in brackets. example: hello_path = ["some string here"])&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"&lt;/span&gt;

      &lt;span class="c1"&gt;# this is the fixed part of the server response. Every response will be the same, except the date changes to be Time.now, and output.length MUST be accurate, or the server will either not print the full request, or it'll hang after all the data is received, because it's expecting more.&lt;/span&gt;
      &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"http/1.1 200 ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"date: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"server: ruby"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"content-type: text/html; charset=iso-8859-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"content-length: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# incrementing my counter&lt;/span&gt;
      &lt;span class="vi"&gt;@counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      
      &lt;span class="c1"&gt;# client.puts is the _sending_ actual response to the server. Headers is distinct from the output. &lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
       
      &lt;span class="c1"&gt;# this stuff is sorta ugly random shit to reset the values so when I reload the page, it'll accept different paths. I am 100% sure this is not best practice.&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;

      &lt;span class="c1"&gt;# I couldn't get my shutdown method to sit neatly in one if statement. ¯\_(ツ)_/¯ &lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"/shutdown"&lt;/span&gt;
      &lt;span class="c1"&gt;# resetting values for next connection&lt;/span&gt;
      &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="n"&gt;client_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;


  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;my_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="iteration-3-supporting-params"&gt;Iteration 3: supporting params&lt;/h2&gt;

&lt;p&gt;Given a sample paramter like&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;http://host:port/path?param=value&amp;amp;param2=value2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;how can we pull the parameters? That will be the first step to doing something with them. I don’t care how I store them for now.&lt;/p&gt;

&lt;p&gt;I think I can pull everything following the &lt;code class="language-plaintext highlighter-rouge"&gt;?&lt;/code&gt; using a REGEX match or split or something.&lt;/p&gt;

&lt;p&gt;lets play around in pry with the string.&lt;/p&gt;

&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://host:port/path?param=value&amp;amp;param2=value"&lt;/span&gt;

&lt;span class="c1"&gt;# eff, so confused. &lt;/span&gt;

&lt;span class="c1"&gt;# ok, I used this:&lt;/span&gt;

&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_response&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="nf"&gt;split&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;word_search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;here’s the output from pry:&lt;/p&gt;
&lt;div class="language-ruby highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;
&lt;span class="n"&gt;path&lt;/span&gt;                 &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="s2"&gt;"/word_search?word=house"&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt;             &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;shutdown_path&lt;/span&gt;        &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;time&lt;/span&gt;                 &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;word_search&lt;/span&gt;          &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="s2"&gt;"house"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description><author>Josh Thompson</author><pubDate>Fri, 07 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/playing-with-http-send-response</guid></item><item><title>Mastodon – a lightweight twitter that can weight a lot</title><link>https://yasha.solutions/mastodon-a-lightweight-that-can-weight-a-lot/</link><description>So, the news broke.
It’s all over the Internet.
Mastodonis the new cool kid on the block.
It came out on my radars a few months ago on ProductHunt, but now it’s “officially” a serious project :
At least most of the major media outlets like for instance :
Mashable: Bye, Twitter. All the cool kids are migrating to Mastodon.Mic: What is Mastodon? Everything to know about new social network**Yahoo: **Mastodon, the new alternative to Twitter**The Verge: **Mastodon.</description><author>Yasha Solutions</author><pubDate>Fri, 07 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/mastodon-a-lightweight-that-can-weight-a-lot/</guid></item><item><title>Dimension 404: Season 1</title><link>https://olshansky.info/tv/dimension_404_season_1/</link><description>Olshansky's review of Dimension 404: Season 1</description><author>🦉 olshansky 🦁</author><pubDate>Thu, 06 Apr 2017 16:26:56 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/dimension_404_season_1/</guid></item><item><title>Writing Good Tests for NodeJS APIs</title><link>https://lucasfcosta.com/blog/Testing-NodeJS-APIs/</link><description>Hello, everyone! Recently I've been working a lot with Node and I felt the urgent need to write a blog post about how to write good API tests. In those tests, all I do is send a request to an insta...</description><author>Lucas F. Costa - Blog</author><pubDate>Thu, 06 Apr 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Testing-NodeJS-APIs/</guid></item><item><title>Scatterplot matrices with gnuplot</title><link>https://bastian.rieck.me/blog/2017/scatterplot_matrices_gnuplot/</link><description>&lt;p&gt;&lt;a href="http://junkcharts.typepad.com/junk_charts/2010/06/the-scatterplot-matrix-a-great-tool.html"&gt;Scatterplot
matrices&lt;/a&gt;
are one of the most practical direct visualization of unstructured data
sets—provided that the dimensionality does not become too large.
Despite their prominence in the visualization community, there are few
non-commercial tools out there that are able to &lt;em&gt;produce&lt;/em&gt; scatterplot
matrices for publication-ready visualizations.&lt;/p&gt;
&lt;p&gt;In this post, I want to briefly explain how to use a recent version of
&lt;a href="http://gnuplot.info"&gt;gnuplot&lt;/a&gt;, one of my favourite plotting tools, to create
something that resembles a scatterplot matrix. In this example, I will
use &lt;a href="https://en.wikipedia.org/wiki/Iris_flower_data_set"&gt;&amp;ldquo;the famous &lt;em&gt;Iris&lt;/em&gt; data set&amp;rdquo;&lt;/a&gt;, which I am sure everyone is familiar with by now.&lt;/p&gt;
&lt;p&gt;I prepared a &lt;a href="https://bastian.rieck.me/blog/data/iris.txt"&gt;slightly-modified version of the data set&lt;/a&gt;, which makes
processing it with &lt;code&gt;gnuplot&lt;/code&gt; easier. To this end, I shortened the labels
and inserted newlines after each block of identical labels. This makes
using colours much easier.&lt;/p&gt;
&lt;p&gt;The basic idea of the plot is to use the &lt;code&gt;multiplot&lt;/code&gt; mode of &lt;code&gt;gnuplot&lt;/code&gt;
and create all plots in a nested loop. The diagonal elements are filled
with histogram of the corresponding attribute—which is of course
also created using &lt;code&gt;gnuplot&lt;/code&gt;. The only thing I am not proud of is the
use of labels. I am using the &lt;code&gt;x2label&lt;/code&gt; feature in order to put axis
labels on top of a plot, but as &lt;code&gt;gnuplot&lt;/code&gt; does not (yet) support
a simpler mechanism for placing labels in multiple plots, I had to
resort to a truly horrid way of getting this to work…&lt;/p&gt;
&lt;p&gt;Without further ado, here’s the code:&lt;/p&gt;

&lt;p&gt;And this is how the output looks like:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/scatterplot_matrix_iris.svg"&gt;&lt;img alt="Scatterplot matrix of the Iris data set" src="https://bastian.rieck.me/images/scatterplot_matrix_iris.svg" width="600" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;You can find the code for this script &lt;a href="https://gist.github.com/Pseudomanifold/79b5969e7e510084ce1431efe161cd7a"&gt;as a gist on
GitHub&lt;/a&gt;.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Wed, 05 Apr 2017 22:41:41 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/scatterplot_matrices_gnuplot/</guid></item><item><title>by the sound, near the sea-wall</title><link>https://mbutler.org/by-the-sound-near-the-sea-wall/</link><description>matthew_butler · by the sound, near the sea-wall Inspired by Stephen Pollington&amp;#8217;s translation of an Exeter Book riddle in Runes: Literacy in the Germanic Iron Age, this sound piece uses dadaists poem fragments to imagine a fictional Immanuel Kant discovering what it might mean to know the ultimate Reality. I was by the sound, near [&amp;#8230;]</description><author>mbutler</author><pubDate>Wed, 05 Apr 2017 16:55:24 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/by-the-sound-near-the-sea-wall/</guid></item><item><title>Mastodon, or: Can Nazi use Free as in Freedom Software?</title><link>https://stop.zona-m.net/2017/04/mastodon-or-can-nazi-use-free-as-in-freedom-software/</link><description>Short answer: yes, they can. Regardless of what some websites are saying.
Mastodon is &amp;ldquo;an alternative to Twitter&amp;rdquo;. Mashable just wrote that:
 &amp;ldquo;Mastodon.. in many ways it&amp;rsquo;s like Twitter, but it is also so not like Twitter&amp;hellip; What makes it stand out? It has better privacy controls than Twitter. Also, neo-Nazis are explicitly banned.&amp;rdquo; and then, 2 lines below: &amp;ldquo;Mastodon is a type of free and open source software (FOSS) known as &amp;ldquo;GNU social.</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 05 Apr 2017 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/04/mastodon-or-can-nazi-use-free-as-in-freedom-software/</guid></item><item><title>Ubuntu 16.04 LTS Xen stuck on "Loading Initial Ramdisk"</title><link>https://thomashunter.name/posts/2017-04-05-ubuntu-16-04-lts-xen-stuck-on-loading-initial-ramdisk</link><author>Thomas Hunter II</author><pubDate>Wed, 05 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-04-05-ubuntu-16-04-lts-xen-stuck-on-loading-initial-ramdisk</guid></item><item><title>How to Win Friends &amp;amp; Influence People</title><link>https://olshansky.info/book/how_to_win_friends_influence_people/</link><description>Olshansky's review of How to Win Friends &amp;amp; Influence People by Dale Carnegie</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 05 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/how_to_win_friends_influence_people/</guid></item><item><title>The cloud is dead — long live the cloud!</title><link>https://yasha.solutions/the-cloud-is-dead-long-live-the-cloud/</link><description>Edit: looking back at this post from a few years back, it does look incredibly naive but still leaving this up - still a a few good links
Back in the (not-so-distant) days, if you wanted to have some online software — to manage your invoices or your customers — or any kind of business management solution — you had to have your own servers for your company and install-and-configure the hell out of it.</description><author>Yasha Solutions</author><pubDate>Wed, 05 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/the-cloud-is-dead-long-live-the-cloud/</guid></item><item><title>Why should you give a damn about the internet</title><link>https://yasha.solutions/why-should-you-give-a-damn-about-the-internet/</link><description>When I talk to people about the Internet – the first reaction is always : “Yes! Today you have no choice”.
Then when I dig a little deeper – you hear the real stories.
The “Yes… but…”
– not in our industry
– people are not buying online really
– the market is not ready
– it is still early
So first, who is connected?
Look, in case you haven’t noticed but everyone is.</description><author>Yasha Solutions</author><pubDate>Wed, 05 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/why-should-you-give-a-damn-about-the-internet/</guid></item><item><title>From ROS prototype to production on Ubuntu Core [1/5]</title><link>https://kyrofa.com/posts/from-ros-prototype-to-production-on-ubuntu-core-1-5/</link><description>UPDATE: I&amp;rsquo;m leaving this series up for historical purposes, but please note that I no longer recommend Ubuntu Core or snaps for use in robotics.
My background is pretty heavily littered with robotics. A natural side effect of this is that I&amp;rsquo;ve published numerous posts discussing snaps, Ubuntu Core, and different robotics frameworks (ROS and MOOS specifically). But my robotics experience was professional, which meant I didn&amp;rsquo;t really have a reason (or money, these things can be expensive) to buy any robotic systems personally.</description><author>kyrofa's blog</author><pubDate>Wed, 05 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/from-ros-prototype-to-production-on-ubuntu-core-1-5/</guid></item><item><title>Probabilistic Policy Violation Detection with IPFWD</title><link>https://www.anardil.net/2017/probabilistic-policy-violation-detection-with-ipfwd.html</link><description>&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;When using a firewall system like IPFW to detect
threats, the system can end up doing a lot of packet processing.
This can negatively impact performance-sensitive systems such as
storage nodes in data centers. This paper describes a practical
solution to this problem using a load-weighted probabilistic
mechanism that …&lt;/p&gt;</description><author>Anardil</author><pubDate>Tue, 04 Apr 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2017/probabilistic-policy-violation-detection-with-ipfwd.html</guid></item><item><title>Social Network Mining YouTube Videos</title><link>https://www.anardil.net/2017/social-network-mining-youtube-videos.html</link><description>&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;YouTube videos are categorized into a number of
classes such as music, entertainment, sports. This paper
will explore how these categories are related, how strongly they
are related, and the techniques used to gain this information.
Data mining, graph analysis, and visualization techniques will be
leveraged to accomplish this …&lt;/p&gt;</description><author>Anardil</author><pubDate>Tue, 04 Apr 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2017/social-network-mining-youtube-videos.html</guid></item><item><title>South Park: Season 20</title><link>https://olshansky.info/tv/south_park_season_20/</link><description>Olshansky's review of South Park: Season 20</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 04 Apr 2017 02:02:52 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/south_park_season_20/</guid></item><item><title>Log4net rolling file appender with multiple projects</title><link>https://www.skouf.com/posts/log-4-net-rolling-file-appender/</link><description>&lt;p&gt;The purpose of this article is to document a minor frustration I ran into at work a few weeks ago, in the hopes that somebody else with the same issue will stumble across it.
If I can save another poor soul some time, then it will be well worth writing this.&lt;/p&gt;</description><author>skouf.com</author><pubDate>Mon, 03 Apr 2017 15:12:23 GMT</pubDate><guid isPermaLink="true">https://www.skouf.com/posts/log-4-net-rolling-file-appender/</guid></item><item><title>50 shades of Cray</title><link>https://jasoneckert.github.io/myblog/50-shades-of-cray/</link><description>&lt;p&gt;&lt;img alt="CRAY" src="cray.png#center" title="CRAY" /&gt;&lt;/p&gt;
&lt;p&gt;If you wanted a fast computer back in 1976, you bought the 5.5 ton, $9 million Cray-1 made by Cray Research.  The Cray-1 was dubbed the first supercomputer as it was designed to be much faster than other (more massive) computers of the time.&lt;/p&gt;
&lt;p&gt;It was incredibly successful in the large computing space and Cray subsequently released a much faster model called the Cray X-MP in 1983 (shown in the picture at the top of this post).  By today’s standards, the Cray X-MP was nothing special (it was only half as powerful as an original Xbox from 2001). but for the 1980s, it was incredibly powerful!  The graphics in the movie “The Last Starfighter” were created on a Cray X-MP.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Mon, 03 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/50-shades-of-cray/</guid></item><item><title>Hal</title><link>https://www.anardil.net/2017/hal.html</link><description>&lt;p&gt;An in depth look into Hal, a Minecraft AI&lt;/p&gt;</description><author>Anardil</author><pubDate>Sun, 02 Apr 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2017/hal.html</guid></item><item><title>Book Review (2016)</title><link>https://captnemo.in/blog/2017/04/02/book-review-2016/</link><description>&lt;p&gt;I tweeted this a while back about my reading progress in 2016, and thought I’d do a post about what I read.&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Made a graph of my &lt;a href="https://twitter.com/goodreads"&gt;@goodreads&lt;/a&gt; reading progress in 2016. I only picked up the pace sometime in May, but managed to read ~10k pages this year.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://pbs.twimg.com/media/C2D9p9DXEAADajk.png" /&gt;&lt;/p&gt;
&amp;mdash; Nemo (@captn3m0) &lt;a href="https://twitter.com/captn3m0/status/819934060256563201"&gt;January 13, 2017&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;Continuing with the &lt;a href="/blog/2016/02/15/2015-in-review/"&gt;review tradition from last year&lt;/a&gt;, here are the top 3 books that I read in 2016:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/26892110-the-library-at-mount-char"&gt;The Library at Mount Char&lt;/a&gt; [&lt;a href="https://www.goodreads.com/review/show/1648561385?book_show_action=false&amp;amp;from_review_page=1"&gt;review&lt;/a&gt;]&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25667918-binti"&gt;Binti&lt;/a&gt; (Hugo winner for Best Novella, SF)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/7604.Lolita"&gt;Lolita&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other books that I enjoyed were “Bands of Mourning”, the 3rd book in Mistborn Era 2, and the Powder Mage Trilogy which I found hard to put down.&lt;/p&gt;

&lt;p&gt;I decided to aim for 36 books in 2016 (as well as 2017 now), and crossed that nicely. I picked 36 because it corresponds to 3 books a month or 1 book every 10 days, which makes for a goal that is easily tracked. I count everything that goodreads might count as a book (which is both good and bad), but I stick to it. Far more important for me would be the page count, which I charted at the end of the year and I read ~830 pages a month, which I’m pretty happy with.&lt;/p&gt;

&lt;p&gt;I’m hoping to read more technical books in 2017, and have made some progress on that front with re-reading &lt;a href="https://sarabander.github.io/sicp/"&gt;SICP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are interested in the script that generated the graph, you can find it on &lt;a href="https://github.com/captn3m0/what-to-read/blob/master/stats.rb"&gt;github&lt;/a&gt;.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sun, 02 Apr 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/04/02/book-review-2016/</guid></item><item><title>Python Last Month</title><link>https://peterlyons.com/problog/2017/04/python-last-month/</link><description>&lt;p&gt;I needed to compute timestamps representing the start and end of "last month" so I could build a URL needed to generate an invoicing report. Because the URL uses actual dates, I can't just bookmark it since it changes every month. Python has a lot of date and time management capabilities, but finding the one that is going to get the job done correctly and succinctly is actually harder than the code itself.&lt;/p&gt;
&lt;p&gt;With that in mind, here's essentially a 3-liner that does it&lt;/p&gt;
&lt;pre class="language-python "&gt;&lt;code class="language-python"&gt;import time
import datetime

now = time.localtime()

# Get the last day of last month by taking the first day of this month
# and subtracting 1 day.
last = datetime.date(now.tm_year, now.tm_mon, 1) - datetime.timedelta(1)

# Set the day to 1 gives us the start of last month
first = last.replace(day=1)

# The default string representation of these datetime instances is 
# YYYY-mm-dd format (which is what I usually need),
# so we can just print them out
print first, last
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's what I see running it on the command line.&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;python &amp;#x2f;tmp&amp;#x2f;range.py
2017-03-01 2017-03-31
&lt;/code&gt;&lt;/pre&gt;</description><author>Pete's Points</author><pubDate>Sat, 01 Apr 2017 20:09:16 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/04/python-last-month/</guid></item><item><title>Indieweb Test</title><link>https://mxuribe.com/posts/indieweb-test/</link><description>&lt;p&gt;A test of Indieweb-related functionality&lt;/p&gt;</description><author>Mauricio Uribe | m.x.uribe</author><pubDate>Fri, 31 Mar 2017 07:00:00 GMT</pubDate><guid isPermaLink="true">https://mxuribe.com/posts/indieweb-test/</guid></item><item><title>Why is this GoLang solution faster than the equivalent Java Solution?</title><link>https://boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/</link><description>&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;At work there is a tradition of a Friday quiz being posted by the winner of the previous week. I missed out on the most recent one due to having to duck off early to do my tax but the problem was rather an interesting one.&lt;/p&gt;
&lt;p&gt;The challange itself is not as simple as you would initally think and taken from a 2015 IBM Ponder This &lt;a href="https://www.research.ibm.com/haifa/ponderthis/challenges/May2015.html"&gt;https://www.research.ibm.com/haifa/ponderthis/challenges/May2015.html&lt;/a&gt;&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 31 Mar 2017 01:52:01 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/</guid></item><item><title>Automatically Promoting Constructor Parameters to Fields</title><link>https://blog.varunramesh.net/posts/constructor-argument-promotion/</link><description>When writing object-oriented code, you frequently want a constructor that takes in values and assigns them to object fields. Some languages reduce the repetition required for this.</description><author>Varun Ramesh's Blog</author><pubDate>Thu, 30 Mar 2017 23:26:00 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/constructor-argument-promotion/</guid></item><item><title>Thirteen Years of Bad Game Code</title><link>https://etodd.io/2017/03/29/thirteen-years-of-bad-game-code/</link><description>&lt;p&gt;
Alone on a Friday night, in need of some inspiration, you decide to relive some of your past programming conquests.
&lt;/p&gt;
&lt;p&gt;
The old archive hard drive slowly spins up, and the source code of the glory days scrolls by...
&lt;/p&gt;
&lt;p&gt;
Oh no. This is not at all what you expected. Were things really this bad? Why did no one tell you?
Why were you like this? &lt;em&gt;Is it even possible to have that many gotos in a single function?&lt;/em&gt;
You quickly close the project. For a brief second, you consider deleting it and scrubbing the hard drive.
&lt;/p&gt;</description><author>Evan Todd</author><pubDate>Wed, 29 Mar 2017 16:00:00 GMT</pubDate><guid isPermaLink="true">https://etodd.io/2017/03/29/thirteen-years-of-bad-game-code/</guid></item><item><title>Runaway Robot - A Mobile Runner Game</title><link>https://blog.varunramesh.net/posts/runaway-robot-a-mobile-runner-game/</link><description>I made a mobile runner game for the CS194 class at Stanford.</description><author>Varun Ramesh's Blog</author><pubDate>Wed, 29 Mar 2017 13:11:00 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/runaway-robot-a-mobile-runner-game/</guid></item><item><title>IETF98: OpenConfig Observations</title><link>https://rob.sh/post/ietf98/</link><description>&lt;p&gt;Anees Shaikh and I put together some thoughts that we shared with &lt;code&gt;rtgwg&lt;/code&gt; at
IETF 98 in Chicago. The slides are linked below.&lt;/p&gt;
&lt;div width="100%"&gt;
	&lt;center&gt;
		&lt;a href="https://cdn.rob.sh/files/slides-98-rtgwg-openconfig-modeling-and-observations-00.pdf"&gt;
			&lt;img src="https://cdn.rob.sh/img/ietf98.png" style="width: 60%;" /&gt;
		&lt;/a&gt;
	&lt;/center&gt;
&lt;/div&gt;</description><author>rob.sh</author><pubDate>Wed, 29 Mar 2017 11:00:00 GMT</pubDate><guid isPermaLink="true">https://rob.sh/post/ietf98/</guid></item><item><title>Honeymoon in Maldives</title><link>https://snevsky.com/blog/maldives</link><description>Photos and notes from our honeymoon on Hadahaa Island in the Maldives: cyan water, white sand, and a small paradise we promised to revisit.</description><author>Serge Nevsky</author><pubDate>Wed, 29 Mar 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://snevsky.com/blog/maldives</guid></item><item><title>Pulling a Page's Modified Date from Git</title><link>https://blog.varunramesh.net/posts/pulling-modified-date-from-git/</link><description>When creating a static site, you can pull a page's modified date directly from git.</description><author>Varun Ramesh's Blog</author><pubDate>Wed, 29 Mar 2017 02:29:00 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/pulling-modified-date-from-git/</guid></item><item><title>Transforming Gaia</title><link>https://peterlyons.com/problog/2017/03/transforming-gaia/</link><description>&lt;p&gt;I interviewed Robert Jordan, who is Director of Engineering at &lt;a href="https://www.gaia.com"&gt;Gaia&lt;/a&gt;, where in 2016 they completed a major update to their subscription video service.&lt;/p&gt;
&lt;div class="youtube-video-container"&gt;

&lt;/div&gt;</description><author>Pete's Points</author><pubDate>Mon, 27 Mar 2017 18:43:01 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/03/transforming-gaia/</guid></item><item><title>All the absurdity of modern copyright, in ONE removal</title><link>https://stop.zona-m.net/2017/03/all-the-absurdity-of-modern-copyright-in-one-removal/</link><description>Today&amp;rsquo;s copyright law is ridiculous and offensive, to say the least, and this week it&amp;rsquo;s Mr Roger&amp;rsquo;s Neighborhood&amp;quot; turn to prove it.
Andrea James writes on Boing Boing that
"Over the weekend, two episodes of Mister Roger's Neighborhood "Conflict" series unexpectedly appeared on YouTube after being unavailable for three decades. YouTube quickly removed them, but to many, the timing felt related to Trump's plans to defund PBS." The full story is here, but I&amp;rsquo;m not mentioning it it because it may &amp;ldquo;be a message to Trump&amp;rdquo;.</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 27 Mar 2017 17:10:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/03/all-the-absurdity-of-modern-copyright-in-one-removal/</guid></item><item><title>Things that never happened before happen all the time</title><link>https://ho.dges.online/words/commonplace/things-that-never-happened-before-happen-all-the-time/</link><description>&lt;p&gt;Scott Sagan&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Things that never happened before happen all the time*.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>ho.dges.online</author><pubDate>Mon, 27 Mar 2017 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/things-that-never-happened-before-happen-all-the-time/</guid></item><item><title>Watch Strap</title><link>https://june.kim/watch-strap/</link><author>june.kim</author><pubDate>Sun, 26 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/watch-strap/</guid></item><item><title>Links - March 26, 2017</title><link>https://faingezicht.com/links/2017/03/26/links/</link><description/><author>Avy Faingezicht</author><pubDate>Sun, 26 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/03/26/links/</guid></item><item><title>Vulnerability Report: ACT Corp</title><link>https://captnemo.in/blog/2017/03/26/act-vulnerability/</link><description>&lt;p&gt;ACT, for those who don’t know is one of India’s most popular broadband providers.&lt;/p&gt;

&lt;p&gt;This is a very brief and concise summary.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ACT has a mobile application&lt;/li&gt;
  &lt;li&gt;That allows you to login and check your plan details, data usage etc&lt;/li&gt;
  &lt;li&gt;I’ve been wanting to build a command line application that lets me check the balance easily&lt;/li&gt;
  &lt;li&gt;I tried scripting their website, but it was too much javascript.&lt;/li&gt;
  &lt;li&gt;The mobile app uses an API to do the same&lt;/li&gt;
  &lt;li&gt;The API happens to have really bad auth&lt;/li&gt;
  &lt;li&gt;Got fixed almost 3 months after reporting this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;/p&gt;

&lt;div class="language-sh highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;curl https://myfibernet.actcorp.in/api/user/plandetails &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authtoken: 2aee21dfb1ef77707c30f48ccc513ad60b74d1fc6a84d60ecc32323ab5941469"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Apiversion: 1.0"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Appversion: 32"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Devicetype: 1"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Deviceid: 68590327e3e0ca81"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Mobilenumber: 9999999999"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Mid: 8973808103928d98703e65c0106b7a9d4001886234afbc2d7ce6415b75f9c216"&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"username":"11111111"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The API responds back with the following:&lt;/p&gt;

&lt;div class="language-json highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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="nl"&gt;"plan_details"&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="nl"&gt;"agreement_info"&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="nl"&gt;"agreement_no"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XXXXXXXXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"promotion_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"package_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACTESS01M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"package_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"agreement_startdate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DD/MM/YYYY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"expiry_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"entity_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subscription_period"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"payterm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"billingcycle_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"contract_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"outlets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"service_points"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"package_tenure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"due_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="nl"&gt;"product_info"&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="nl"&gt;"product_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"product_desc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="nl"&gt;"plan_usage_info"&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="nl"&gt;"service_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACTESS01M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"service_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACTESS01M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"outbyteslimit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;322122547200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"outbytesremaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;153400581140&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"outbytesused"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;168721966060&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="nl"&gt;"bill_info"&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="nl"&gt;"accountno"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"111111112233"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subscribername"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NAME"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"phonenumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PHONENUMBER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"address"&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="nl"&gt;"line1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YUP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"line2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"THESE TWO LINES WERE FILLED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"line3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"district"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AND THIS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BANGALORE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KARNATAKA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"India"&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="nl"&gt;"billno"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10000001111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"billdate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DD/MM/2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"account_period"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"01/MM/2016-30/MM/2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"previous_due"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"current_invoice_amt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"total_due"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"bill_due_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"15 Nov 2016"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Some of these are empty fields, and some values that I didn’t understand I’ve replaced with &lt;code class="language-plaintext highlighter-rouge"&gt;[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fun part is that the request is actually a POST and contains the following data:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;{"username":"11111111"}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I happen to have friends who also use ACT. I &lt;a href="https://twitter.com/captn3m0/status/803579876502405120"&gt;asked around for usernames&lt;/a&gt;, and just by changing this one parameter in the request, I could access the complete details of almost everyone else.&lt;/p&gt;

&lt;p&gt;Almost everyone, because for certain cases, I get a valid empty response. Valid because it has the same schema, but empty because all values are empty strings. Don’t know what that happens consistently only for certain accounts. (One of these was a Hyd account, the other in BLR).&lt;/p&gt;

&lt;p&gt;If you are interested I’m working on a simple API that lets you access the ACT API to check the same details. It would ask you for an OTP the first time you login, and then cache the credentials to let you check the balance easily.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;I’ve reported this to ACT as soon as I found it. Will disclose after I’ve given them some time!&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: This was reported and fixed by ACT after I managed to find a contact via an investor (really!).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Date&lt;/th&gt;
      &lt;th&gt;Details&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;29 Nov 2016&lt;/td&gt;
      &lt;td&gt;Vulnerability Identified&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;29 Nov 2016&lt;/td&gt;
      &lt;td&gt;Email sent to ACT, no response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6 Dec 2016&lt;/td&gt;
      &lt;td&gt;Email sent with partial customer details to explain scope of the issue, no response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8 Dec 2016&lt;/td&gt;
      &lt;td&gt;Reminder sent, no response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;20 Jan 2017&lt;/td&gt;
      &lt;td&gt;Another reminder with a writeup sent. I also set a deadline of 29th January (2 months since first contact). Also got in touch with CERT-IN. &lt;em&gt;No response&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;23 Jan 2017&lt;/td&gt;
      &lt;td&gt;Accidentally an investor in ACT saw my tweet and responded over twitter. Send a writeup, along with the suggestion to take down the application&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;24 Jan 2017&lt;/td&gt;
      &lt;td&gt;ACT reports issue is fixed. I test and report back as fixed the next day&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;26 Mar 2017&lt;/td&gt;
      &lt;td&gt;Report published&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;However, the huge timeline involved here pretty much guarantees that if you are an ACT customer,
your data is out there in the public.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sun, 26 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/03/26/act-vulnerability/</guid></item><item><title>How I Manage Passwords with KeePass</title><link>https://www.mikekasberg.com/blog/2017/03/25/how-i-manage-passwords-with-keepass.html</link><description>&lt;p&gt;Several weeks ago, I wrote a &lt;a href="https://www.mikekasberg.com/blog/2017/03/10/dealing-with-passwords.html"&gt;blog
post&lt;/a&gt;
about how horrible it is to have to deal with the various password restrictions
websites use. Of course, that post was influenced by Jeff Atwood’s post,
&lt;a href="https://blog.codinghorror.com/password-rules-are-bullshit/"&gt;Password Rules are
Bullshit&lt;/a&gt;. While
writing the post, I did some research on what makes a good password. And after
writing it, I spent several weeks thinking about my own password management
strategies.&lt;/p&gt;

&lt;div class="warning"&gt;
&lt;p&gt;&lt;b&gt;July 2020 Update&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I wrote this blog post back in 2017, and a little bit has changed since then!
I used to manage my passwords with KeePass, but more recently I've been using &lt;a href="https://bitwarden.com"&gt;Bitwarden&lt;/a&gt;. My reasoning for using a password
manager (described below) is largely unchanged &amp;ndash; I simply like Bitwarden
better than KeePassXC now. You can read my comparison between Bitwarden and
KeePassXC &lt;a href="https://www.mikekasberg.com/blog/2018/11/20/keepass-vs-bitwarden.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Really, the password problem boils down to this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The longer a password is, the more secure it is. Ideally 16 characters or
longer.&lt;/li&gt;
  &lt;li&gt;Don’t use the same password on different websites.&lt;/li&gt;
  &lt;li&gt;A password must conform to the rules of the website it’s used for
(length limits, character requirements, etc).&lt;/li&gt;
  &lt;li&gt;Oh, and humans can’t remember 20 different passwords that change every 6
months.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a world where I have accounts to dozens of different websites that I’m
actively using, a password manager really is the only good solution (other than
Sign In with Google) anyone’s come up with so far. Although I’ve spent years
avoiding any kind of password manager (putting all your passwords in one place
just seems like a bad idea (it is a single point of failure, after all)), I
think I’m finally giving in. &lt;em&gt;Sigh&lt;/em&gt;. (Really though, if you do it right, the
benefits outweigh the risks.) After researching the different password manager
options available, I settled on &lt;a href="https://keepass.info/"&gt;KeePass&lt;/a&gt; because:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s open-source.&lt;/li&gt;
  &lt;li&gt;It doesn’t rely on browser extensions (which appear to be &lt;a href="https://twitter.com/taviso/status/843965519371812864"&gt;relatively
vulnerable&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;It works on pretty much anything (I need something that supports both Linux
and Android).&lt;/li&gt;
  &lt;li&gt;It can sync via Dropbox.&lt;/li&gt;
  &lt;li&gt;It can generate pseudo-random passwords.&lt;/li&gt;
  &lt;li&gt;It stores passwords in an encrypted file, in an open format, that I own &amp;amp; control.&lt;/li&gt;
  &lt;li&gt;It’s free.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I put some thought into getting everything set up nicely, and tried out a couple
different applications. KeePass is open source, and there are several different
options for post platforms listed on its &lt;a href="https://keepass.info/download.html"&gt;download
page&lt;/a&gt;. Here’s what I’m using:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://keepassxc.org/"&gt;KeePassXC&lt;/a&gt; has a much nicer interface on Linux than
the original KeePass (and reads/writes the same file format).&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=keepass2android.keepass2android&amp;amp;hl=en"&gt;Keepass2Android&lt;/a&gt;
has a really rich feature set (including fingerprint unlock) and syncs to
Dropbox.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.dropbox.com/"&gt;Dropbox&lt;/a&gt; to sync.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get started, I installed KeePassXC on my computer and created a new password
database file in my Dropbox folder. I’m adding passwords to it (and changing
them to new, pseudo-random passwords) as I visit the websites I use. After a
couple weeks of this, most of my passwords will be in KeePass!&lt;/p&gt;

&lt;p&gt;That one website that requires your password to be 12-14 characters with at
least one letter and one number but no symbols? Handled. Somebody got hacked?
OK, just generate a new password. Nothing new to remember. Password strength? 24
characters of pseudo-random letters and symbols, where websites allow it. New
password every 6 months? Not a big deal. I think this is going to work well.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sat, 25 Mar 2017 18:05:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/03/25/how-i-manage-passwords-with-keepass.html</guid></item><item><title>Image Recognition Services Benchmark: Amazon, Clarifai, Google and Microsoft</title><link>https://thedarkside.frantzmiccoli.com/experimentations/2017/03/25/image-recognition-benchmark-amazon-clarifai-google-microsoft.html</link><description>&lt;p&gt;tl;dr this article presents an arbitrary evaluation of the different commonly
available image recognitions services. The key takeaway of this would
be to use Clarifai, if you look for best labeling, and
Microsoft if false positives are something you would like to avoid as much as
you can. Google or then Amazon are representing a good trade-off.
You can jump to the first result graph presented sums up the global performance
of each service.&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Baby, this is 2017! If you are not using deep learning to guess your next
commit message you are probably not as artificial intelligence as you should
be.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I am pretty much trying to avoid the buzzword fudge usually served every time
you write software that is supposed to be smart in some sense. Nevertheless last
december I was assisting a project where, suddenly, using image recognition was
making sense.&lt;/p&gt;

&lt;p&gt;Basically we were crawling content from different websites and one of the
key problems to make this scale properly was to get a better classification.
The challenge was to take content from different websites and sort it into
our own categories tree. The provided data about an item was:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Url&lt;/li&gt;
  &lt;li&gt;Name&lt;/li&gt;
  &lt;li&gt;Description&lt;/li&gt;
  &lt;li&gt;Pictures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For some, the description was not enough, even for a human to classify
correctly. Though most pictures were usually unambiguous and pretty easy to
identify for the human eye, a proper image recognition would simplify this
classification problem to a simple remapping from the labels detected to the
categories we hope. A much simpler problem as it could be easily solved with a
satisfying precision by a human made decision tree.&lt;/p&gt;

&lt;p&gt;We ended up using Amazon Rekognition for this specific need, as all of our
infrastructure was already running inside AWS. This was the most easy to
integrate and as time and keeping system complexity low were two important
constraints, I mostly explored other options to know what possible enhancement
is at hand.&lt;/p&gt;

&lt;h3 id="protocol"&gt;Protocol&lt;/h3&gt;

&lt;p&gt;Usually services provide labels with a confidence, anything below 0.5 has been
discarded and not considered.&lt;/p&gt;

&lt;p&gt;When doing label detection there are two things that you are two different
objectives:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Getting the most precise labels for every elements of a picture, eventually
labels could explore a semantic hierarchy, for example, a “dress” is a piece of
“clothing”. This is close to counting true positives in a basic classification
case.&lt;/li&gt;
  &lt;li&gt;Avoiding wrong labels, what I called noise. This is close to counting
false positives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The analogy to true positives and false positives reaches its limit when you
consider that an element could be counted in both set, you have right labels
among erroneous ones.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Anneliese Phillips" src="/res/unsplash-anneliesephillips-fieldforestmountainpeople.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://unsplash.com/photos/uv4-vl3liKM"&gt;the above picture&lt;/a&gt;,
could be labeled correctly: “field”, “people”,
“moutain”, “pine tree” and “sky” ; and also incorrectly “cow” and “painting”.&lt;/p&gt;

&lt;p&gt;On both dimensions I have arbitrarily scored the result from the tested service:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;0: means worst outcome, missing labels or a lot of noise&lt;/li&gt;
  &lt;li&gt;5: means best outcome, right labels or very good signal noise ratio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is fair to not consider minor differences as meaningful as per the subjective
process of evaluation of the output provided by the different services.&lt;/p&gt;

&lt;p&gt;Please note that those tests has been ran in late December 2016, except for
Clarifai that I considered only in March 2017, services may have evolved since
then, even though I did not notice changes while I played again with the first
ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/frantzmiccoli/image-recognition-benchmark-data"&gt;The datasets, the scoring and the graph generation is available on Github&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id="services"&gt;Services&lt;/h3&gt;

&lt;p&gt;I have tested the services of the three leaders in the industry of the cloud
services: Amazon, Google and Microsoft, and one startup a friend recommended
after reviewing a first version of this article: Clarifai.&lt;/p&gt;

&lt;h4 id="amazon-rekognition"&gt;Amazon Rekognition&lt;/h4&gt;

&lt;p&gt;Amazon Web Services is a defacto standard for many startups, their image
recognition service is called
&lt;a href="https://aws.amazon.com/rekognition/"&gt;Rekognition&lt;/a&gt;. It integrates like another
AWS service, which means quite easily if you are able to get through the
quite convoluted and abstruse documentation. Rekognition is part of the AWS Free
Tier, so you can get started and play with it for free.&lt;/p&gt;

&lt;p&gt;It can work directly from an S3 file identifier which might come handy if your
data is already inside S3.&lt;/p&gt;

&lt;p&gt;The biggest drawback for Rekognition is that you need an AWS account to be able
to experiment with it and make some quick tests. It is not very outsider
friendly, though if you have an AWS account a web interface lets you upload some
image and get a result.&lt;/p&gt;

&lt;p&gt;Google and Microsoft let you see how their product work on your data without
the need to be a registered user.&lt;/p&gt;

&lt;h4 id="clarifai"&gt;Clarifai&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://clarifai.com/"&gt;Clarifai&lt;/a&gt; is dedicated to image recognition … and they
seem to do it well. Aside what others do, they tend to extract high level
concepts from pictures which could seriously ease content exploration.&lt;/p&gt;

&lt;p&gt;For example an image with a good looking landscape would be labeled “travel”,
one with a nice Desktop view “business” and a nicely dressed woman as “fashion”.
They usually give back much more labels than the other services, but their
recognition ability is the most impressive.&lt;/p&gt;

&lt;h4 id="google-cloud-vision-api"&gt;Google Cloud Vision API&lt;/h4&gt;

&lt;p&gt;Google offers perhaps the most elaborate service for image recognition with its
&lt;a href="https://cloud.google.com/vision/"&gt;Cloud Vision API&lt;/a&gt;, all services are offering
to detect faces and facial expression but Google brings it to the next step.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Anneliese Phillips through Cloud Vision" src="/res/google-cloud-vision-landmark.png" /&gt;&lt;/p&gt;

&lt;p&gt;I have discovered this awesome landmark recognition feature out of the blue, as
it worked only for one of the dozen landscape pictures I tested. Google seems
to be able to recognize where a picture has been taken. I think that Street View
data offers an unchallenged data source to match a landscape picture to some
precise geographical position.&lt;/p&gt;

&lt;p&gt;The file containing no coordinates in its exif metadata, we still have to
consider that Google may also have leveraged some data it has discovered while
indexing this very picture from Unsplash. But this would be cheating and I
consider it unlikely.&lt;/p&gt;

&lt;h4 id="microsoft-computer-vision-api"&gt;Microsoft Computer Vision API&lt;/h4&gt;

&lt;p&gt;Microsoft is the cloud reference for those working around the .NET stack, they
have tried to develop things under a different approach than the two others, for
example, their &lt;a href="https://azure.microsoft.com/en-us/services/machine-learning/"&gt;Machine Learning&lt;/a&gt;
tool is more a web enabled modern competitor to what SAS offers through its
outdated Entreprise Miner, than to what Amazon offers through an API.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.microsoft.com/cognitive-services/en-us/computer-vision-api"&gt;Computer Vision API&lt;/a&gt;
is not extremely different from Amazon’s with the exception that you can easily
play with it online and that the test interface is more pleasant to use.&lt;/p&gt;

&lt;h3 id="global-performance"&gt;Global performance&lt;/h3&gt;

&lt;p&gt;&lt;img alt="global recognition benchmark" src="/res/benchmark-global.png" /&gt;&lt;/p&gt;

&lt;p&gt;Basically we can see a Pareto curve where you can make your tradeoff between:
precision and noise. Even though on many sets the Clarifai solution seems to
just be dominating the others.&lt;/p&gt;

&lt;h3 id="datasets"&gt;Datasets&lt;/h3&gt;

&lt;p&gt;Every dataset is composed of twenty images. For every dataset though I have
tried to discard some images in order to provide more diversity with what I was
testing.&lt;/p&gt;

&lt;h4 id="amateur"&gt;Amateur&lt;/h4&gt;

&lt;p&gt;This dataset has been composed with the most random things that you can find
online, even though I have been avoiding the ones loaded with text.
Some has been found on &lt;a href="http://imgur.com/"&gt;Imgur&lt;/a&gt;, some others on a
website proposing explicitly to open random images from the internet. Some of
the images in this dataset are pretty normal, others are representing a
challenge precisely because of the humor or creativity that compose their key
message.&lt;/p&gt;

&lt;p&gt;An example of an easy one:&lt;/p&gt;

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

&lt;p&gt;Some examples of hard ones, &lt;strong&gt;where the point of art or humour is the
ambiguity&lt;/strong&gt;:&lt;/p&gt;

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

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

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

&lt;p&gt;This gives the following result:&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/res/benchmark-amateur.png" /&gt;&lt;/p&gt;

&lt;p&gt;Clarifiai offers a different trade-off than the others and is quite impressive
at analysis the content.&lt;/p&gt;

&lt;p&gt;The three other services are offering similar performance, being in general only
able to partially label the input.&lt;/p&gt;

&lt;h4 id="creative"&gt;Creative&lt;/h4&gt;

&lt;p&gt;The creative dataset is the most diverse in term of medium, its content comes
from &lt;a href="https://www.instagram.com/"&gt;instagram&lt;/a&gt; (mine mostly),
&lt;a href="http://www.fubiz.net/"&gt;Fubiz&lt;/a&gt;, a leading creative media, and,
&lt;a href="https://dribbble.com/"&gt;Dribbble&lt;/a&gt; and &lt;a href="http://www.deviantart.com/"&gt;DeviantArt&lt;/a&gt;,
communities where creative can showcase their work. Pictures from weird angles,
drawing or artistic compositions.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Can Sunlight" src="/res/instagram-frantzmiccoli-cansunlight.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Hulk urinatory" src="/res/fubiz-smartphonepictures-hulkurinatory.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Bird book layout" src="/res/dribbble-vladyslavtaran-booklayoutbird.png" /&gt;&lt;/p&gt;

&lt;p&gt;Definitely this dataset stretches the services to their limit, the ranking is
clear for the three cloud services, Google then Amazon then Microsoft but none
manage to achieve a correct labeling. As per the previous dataset Clarifai
provides another trade-off.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/res/benchmark-creative.png" /&gt;&lt;/p&gt;

&lt;h4 id="photography"&gt;Photography&lt;/h4&gt;

&lt;p&gt;The photography dataset is perhaps the one fitting the most the user content
upload use case. This one is perhaps lacking faces and portraits and still
contains some kind of creative material. All pictures comes from
&lt;a href="https://unsplash.com/"&gt;unsplash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Field" src="/res/unsplash-anneliesephillips-fieldforestmountainpeople.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Mountain" src="/res/unsplash-caitlinwynne-mountainssnowlake.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="Library and books" src="/res/unsplash-dmitrijpaskevic-libraryoldbooksscalestaircase.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Clarifia here dominates with no ambiguity the other services,
Google and Amazon exhibit a similar behavior, Microsoft though is here the best
choice to avoid noisy results in a compromise for correct labeling. This API has
made the choice to rather give no answers rather than a possibly bad answer.&lt;/p&gt;

&lt;p&gt;&lt;img alt="photography" src="/res/benchmark-photography.png" /&gt;&lt;/p&gt;

&lt;h4 id="products"&gt;Products&lt;/h4&gt;

&lt;p&gt;The products dataset is only composed with content from
a promotion listing website. The products are supposedly the
simplest thing to recognize, a single object on a white background.&lt;/p&gt;

&lt;p&gt;&lt;img alt="bike" src="/res/malinshopper-bike.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;On this dataset Amazon, Clarifai and Google provides extremely good performance
with close to no error. Microsoft lags a bit behind.&lt;/p&gt;

&lt;p&gt;&lt;img alt="products" src="/res/benchmark-products.png" /&gt;&lt;/p&gt;

&lt;h4 id="puritanism-and-the-specific-case-of-porn"&gt;Puritanism and the Specific Case of Porn&lt;/h4&gt;

&lt;p&gt;I initially thought about also benchmarking using a porn dataset. This
dataset is in the form of a list of urls to be downloaded (as GitHub request
no explicit content to be uploaded).&lt;/p&gt;

&lt;p&gt;There is seems that there is failure by design. Those services are usually not
only able to tell you “this is a bird”, they can tell you what species it is.
They are better than most human beings at those tasks.&lt;/p&gt;

&lt;p&gt;But when presented a
woman in lingerie they give you the response of a confused father with a kid
asking “what is this woman doing daddy?”, “well, she has her swimming costume
on ; so she must be going to the beach”. If you want to launch yet another image
recognition service, I suggest you to focus on this precise market where you
most perhaps get close to no competition from those industry leaders.&lt;/p&gt;

&lt;p&gt;A friend suggested that if you start to include adult terms, you venture into
sketchy grounds when you get false positive. A flag to enable / disable adult
labels could probably solve this problem.&lt;/p&gt;

&lt;p&gt;Nevertheless, Microsoft and Google offers to identify if the content is adult
or not with an appreciable accuracy.&lt;/p&gt;

&lt;p&gt;Funnily, Microsoft presents a picture of a man swimming and one of a woman
standing on the beach in their demo data. The man is not labeled as racy, the
woman is. I would be curious to know how this has emerge: sheer experimental
problem, manual labeling bias or bias extracted from some automated learning
based generation from online content.&lt;/p&gt;

&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;With a very similar pricing, the services performance can vary a lot, and
depending on the requirements one service could predominate where another would
fail, depending on the cost of noise and on the considered dataset.&lt;/p&gt;

&lt;p&gt;In any case you mileage may vary a lot from one dataset to another, from close
to perfect recognition to something partially or completely incorrect for 50% of
the items.&lt;/p&gt;</description><author>The Dark Side</author><pubDate>Sat, 25 Mar 2017 12:08:36 GMT</pubDate><guid isPermaLink="true">https://thedarkside.frantzmiccoli.com/experimentations/2017/03/25/image-recognition-benchmark-amazon-clarifai-google-microsoft.html</guid></item><item><title>CCTC Challenge VM</title><link>https://captnemo.in/blog/2017/03/25/cctc-vm-images/</link><description>&lt;p&gt;This is specifically about the contest held in 2011,
6 years ago. I’ve written about my experience
during the contest &lt;a href="/blog/2011/11/20/cctc-blog/"&gt;on this blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More specifically, Round 2 of the contest was a pentesting
scenario where we were only provided with a VM image
and asked to test it and report any vulnerabilities
that we found.&lt;/p&gt;

&lt;p&gt;I recently found the VirtualBox images, and thought
I’d share them as a easy intro to web security.&lt;/p&gt;

&lt;h1 id="instructions"&gt;Instructions&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="/contact/"&gt;Reach out to me&lt;/a&gt; for the VM image&lt;/li&gt;
  &lt;li&gt;Hack.&lt;/li&gt;
  &lt;li&gt;Credentials are student:student (username:password)&lt;/li&gt;
  &lt;li&gt;Open /cctc in your browser.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id="rules"&gt;Rules&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;Only application and its serving components can be tested for vulnerabilities. The serving components include
    &lt;ul&gt;
      &lt;li&gt;Webserver&lt;/li&gt;
      &lt;li&gt;Operating System&lt;/li&gt;
      &lt;li&gt;Any other services/files in the guest machine and guest operating system&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Any vulnerability identified in any component outside the above mentioned ones, will not be used for evaluation&lt;/li&gt;
  &lt;li&gt;All participants should necessarily submit all the exploit codes/custom scripts written to identify the vulnerabilities in the system.&lt;/li&gt;
  &lt;li&gt;The deadline for the original challenge was 2 weeks, but you’re free to take as much time as you want. Feel free to publish a list of vulnerabilities you find.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1s_o-HGlS2dKbDnm2mjTbgXpDHDHQgMYXlbOMEVNaBvY/edit?usp=sharing"&gt;The attached spreadsheet&lt;/a&gt; provides format of the report, challenges in scope, and the details to be filled out for each vulnerability identified.&lt;/p&gt;

&lt;p&gt;The tasks to be performed are mentioned in the report. Each task consists of the following sections:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Vulnerability/Vulnerabilities - You need to write the description of the vulnerability&lt;/li&gt;
  &lt;li&gt;Root Cause(s) - What is the root cause of the vulnerability?&lt;/li&gt;
  &lt;li&gt;Approach adopted (Steps with screenshots) – Write the steps followed to exploit the vulnerability along with screenshot of the final screen and/or intermediate steps.&lt;/li&gt;
  &lt;li&gt;Remediation with sample code snippet – Write the remediation steps to address this vulnerability. Also, write the sample code if applicable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also &lt;a href="https://drive.google.com/file/d/0B2qzfUR1eWklMHJONkZPUkVqLWZPS3pwTzFDYW84aVJhbjZB/view?usp=sharing"&gt;attached is a step by step installation guide&lt;/a&gt; for application set-up.&lt;/p&gt;

&lt;p&gt;Few points to be considered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Challenges can be attempted and completed in any order.&lt;/li&gt;
  &lt;li&gt;Only the application and its serving components can be tested for vulnerabilities. All other components like VMware, if tested for security issues, would lead to disqualification.&lt;/li&gt;
  &lt;li&gt;I will not be responsible for the discovery/notification of any zero day vulnerability in any software.  If any zero-day vulnerability is identified, it is the responsibility of the concerned participant to notify the vulnerability to the respective vendor as per vendor’s policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are really interested, you can find a copy of the report
we submitted at &lt;a href="/reports/cctc/"&gt;/reports/cctc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to Harshil and Shobhit for working alongside on this.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sat, 25 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2017/03/25/cctc-vm-images/</guid></item><item><title>Subreddit Algebra</title><link>https://mbutler.org/subreddit-algebra/</link><description>Yesterday, FiveThirtyEight featured a fantastic article by Trevor Martin, a Ph.D student in Computational Biology at Stanford University. Martin’s piece, Dissecting Trump’s Most Rabid Online Following, looked at the toxic communities surrounding Donald Trump, notably r/The_Donald, by using a machine learning technique called latent semantic analysis. LSA uses words and concepts from two sets of documents [&amp;#8230;]</description><author>mbutler</author><pubDate>Fri, 24 Mar 2017 22:45:01 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/subreddit-algebra/</guid></item><item><title>Last Week Tonight With John Oliver: Season 4</title><link>https://olshansky.info/tv/last_week_tonight_with_john_oliver_season_4/</link><description>Olshansky's review of Last Week Tonight With John Oliver: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 24 Mar 2017 12:36:03 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/last_week_tonight_with_john_oliver_season_4/</guid></item><item><title>The Lobster</title><link>https://olshansky.info/movie/the_lobster/</link><description>Olshansky's review of The Lobster</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 24 Mar 2017 12:08:53 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_lobster/</guid></item><item><title>YAC - Why? The app</title><link>https://prashamhtrivedi.in/yac_why_app.html</link><description>In this series, I will be talking about some desicions I have taken during the development of my new app YAC. This first part is about why I decided to develop the app.</description><author>Prasham H Trivedi</author><pubDate>Thu, 23 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/yac_why_app.html</guid></item><item><title>The Yearn Proof</title><link>https://mbutler.org/yearn-proof/</link><description>a. If you want to build a ship, don’t drum up the men to gather wood, divide the work, and give orders. Instead, teach them to yearn for the vast and endless sea.1 b. The invention of the ship was also the invention of the shipwreck.2 c. Therefore, yearning is the cause of suffering.</description><author>mbutler</author><pubDate>Wed, 22 Mar 2017 18:20:16 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/yearn-proof/</guid></item><item><title>How do you make a React form start out with some values prefilled when editing?</title><link>https://goshacmd.com/react-forms-for-editing/</link><author>Gosha Spark</author><pubDate>Tue, 21 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/react-forms-for-editing/</guid></item><item><title>Swivel Chair</title><link>https://june.kim/swivel-chair/</link><author>june.kim</author><pubDate>Mon, 20 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/swivel-chair/</guid></item><item><title>Distributing a ROS system among multiple snaps</title><link>https://kyrofa.com/posts/distributing-a-ros-system-among-multiple-snaps/</link><description>One of the key tenets of snaps is that they bundle their dependencies. The fact that they&amp;rsquo;re self-contained helps their transactional-ness: upgrading or rolling back is essentially just a matter of unmounting one snap and mounting the other. However, historically this was also one of their key downsides: every snap must be standalone. Fortunately, snapd v2.0.10 saw the addition of a content interface that could be used by a producer snap to make its content available for use by a consumer snap.</description><author>kyrofa's blog</author><pubDate>Mon, 20 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/distributing-a-ros-system-among-multiple-snaps/</guid></item><item><title>Open Source Contributions Made Easy</title><link>https://lucasfcosta.com/blog/Open-Source-Contributions-Made-Easy/</link><description>Hi, friends! Sorry for taking too long to post something new, but I have come back from the UK recently, where I've had a great day with some friends at Voxxed Days Bristol.

Recently, I have also ...</description><author>Lucas F. Costa - Blog</author><pubDate>Sun, 19 Mar 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Open-Source-Contributions-Made-Easy/</guid></item><item><title>A Few Good X-Men</title><link>https://xavd.id/blog/post/a-few-good-x-men/</link><description>The canonical order in which to watch the X-Men movies&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/a-few-good-x-men/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Sun, 19 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/a-few-good-x-men/</guid></item><item><title>The Man Least Likely to Succeed in Politics</title><link>https://www.danstroot.com/posts/2017-03-19-the-man-least-likely-to-succeed-in-politics</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/elvis_nixon.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Dick Nixon understood that getting the smart, popular kids to vote for you didn't matter. He called the popular kids "Franklins" and he called his kind the "Orthogonians".  Nixon discovered that being hated by the "Franklins" was no impediment to political success.&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2017-03-19-the-man-least-likely-to-succeed-in-politics"&gt;The Man Least Likely to Succeed in Politics&lt;/a&gt; first appeared on &lt;a href="https://www.danstroot.com"&gt;Dan Stroot's Blog&lt;/a&gt;</description><author>Dan Stroot</author><pubDate>Sun, 19 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2017-03-19-the-man-least-likely-to-succeed-in-politics</guid></item><item><title>PGP Pub Key</title><link>https://blog.eutopian.io/pgp/</link><description>-----BEGIN PGP PUBLIC KEY BLOCK----- Version: SKS 1.1.5 Comment: Hostname: pgp.mit.edu mQINBFkCCS4BEAC8cC7geoSLb6xG+BM2XCCMl81KxIibgs+5UuD2slIvGBVntWg2BYQF5oHD Dbcqx3FmiRkU5L9clwYTMpR9293b4+fk64cPm1bGx0YTU6vpRmA+Cc5Q36Mny/okhWNr0Fxb UMh+EfTIjp/U0zXF/sFLcZgM0pUO0KRkaWkcLuuD0QuCx93Eo4IY169RqPwjRhw33EhDpgmC Xrfwnug31CTt+z6VNFmYv9Pm14u8ct/8wBh47J374mlRm+fTovw0qzokUYDAd4l9PHF0+K9l F0mf2suDn+1VAyTd7ZniEnwT8N+VX/6RoS3cq0TwKuGFN6tupAmFdFgq4PtrX4hiyQyeyhn1 0Dmwli8ZfQKpqQoVtKOWcKSVhll7/eWi/5eYBGYmDQe92j2OOt0+mwCPGrsaq51Pe7LAx4AW qYYbINYhdpJNL/MElRqbxWnhjNHa9L7UJg7iffh5l332Ufe2FwGGXVhbSG6UQdUH6ke7mvFU Zilt0e9h1TFtLpjuuY+9bVJfubBrO9KPvFfcurJ7cL+M69uaU1IUUk/ZsT2e3hIv7KqwZSwu qI9vWE8YMkIC5HkmuUn4Y1xlNvl5Q0G5K+cpASolxmxr6NfkZkw1BbSioaa7xTCqJTPBnckX yBxyRScDR8jz7brt1o6aupKXexsS2jn8T3D8pjUfb5bP1LxGKwARAQABtBxOaWNrIEh1dHRv biA8bmlja0AzNjBpcy5jb20+iQI9BBMBCgAnBQJZAgotAhsDBQkSzqYABQsJCAcDBRUKCQgL BRYCAwEAAh4BAheAAAoJEGQ9326ErjpXRF0P/1LFAFTHjTrA8uGoFlg4OToVqYfWSykBzmkv NJrFpHzYACV1CkiOrNh9jrtH7pL7+1gANWAtGvZ8Px4RGUxxnzUZcmdXqXYSCf9fjAZfRwVd 1ZfVz6ItnXDpgaAM/+jpp59Zq4p2Ibz2o1NrwBIkpbGgiXkUZm51VLKeuQhGHZOmWnAJ6r2x fQX201SGtRzDHPbKB9sNp7wg8eRf4IcjnImeUrwyYwhXvWuGsxrjF8ISMwTrTO5V7090kAoO DEywVtoKpg1NNDnskj6Zwfapc7O849mIFqDXJHPtv19RjiDH3ji8cxWSTMpsa7zGWsX3UJ7G M3MvMXPgBr0nMx/p4EYp8BMZzRGEgdhPfgNdFdkJ7PSwh/FjgOlgrUGmAydjHCWZ6Reiritm h7R/FitOSmNIX6axOXba/fxl7qmE9m/MkBto6ddR8AtS10i+IYSPvNoyH7gJdr9YeYQEiihN 05M0TXa7s+ShjCSjV6pYNuC8LbJpnrziVikl9T174GIsDe31oK+tIKhCXotQo3mOJL3RxM0R LWDBtKAAUBWsmPHx0RVkfV0sypaHDpbeqgD+wOoNM/O3XqjdnJWAvVq647EK6S/lbfO1W9h7 0So+SECiyX9EAV5D14F1FCzqoMUdr5FWfbucn2RajDKCR8IaDvSom+9HNHDBcpeRcrEIJjYT tB1OaWNrIEh1dHRvbiA8bmlja2hAMzYwaXMuY29tPokCPQQTAQoAJwUCWQIKPwIbAwUJEs6m AAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRBkPd9uhK46VyV+D/wJPfXZRKn0sXJqyCto kd5PACd9sfMQASFGO5of9rsISNgDEyQPR36f8w7oC5ci2ysVVWfs61S+lyWg9xOcLvbGFGPt pAIVeM6MeozJWZDnNDx/YGX3I8AIv4RLbL4Ffj2q0APgGmebQ3Gj1QMYSxd9j1no3gaYUx4P n/dSgWAsZDxb3qjkwGTG5FrXKbBa3VL2smWjIFCehO80wQjSOQGIcvJAOKCeMV00TFTYviNM SYVE0/EKfQaNsCn2uVtPnjWeC7z8vaPysLtngWYjJLqwh9US/4REgFRqyzXerkackaFNFwiG mCyI8lADG+mfQAY//AinXRRP0tkmFmDVeDCCDZTfpAV6V1ir/r4dD3doXkgmnKc5gsu4xbgh L9c3ltdI5wJTLSCvxpfKV6k2EKnptd8cmcCJXA2Gcdy7BvmDhmVGz9jhl6oS1gbS498TloR7 cs9LoU1CkINChJeVeXSrWpsqV+WsqQuSsVIRHyMTO9wVbrrJ8FlszYe+DzgyD0p63E/XcS1A 5n9JoPoYuzDA/u3Iu4RevUu1xOVsDZjd86biqKwoG+/Nbx58cen50pxhNhXhcjO5boMs2oD9 y8w7eiCQSeCoVazn2qixFkZX8OUVKkG3bFV2FZVAq4lSMAgkmxf9SDkJa3/XtM5So1bU8nso ygCwRCbWvZnQenKB9rQjTmljayBIdXR0b24gPG5pY2suaHV0dG9uQDM2MGlzLmNvbT6JAkAE EwEKACoCGwMFCRLOpgAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlkCCjUCGQEACgkQZD3f boSuOldYJw/+OtKmj51BK3qi4cyE6/leK4n5u0qogdfo+9mg8wNY52MUTb4LOLn07JxFT0VO DxXCr+CPlUGHVmbGkwmmVuTTt3R98g22gK5nsH5icEDd+e5hXJ2tHOPJ9NgY17OBARtAT02a USSy3WWGu3GL5osnHZmv7ejrnnwDCizk97+zYzpIGHMzC+nT17/rpggcvDhfIVVWySJB8Zv1 rTrqJS5/B/nXXT/9p5wJZw1K6ilRvL/oh6JgcDZ2Cd4UHvdOO+sq/5reT6XwR6Q0Xt5hx20f Hj5wpD+X81Aqsm0KtpyUHvgR39K8+DzenOX00CZl1QBafJ0Ca545fDWqQOqfD6TS2H6AtCBM Lzsj/Z43r/1KW6ZvXcI2nI317+BunadVlnDb4X5vfhbGpEnuClZsGPk7f/ggF5cdO+ezKs1c FCk+U5KUSYJVXYR4gLkTSgoa0RNWyUso/O5fKSol1MqRlodttBpsGxTybnJezE7QxlbSbS4Q vV50NuUApznLMm9k/wjfFoTW1ScgW7vAQM75QkxVtA/71JJB7bhNuvZXQ/kOOtJddvpBlbWg /SdGcrnFBk9wWF6ENOTx6K29ny4+R7PJvt3SUsMIaQR/IP7Y3H1izi6+T0AQQVrDkBccWozz 48Xhg2nFsTYCrx3YAawSh5ARM0DeX2r20awms6gf2XisdUOJAj0EEwEKACcFAlkCCS4CGwMF CRLOpgAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQZD3fboSuOldQQQ//ciyZlwaBOx/k xfbVxmpBcld+hw/x7mRsXrLD+bbIb8Ie4ljlb2xTgeLHxkQ/5qcaxJVUJJHKO//5L1w/NofV E1CaDtuAgOUF/U7VzS1xzyNZeRFqCpGkVx0IdF47yHbKkHBcGlInapnckIKGpa3n8kWTHYeC G1vti8ljf+ivc/YN21eo99ij0wKhYErx0esD5I66E20Sb5Oi0602yPHTIh9OWYGgvo43V8pd lJPpp3X6Nu8U29UWht/RtiJ2JFHgyoTZqjKwrh4eAbsoa7+c7a9APKomvKTIQJdujGYmnIHr C0hRPvRJ0KxnhCMwhqHGnDfcAYUOOJdsIuuZfiBMUhmjhq5cKU+mdx1/aEnTi41PIRVTFM5S lyc58lCaqpq0xGdkigAjPZHmCC8eHfaLmjAZWtuO7Bh86uI+hOroK+53FJ6TQuQxIko6xl5w U2RH+3aKOAv5rn7ArsvNQlnGM1u5Q5qSNfQROUyWFJ+zdhTGF8N4x3dzXSRtIHahow19OfS9 Oqk7JaTcombO/dD1exx541fB1h/dgpocTCBmrcI+4Fh2BiEzfyXcFgY3VdFDGdPSYZX9xx2I 1wjZ0sRucWLSyllr5vy3IW7WX7RncZmgj3YIFX18UwLk59JJvpl0LxvVsT4FmPLlnQ+Ky8pf YWZaZ0hfGgH6uNXgggzaDQ7R/wAACNLIEAEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgAB AQEASABIAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiu im5woNqirr7EztDOfJri8uDI8LjKzsb/wgALCADTAKEBAREA/8QAGAAAAwEBAAAAAAAAAAAA AAAAAAECAwT/2gAIAQEAAAAB1QwmExzgtqqhoDPMcRd1nOzdDsXJlrq4yT2Ua3bHJxTJeuue c1pshthhzVA66CKNkDbc8MGl3dMZRw10seHItummOlIGPL12Ecb69BgAhLl6NGHBfU2AAkjG 9GVxvobABCSz0sKzy3bECaSM9bGLn3aGATnJWjYjOyG6pTGdFUwYh1lO7jKcdbqmNinSc5qz JaCdsEA1SkM1YjQZIDYk5WehJoM6A5baThrPVRXUBkgAaGsrIvRo1QZpkyGN6LTRtMDKaJlL NbzuyhimU1MilW9mA2knIkRKrSgCwQ0lKmHpQxtgJglMqhjomwEwCMxsbuVYCYAc0YX2FOT/ xAAkEAACAgEFAAICAwAAAAAAAAAAAQIREBIgITAxA0EyQCIzUP/aAAgBAQABBQLFFFFHBqRq RaLRxiZHrczVZzh5vEyHS3RKbliMWUzSUPF0IkuI9MnqebE1hlLKkaV0fJLfEZRRpNJ+Jae5 8Dd5o0Gg0lFFZQ+R/wAWpbZ+YiiuuawvMz8KEuOx8OH45axH3tkQ82TXMe6QvNklZHukLzZR 99WosTHvYullxOCj63NCKxKaRH5LLyyzSLiMfOhYY4piVbJC20UUV2PtXQz7yt/HdH2kUikU jTE0o0oroZeyKs0Gg0Gja/d31lkOl9FnIsLztoo0lfsfX6i/xXjgv9N/2R5H+HxN3u//xAAi EAABAwMDBQAAAAAAAAAAAAAAARExECEwMkBwQVBRYGH/2gAIAQEABj8C7Zc+UklKea32N87c rv6/KkqalNVII4InaN0FcfB//8QAIRAAAwACAgMBAQEBAAAAAAAAAAERECEgMUFRYTBxgaH/ 2gAIAQEAAT8hiIiCCCBx5Pgz4ZrboZ4GtExEIQnCiV0NujF5Nlfqjv0J+xTBOoXSPInC4pRK 0aRaEfk7UIXsv8HXmfwbTxg/4JmiC+UWpC9iFxh0fzEbmllP7Guh/BvaGzrQ6tMTnRsjFLQ1 BYjIyMpqj/RdmuCPQTDc7iVjb7dEouLJKWN4XYrEEgkFxzQlBG1I37zo0a7DxfYuKjfClkbR bRmzZsSh9iEv0PYoNoUpRDQ1sT9i1iGEJiDi7/V8lTsfuTRomKUiGkEoVil5NjQeJ1RCEIbN i7Og3DZsVELDZsNIm4/ND3xUpqOpsyJYWnSFWGPBI3sfbVYmryeAXGIiH2JFBYuPYvb7Yk/Y nhLgkNImIIIIyxb4MfCuC740vFR4mSyZ2xSlKvhr4f4F3OT3hk2JaGMWqfJHyPkfLhf24s0K CECYxoohRUVBXsf4QQT4hJyJwbo8iF9wXtl2aIiLheF417Ne0OLyNPComx0GLMUUvHvLHsjM zBPQlWJ5pRRdZYhrMyxvCQl+RYaJwY0JE/MuEINDRBLC7POEdLl55UvFK34FG3sJH00+Cw+X nm7/AJjr+DN1bumhusoef//aAAgBAQAAABBrxNa4VrMlZHPl+dc3HTNLhk96nWALjj2Yvs/I lICCw3M18thJQEBo4uXvtK6ax8WFxOBoXsYQjrSg4GVj2caGihT8+gaxOf/EACQQAQEBAAEE AgIDAQEAAAAAAAEAESEQMUFRYXEgkYGh8PHh/9oACAEBAAE/EP8Ae3+tv87f52+393+dn38f zIKCMM44/m1cxuzwv0wjCHaSgSSpp4uUCDBs2vptfTa+m4CvGXFMWaOA97Yun70tntXvtKcf 73g0S1qv3AOItguQPcNYYiGFhW9R62BLo/F5fu8CgcP5+3yt4e6Dl4vKb4J58xDsJDuHd78X IAMByaPcmyNyYfCPQJCWlpb9kiNUu6qdovgz5Z17wo7Fe79zhhvvLE5el4tTyJdhcrD3A9x4 dZ5mcOjcw0/u09v5uUDEHUCATvB3SY4dmxObN7RTnJoa7TJDQ0jLEgG84jNw6KcgIlghhhtn qO1oihafMtwDYuNmTmwckLxAdp0TmDCw6MJE7zQYeJcHM8xjGR0E5+Vp+C226IiAgiLFpPTe jljvIg+pjDuQetnpZ6W2+Seotn2sREH47bL0W24sZEPFxnqOsUnxYIjxsHBEWdXqz0WzLPl5 YPzB9tn3Y+mX110gx7vEFn4b1emQuOMMEbc3PSWF4iCvzBxBZ0euWSTbNxPu4j4hjoff+5KD 1N9129GGrSLLJ4gC0Z5tXC1cYb9kAA2B7bHux7b6X0sg5ch0mpij0gl2czxcEMcuEji6kMIc PnIuMITrC2vq19dPdIp3melvK7Wfkl8zXJHAM55IhyYyktn52ASfOWWdacJKDdi/ZDxDDbbf DfDc8e7mniyT57b8QZaEwJ+7nHbIjqrg6cgi4DB6sXaMR3Ig+S+ZvmbH4gbhjIS2wcwHmB4h vaDOg5nzDMuT4Rc3Nzfa+134hm/PPQOhQbOLzHTZZhjtMrkbeg6Py/tb7xEJnKSQdGyOJK2C PE/yXAhCwD76d8e+PfHn/TPpL4P7kmh2CbLL0jhzBPDYEAoGvuJMh0nUOcd/Uf8AtX/Wv+pf 9WT4t9Fj0/Vj/wArQM6BJxMvMnK8t4sRRWbmQWHwcWO4IF4L4C+L8HFyRsg6Ek9H7nPD+69N kfdl+rlFw9E91d1lHvmTSWR72IR7NsstmY6dkHu7S3iQkggDi4WUy7R52HiQ6hPBlsvR2lvy dGeheJXLkmszELO5b2ZPPQOOj1TiHHTT7uEkkkG0Z4wXkfEPEdsgs5Cw9/gy5fwYzDxIyCyN e89Yd4Tye7fx8o/BNu/MPiO3w+ni2Ykfov6dEbY77eegnrn5PZH4srZ7LmRwTRs8ZL41aGcW a2ruPMHezt09jPT/2YkCPQQTAQoAJwUCWQIR3QIbAwUJEs6mAAULCQgHAwUVCgkICwUWAgMB AAIeAQIXgAAKCRBkPd9uhK46V7/7D/9jgbf6/eySOPRsnhxNu+bzgIcd/nGgwm+h/zcBy5tb oD5LAU2vRFZgk8RuGDAQcKdJ23Phf+BQUb1CE1OEd8GCEU4F9z1MLSaA3JIOfqAdBFfUY/0H t1pAlDsXVAC7Q8Lpoi4oQi5NVrBZqlbTSAg7DxoWA2A3qllrTiYP62EcocLRpXl5Ka52UqyN f1o9qij/2AXWSk0pqcJFgn3MNOb8s6eG74wYckRBylCpkc5iiWpPjlQDzfiQglw9FtebTzYb GAmVXGQCPhV1HAy9UobVsZHu/wvervHv7SrfjOtsz/f+ZL57/KBWBVYDTUuvFgfrJOq1pdX/ ksAeheiXktjOfOYjos172MhtwE6uCJMla97Cqf5r4L4STrZK1LZB2oQAa8cqJXMoby+t2X7T e6fErB+4kkv8hBBToXtrOE7LVQ9gEcsgQ8zv3CGfW7gPVvOFy/KmRfKkVy9dwLCoVs4Gw1MK CxPgd1efK+dEp4IJL8c9VmLKV81lJK+1iIaJSJdGcnZpqZ9BR/PJNdy7KzGh9eH6sGzN3+SB axDV4O6hSBbQlh3QhW6KUh5hV1G8o2px+VKWu7Tq3duF7cCcYxqY9OnpqbnBAKhwEsrVbI/U i05geu+UEDN7DyofZ8rI9IZk6UvESQdl1L7fhuL1ndCkqVW7ODt9bWe4q2Go1JyQrrkCDQRZ AgkuARAA4OQDyvga1iSKHcir2y/gY+VvsoOesq7jxcNgeHKvz/CnPoBcermJuNbnpSmdGqTI tnCKS5gWfpP7mD3lmV9tMF5njOGuSN9CfIRIVI8syrVS35WSLvXIver8lORGIPmRBh+NfowT v6UXhejNJoRZ36C6uqFySKcONgrxPm0q3QhiLZ25IaEd0hKQYdrucZnrcoLobJuD2yGmaNWY u/4v3w5VbKRatPLDl8UiQn44gvXgTntY39A8+j5wW7AS3zQdMbPE+Wg33JhJobKCIHKag5AH oDj7RvJHCSx2ftihzaGvPbk1YmhkwPpwB40nJoQ95FGiFz9AZmPtzh15HtIuIjGeBeQl6G/k OS/yDuHRJOejyOs1HjveGkKxCM4b+n3L4B2wB5EnRmL8HeHQztYAzhZwmM0XQFGVSrlAzMuE OpDQVYuYNq9asVPLs7ntuuGEd1VnbBipFd5ouIjaCNHIl5m61k/gI9Dq80Etm3hkYAKYYv/O NCPLjyJSWbSjZeJ5RW2jbmDl9/6wudpJlvZWEy8LuXRiNYMtG6nYWXuTSTuXGnzx8HGWw/Rj iyhdj8Q5EuJEN91JZN2nuM62Bg5Uq8e8MRb5ce7xZtt/RGO5GYPtdefzRV4IGs4IsfMoPcS+ FxgJYUVNEcsyMAnuGysRb3WpthZd3es7iihksBOVFNEAEQEAAYkCJQQYAQoADwUCWQIJLgIb DAUJEs6mAAAKCRBkPd9uhK46V0eCEAC06M58vdiXgxLLZNoo7c+xffXCMUMmH2x5rDci0x2P z4j3KNEeDZugL/azN2VP65tYYTQgAwZj/0CWPohOsZhvnBlhGHMq2xjps9UfOSV2YXgPUxVz N14JFfzxomkn2psvy7Yty2I3OjOnbGrcrv4Y0Kp9hArvJu95cRH9U+Fw88wFwzv5klWN+yNO 8VkU1P/o3Kz4S5s82qD7Ssl+hXkP7iiXlWfXm+/Kwtf0h4FZOML7VYs62xMGp1zaw2wWZ3qC z8iDfm+AWMbzs3GxuRZFmAkhdhuA7k1KrKeklR4TOH5sT2WeiCOlrpsHbQKa50omF2ikYFgT oL6wy5JrtZ5UIOAa+VTi45bhOIqrTYXuI5A/njBOhHRlLFxnVmQK0ZHRcsNdIatvcjdOFEHA V/8gyGWZw5Edz/VVClYNb7VJ31g+A5L0eDQi42IFAucVwX5H+7vv7g01JJKqGWnQp99SnsDM SNrk9whCBWIE+yHXLnirG/DCir0fyeV4WWt/0DN6DB8VhbOqK8CaGTaleopYjbBFOZu2hMEs +OPZ9LmnADYyEMp21N2ZRmhg8ujrREr0Lfa04haCtH57w3ou992s/sW7ySvjZWmiJV37OCz4 KtP+mmbLIrwSPYb3G3NKY9SI5dqsSsaIiFCpD6Dj6GexZpWUkVN/RdzbthE3vtuCaA== =ZhkS -----END PGP PUBLIC KEY BLOCK-----</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Sat, 18 Mar 2017 23:23:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/pgp/</guid></item><item><title>Chasing Bugs: PHPUnit Hides Errors</title><link>https://www.mikekasberg.com/blog/2017/03/18/phpunit-hides-errors.html</link><description>&lt;p&gt;I love stories about hunting down interesting bugs. I find things like &lt;a href="https://arstechnica.com/information-technology/2016/03/rage-quit-coder-unpublished-17-lines-of-javascript-and-broke-the-internet/"&gt;left-pad
breaking the
internet&lt;/a&gt;,
&lt;a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1139"&gt;cloudbleed&lt;/a&gt;,
and the &lt;a href="https://www.eveonline.com/news/view/sleeping-beauty"&gt;sleep bug in Eve
Online&lt;/a&gt;
extraordinarily interesting.&lt;/p&gt;

&lt;h2 id="the-bug"&gt;The Bug&lt;/h2&gt;

&lt;p&gt;Recently, I went on my own bug hunt. I’d seen some strange behavior in our
PHPUnit test suite. The tests were passing when run normally, but certain tests
would consistently fail with process isolation enabled. The behavior was similar
to what is shown below, which is a from a simple test suite I made to reproduce
the problem:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mkasberg$ phpunit .
PHPUnit 5.7.15 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 124 ms, Memory: 8.00MB

OK (3 tests, 3 assertions)

mkasberg$ phpunit --process-isolation .
PHPUnit 5.7.15 by Sebastian Bergmann and contributors.

..E                                                                 3 / 3 (100%)

Time: 421 ms, Memory: 8.00MB

There was 1 error:

1) ThingTest::testTheThing
array_keys() expects parameter 1 to be array, integer given

/home/mkasberg/Desktop/php-test/ThingTest.php:7

ERRORS!
Tests: 3, Assertions: 2, Errors: 1.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Uh-oh. That’s not good. I mean, the failure alone is bad enough, but the fact
that it only shows up with process isolation turned on is particularly
troubling. Process isolation starts a new PHP process for each unit test. If
tests are passing &lt;em&gt;without&lt;/em&gt; process isolation and failing &lt;em&gt;with&lt;/em&gt; process
isolation, it implies that the tests are changing global state. These type of
bugs are notoriously hard to track down.&lt;/p&gt;

&lt;h2 id="the-search-begins"&gt;The Search Begins&lt;/h2&gt;

&lt;p&gt;I started by simply debugging one of the failing tests. And I found rather
quickly that the error (shown with process isolation enabled) was correct. Very
simply, a function was being called with incorrect parameters. Now, that’s easy
to fix, but I didn’t &lt;em&gt;want&lt;/em&gt; to fix it yet. Before I could fix it, I had to
understand why it appeared to pass when run as part of a larger test suite.
A test suite that hides failures is a &lt;em&gt;really scary thing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The scale of the problem I faced was overwhelming. The results shown above are
from a simple test suite designed to reproduce the problem. The suite where I
originally discovered the problem had more than 1000 different tests, more than
20 of which would fail with process isolation enabled. Figuring out which one of
the 1000+ tests was affecting the global state was a daunting task (because it
could literally be any of them).&lt;/p&gt;

&lt;h2 id="needle-in-a-haystack"&gt;Needle in a Haystack&lt;/h2&gt;

&lt;p&gt;My first step was to reduce the size of the problem. Disable as many test cases
as possible while still producing the behavior I originally saw. Basically, I
turned off different parts of the test suite until I figured out exactly which
combination of tests was causing the problem. This is a bit strange - imagine, I have a
test suite with more than 1000 tests that should be producing roughly 20 errors, but isn’t.
And I’m turning off entire chunks of the test suite, hoping that I still don’t
see any errors even though I should. Eventually, I was able to reduce the problem to 3
tests.&lt;/p&gt;

&lt;p&gt;One of the tests was the test that is supposed to fail. The other two tests were
required to run before the failing test to reproduce the behavior that hides the
error. If I turned off either of the other two tests, the error would be shown.
These two tests were somehow affecting the global state of the PHP process. I
created a
&lt;a href="https://gist.github.com/mkasberg/ce7611c602e5f445b730493577b9c8e5"&gt;gist&lt;/a&gt; on
Github that shows my own (simplified) reproduction of the problem.&lt;/p&gt;

&lt;h2 id="finding-the-bug"&gt;Finding the Bug&lt;/h2&gt;

&lt;p&gt;At this point, although I knew &lt;em&gt;which&lt;/em&gt; tests were causing the problem, I still
didn’t know &lt;em&gt;why&lt;/em&gt;. In the codebase where I first discovered the problem, the
problematic function call was buried 15 layers down the call stack. To find it,
I took the same approach that I took to finding the 3 problematic tests. Comment
out large chunks of code ’til something changes. If I comment out a large chunk
of code and the error shows up because of it, I know that something in that
chunk is causing the problem. I didn’t care if I broke any of the other tests
along the way - I just needed to find out which line of code was preventing
PHPUnit from showing the correct error message.&lt;/p&gt;

&lt;p&gt;After a bit of searching, I found it. And after finding it, it made perfect
sense. Our code was calling &lt;code class="language-plaintext highlighter-rouge"&gt;set_error_handler()&lt;/code&gt; to do some custom logging with
errors. In a production environment, our custom error handler would be
configured to send error messages to certain places, or act on them in other
ways. In PHPUnit, none of this config was loaded. So it would eat error messages
&lt;em&gt;without reporting them anywhere&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="the-solution"&gt;The Solution&lt;/h2&gt;

&lt;p&gt;If I was writing all of this from scratch, I’d probably solve this problem with
dependency injection. In production, &lt;code class="language-plaintext highlighter-rouge"&gt;set_error_handler()&lt;/code&gt; would actually be
called. And in unit tests, I’d use a mock that would never actually call the
&lt;code class="language-plaintext highlighter-rouge"&gt;set_error_handler()&lt;/code&gt; function. But I wasn’t writing this from scratch. This
error handler was in a very old part of a very large codebase. I needed to be
&lt;em&gt;sure&lt;/em&gt; that &lt;code class="language-plaintext highlighter-rouge"&gt;set_error_handler()&lt;/code&gt; would be called 100% of the time in
production. And, for fear of running into the same problem again, I needed to be
&lt;em&gt;sure&lt;/em&gt; that it would never be called inside a unit test. The solution I came up
with is ugly. But it &lt;em&gt;always works&lt;/em&gt;.&lt;/p&gt;

&lt;div class="language-php highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GLOBALS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'argv'&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="nb"&gt;strpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GLOBALS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'argv'&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="s1"&gt;'phpunit'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;set_error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&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;h2 id="lessons-learned"&gt;Lessons Learned&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The biggest lesson I learned from this experience is really just reinforcing
something I already knew. PHP has several functions like &lt;code class="language-plaintext highlighter-rouge"&gt;ini_set()&lt;/code&gt;,
&lt;code class="language-plaintext highlighter-rouge"&gt;set_error_handler()&lt;/code&gt;, etc. that can affect the global state of a PHP process.
If you can’t avoid using these functions entirely, at least isolate them in your
code base so they’re not inter-mingled with other logic in your code.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run your PHPUnit test suite with &lt;code class="language-plaintext highlighter-rouge"&gt;--process-isolation&lt;/code&gt; occasionally. It’s
slower, but it might show you problems you didn’t otherwise know about.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sat, 18 Mar 2017 18:02:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/03/18/phpunit-hides-errors.html</guid></item><item><title>Fun with Inodes</title><link>https://peterlyons.com/problog/2017/03/fun-with-inodes/</link><description>&lt;p&gt;I had an inherited client project running on an EC2 Ubuntu instance like a champ. The system had racked up nearly 900 days of uptime! Not a lot of traffic but still it was running nginx with TLS, a node/express app, and mysql with pretty much 100% uptime for over 2 years.&lt;/p&gt;
&lt;p&gt;As I went to do some routine TLS certificate maintenance, the system started throwing "No Space Left On Device" errors. I was confused because the root filesystem still had ample free space according to &lt;code&gt;df -h&lt;/code&gt;. A round of googling eventually clued me in to having exhausted all of the ext4 filesystem inodes, which again I eventually through research understood to be mostly caused by continually accumulating unused debian linux kernel .deb packages through normal automated security patching. We had at least 15 different versions of the kernel available and each requires many files under &lt;code&gt;/usr/src/linux&lt;/code&gt;. I eventually found a solution consisting of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Free up some inodes by &lt;code&gt;rm -rf /usr/src/linux-headers-X&lt;/code&gt; where X were older versions no longer needed. You can confirm the version you are running with &lt;code&gt;uname -r&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Identifying a longish list of important packages with broken dependencies and reinstalling them with &lt;code&gt;apt-get remove&lt;/code&gt; followed by &lt;code&gt;apt-get install&lt;/code&gt;. The list ended up being &lt;code&gt;linux-headers-virtual linux-virtual linux-image-virtual libc6-dev libstdc++6-4.6-dev g++-4.6 g++&lt;/code&gt; which is rather frightening to uninstall (not sure the system would be usable if you rebooted between the remove and the reinstall).&lt;/li&gt;
&lt;li&gt;Cleaning up using the commands in &lt;a href="http://askubuntu.com/a/564558/43030"&gt;this askubuntu answer&lt;/a&gt;: &lt;code&gt;apt-get install -f &amp;amp;&amp;amp; apt-get autoremove&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I ended up freeing up nearly 400K inodes and over 2.5 GB of disk space during this activity. The &lt;code&gt;apt-get autoremove&lt;/code&gt; for all those linux kernel image packages took a long time (several hours) as there's a bunch of processing associated with each one.&lt;/p&gt;
&lt;p&gt;My appreciation for dpkg/apt has always been strong, but here's another anecdote to pile on. Prior to this, I've done many many successful upgrades of debian and ubuntu and even when things start to go a bit sideways, always managed to recover a working system without wiping and reinstalling. Now I know that you can run out of inodes over and over on a server for months at a stretch, foolishly reboot before attempting any repair and still boot and run your production processes fine while you handle the repairs.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 17 Mar 2017 21:03:32 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/03/fun-with-inodes/</guid></item><item><title>Doctor Strange</title><link>https://olshansky.info/movie/doctor_strange/</link><description>Olshansky's review of Doctor Strange</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 17 Mar 2017 16:33:20 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/doctor_strange/</guid></item><item><title>Futuretech '92</title><link>https://jasoneckert.github.io/myblog/futuretech-92/</link><description>&lt;p&gt;&lt;img alt="FT92a" src="ft92a.png#center" title="FT92a" /&gt;
&lt;img alt="FT92b" src="ft92b.png#left" title="FT92b" /&gt;&lt;/p&gt;
&lt;p&gt;This year marks Canada’s 150th anniversary (1867-2017), and while there are some cool events happening this year (e.g. National Parks have free admission), there really isn’t a lot of hoopla surrounding it.&lt;/p&gt;
&lt;p&gt;However, I have very fond memories of Canada’s 125th anniversary in 1992, because that’s when I got to go to Alberta as part of a student enrichment event.&lt;/p&gt;
&lt;p&gt;In the summer of 1992, the Canadian government hosted an event called Futuretech ’92,   where 125 of the top students from Eastern Canada were flown to Calgary for a week of educational motivation, and 125 of the top students from Western Canada were flown to Montreal for the same.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Thu, 16 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/futuretech-92/</guid></item><item><title>Samurai Jack: Season 5</title><link>https://olshansky.info/tv/samurai_jack_season_5/</link><description>Olshansky's review of Samurai Jack: Season 5</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 15 Mar 2017 16:32:41 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/samurai_jack_season_5/</guid></item><item><title>Links - March 15, 2017</title><link>https://faingezicht.com/links/2017/03/15/links/</link><description/><author>Avy Faingezicht</author><pubDate>Wed, 15 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/03/15/links/</guid></item><item><title>Flash Boys: A Wall Street Revolt</title><link>https://olshansky.info/book/flash_boys/</link><description>Olshansky's review of Flash Boys: A Wall Street Revolt by Michael Lewis</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 15 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/flash_boys/</guid></item><item><title>Programs that have saved me 100+ hours by automating repetitive tasks</title><link>https://danielsada.tech/blog/programs-saved-me-100-hours/</link><description>Since I wrote this, there has been two HN threads on this blog, they contain super useful links and programs, go see them! Thank you for reading! https://news.ycombinator.com/item?id=13887237 https://news.ycombinator.com/item?id=22849208
Along the year I&amp;rsquo;ve been working on several web platforms where repetitive tasks are usually the norm. From batch optimizing a thousand images, to changing from this obscure format to csv or json. What if you need to critically update a file in your client&amp;rsquo;s and you aren&amp;rsquo;t fancy enough to use some kind of continuous integration tool I&amp;rsquo;ll give you some tips and tricks to be productive.</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Wed, 15 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/blog/programs-saved-me-100-hours/</guid></item><item><title>Spoon carving</title><link>https://june.kim/spoon-carving/</link><author>june.kim</author><pubDate>Tue, 14 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/spoon-carving/</guid></item><item><title>Google Home As A Bluetooth Speaker for Apple Users</title><link>https://olshansky.info/posts/2017-03-13-google-home-bluetooth-speaker-apple-users/</link><description>One of the biggest disappoints I experienced after purchasing my Google Home is discovering that it cannot function as a Bluetooth speaker…</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 13 Mar 2017 07:11:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2017-03-13-google-home-bluetooth-speaker-apple-users/</guid></item><item><title>Installing gnuplot on macOS</title><link>https://xenodium.com/installing-gnuplot-on-macos</link><description>&lt;p&gt;UPDATE(2019-05-19 Sun): Plan A and B use options no longer available since the recent changes to &lt;a href="https://github.com/Homebrew/homebrew-core/issues/31510"&gt;remove all options from Homebrew/homebrew-core formulae&lt;/a&gt;. See Plan C.&lt;/p&gt;
&lt;h2&gt;&lt;s&gt;Plan A&lt;/s&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;s&gt;Install gnuplot Qt&lt;/s&gt;&lt;/h3&gt;
&lt;p&gt;&lt;s&gt;If you have the resources, you can try the Qt flavor. You need at least 15GB to download and a long build. Ran out of space on my Macbook Air. Aborted.&lt;/s&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install gnuplot --with-qt
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;s&gt;Plan B&lt;/s&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;s&gt;Install xquartz&lt;/s&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install Caskroom/cask/xquartz
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;s&gt;Install gnuplot x11&lt;/s&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install gnuplot --with-x11
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Install feedgnuplot&lt;/h2&gt;
&lt;p&gt;Feedgnuplot is handy for plotting data streams realtime.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install feedgnuplot
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Plan C&lt;/h2&gt;
&lt;h3&gt;Install with no options&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install gnuplot
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far so good, but default gnuplot formula uses Qt and the Cocoa plugin could not be loaded:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;qt.qpa.plugin: Could not find the Qt platform plugin &amp;quot;cocoa&amp;quot; in &amp;quot;&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Debugging&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;QT_DEBUG_PLUGINS&lt;/p&gt;
&lt;p&gt;Turns out you can get plugin logs using the QT_DEBUG_PLUGINS environment variable:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;export QT_DEBUG_PLUGINS=1
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;QFactoryLoader::QFactoryLoader() checking directory path &amp;quot;/Users/myuser/homebrew/Cellar/gnuplot/5.2.6_1/libexec/gnuplot/5.2/platforms&amp;quot; …&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This led me to find out about the &lt;em&gt;gnuplot/5.2/gnuplot_qt&lt;/em&gt; binary.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;qt_prfxpath&lt;/p&gt;
&lt;p&gt;Getting the Qt prefix can be done by inspecting QtCore's strings:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;strings /Users/myuser/homebrew/Cellar/qt/5.12.3/Frameworks/QtCore.framework/QtCore | grep qt_prfxpath
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;qt_prfxpath=/usr/local/Cellar/qt/5.12.3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok so qt_prfxpath is pointing to &lt;em&gt;&lt;em&gt;usr/local/Cellar/qt&lt;/em&gt;, while my installation's is at //Users/myuser/homebrew/Cellar/qt&lt;/em&gt;. This is problematic and indeed my fault for installing homebrew in &lt;em&gt;&lt;em&gt;Users/myuser/homebrew&lt;/em&gt; instead of the recommended //usr/local&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Symlinking did the job:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;sudo mkdir -p /usr/local/Cellar
sudo ln -s ~/homebrew/Cellar/qt /usr/local/Cellar/qt
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;/Users/myuser/homebrew/Cellar/gnuplot/5.2.6_1/libexec/gnuplot/5.2/gnuplot_qt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Success.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 13 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/installing-gnuplot-on-macos</guid></item><item><title>Links - March 13th, 2017</title><link>https://faingezicht.com/links/2017/03/13/links/</link><description/><author>Avy Faingezicht</author><pubDate>Mon, 13 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/03/13/links/</guid></item><item><title>Miscellanea</title><link>https://faingezicht.com/photos/2017/03/13/miscellanea/</link><description>Well, here's a random set of stuff. Costa Rica, San Francisco, and México.</description><author>Avy Faingezicht</author><pubDate>Mon, 13 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/03/13/miscellanea/</guid></item><item><title>Profiling and optimizing Go web applications</title><link>https://artem.krylysov.com/blog/2017/03/13/profiling-and-optimizing-go-web-applications/</link><description>&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This post was updated on 2021-04-25.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Go has a powerful built-in profiler that supports CPU, memory, goroutine and block (contention) profiling.&lt;/p&gt;
&lt;section id="enabling-the-profiler"&gt;
&lt;h3&gt;Enabling the profiler&lt;a class="headerlink" href="#enabling-the-profiler" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Go provides a low-level profiling API &lt;a class="reference external" href="https://golang.org/pkg/runtime/pprof/" target="_blank"&gt;runtime/pprof&lt;/a&gt;, but if you are developing a long-running service, it's more convenient to work with a high-level &lt;a class="reference external" href="https://golang.org/pkg/net/http/pprof/" target="_blank"&gt;net/http/pprof&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;All you need to enable the profiler is to import &lt;span class="docutils literal"&gt;net/http/pprof&lt;/span&gt; and it will automatically register the required HTTP handlers:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kn"&gt;import&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="s"&gt;&amp;quot;net/http&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;net/http/pprof&amp;quot;&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;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hiHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hi&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="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;func&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hiHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;:8080&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your web application is using a custom URL router, you'll need to register a few pprof HTTP endpoints manually:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kn"&gt;import&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="s"&gt;&amp;quot;net/http&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;net/http/pprof&amp;quot;&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;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hiHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hi&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="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;func&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;r&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hiHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Register pprof handlers&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/debug/pprof/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pprof&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/debug/pprof/cmdline&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pprof&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cmdline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/debug/pprof/profile&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pprof&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/debug/pprof/symbol&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pprof&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/debug/pprof/trace&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pprof&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;:8080&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's it, launch the application, and then use the pprof tool:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;binary&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/profile&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One of the biggest pprof advantages is that it has low overhead and can be used in a production environment on a live traffic without any noticeable performance penalties.&lt;/p&gt;
&lt;p&gt;But before digging deeper into pprof, we need a real example which can show how to identify and fix performance issues in Go.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="example-left-pad-microservice"&gt;
&lt;h3&gt;Example: Left-pad microservice&lt;a class="headerlink" href="#example-left-pad-microservice" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Assume you need to develop a brand-new microservice that adds a left padding to a given input string:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://127.0.0.1:8080/v1/leftpad/?str=test&amp;amp;len=10&amp;amp;chr=*&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;str&amp;quot;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;quot;******test&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The service needs to collect some basic metrics - the number of incoming requests and how long every request takes. All collected metrics are supposed to be sent to a metric aggregator (e.g. &lt;a class="reference external" href="https://github.com/etsy/statsd" target="_blank"&gt;StatsD&lt;/a&gt;). In addition, the service needs to log the request details - URL, IP address and user-agent.&lt;/p&gt;
&lt;p&gt;You can find the initial implementation on GitHub tagged as &lt;a class="reference external" href="https://github.com/akrylysov/goprofex/tree/v1" target="_blank"&gt;v1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Compile and run the application:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;build&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;./goprofex&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="measuring-the-performance"&gt;
&lt;h3&gt;Measuring the performance&lt;a class="headerlink" href="#measuring-the-performance" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We are going to measure how many requests per second the microservice is able to handle. This can be done using the &lt;a class="reference external" href="https://httpd.apache.org/docs/2.4/programs/ab.html" target="_blank"&gt;Apache Benchmark tool&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;ab&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://127.0.0.1:8080/v1/leftpad/?str=test&amp;amp;len=50&amp;amp;chr=*&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# -k   Enables HTTP keep-alive
# -c   Number of concurrent requests
# -n   Number of total requests to make&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not bad, but could be faster:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;Requests per second:    22810.15 [#/sec] (mean)
Time per request:       0.042 [ms] (mean, across all concurrent requests)&lt;/code&gt;&lt;/pre&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The benchmarking was performed on MacBook Pro Late 2013 (2.6 GHz Intel Core i5, 8 GB 1600 MHz DDR3, macOS 10.12.3) using Go 1.8.&lt;/p&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="cpu-profile"&gt;
&lt;h3&gt;CPU profile&lt;a class="headerlink" href="#cpu-profile" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Run the Apache benchmark tool again, but with a high number of requests (1 million should be enough) and at the same time run pprof:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/profile&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The CPU profiler runs for 30 seconds by default. It uses sampling to determine which functions spend most of the CPU time. The Go runtime stops the execution every 10 milliseconds and records the current call stack of all running goroutines.&lt;/p&gt;
&lt;p&gt;When pprof enters the interactive mode, type &lt;span class="docutils literal"&gt;top&lt;/span&gt;, the command will show a list of functions that appeared most in the collected samples. In our case these are all runtime and standard library functions, which is not very useful:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;(pprof) top
63.77s of 69.02s total (92.39%)
Dropped 331 nodes (cum &amp;lt;= 0.35s)
Showing top 10 nodes out of 78 (cum &amp;gt;= 0.64s)
      flat  flat%   sum%        cum   cum%
    50.79s 73.59% 73.59%     50.92s 73.78%  syscall.Syscall
     4.66s  6.75% 80.34%      4.66s  6.75%  runtime.kevent
     2.65s  3.84% 84.18%      2.65s  3.84%  runtime.usleep
     1.88s  2.72% 86.90%      1.88s  2.72%  runtime.freedefer
     1.31s  1.90% 88.80%      1.31s  1.90%  runtime.mach_semaphore_signal
     1.10s  1.59% 90.39%      1.10s  1.59%  runtime.mach_semaphore_wait
     0.51s  0.74% 91.13%      0.61s  0.88%  log.(*Logger).formatHeader
     0.49s  0.71% 91.84%      1.06s  1.54%  runtime.mallocgc
     0.21s   0.3% 92.15%      0.56s  0.81%  runtime.concatstrings
     0.17s  0.25% 92.39%      0.64s  0.93%  fmt.(*pp).doPrintf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a much better way to look at the high-level performance overview - &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-http&lt;/span&gt;&lt;/span&gt; flag:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;-http&lt;span class="o"&gt;=&lt;/span&gt;:8081&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/profile&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you run &lt;span class="docutils literal"&gt;pprof&lt;/span&gt; with the &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-http&lt;/span&gt;&lt;/span&gt; flag, the tool opens the profile in the web browser. The graph allows to see all hot spots:&lt;/p&gt;
&lt;img alt="" src="https://artem.krylysov.com/images/2017-goprofex/web-cpu.png" style="width: 510px;" /&gt;
&lt;p&gt;From the graph above you can see that the application spends a big chunk of CPU on logging, metric reporting and some time on garbage collection.&lt;/p&gt;
&lt;p&gt;Use &lt;span class="docutils literal"&gt;list&lt;/span&gt; to inspect every function in details, e.g. &lt;span class="docutils literal"&gt;list leftpad&lt;/span&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;(pprof) list leftpad
ROUTINE ======================== main.leftpad in /Users/artem/go/src/github.com/akrylysov/goprofex/leftpad.go
      20ms      490ms (flat, cum)  0.71% of Total
         .          .      3:func leftpad(s string, length int, char rune) string {
         .          .      4:   for len(s) &amp;lt; length {
      20ms      490ms      5:       s = string(char) + s
         .          .      6:   }
         .          .      7:   return s
         .          .      8:}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For those who are not afraid to look at the disassembled code, pprof includes &lt;span class="docutils literal"&gt;disasm&lt;/span&gt; command, which helps to see the actual processor instructions:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;(pprof) disasm leftpad
ROUTINE ======================== main.leftpad
      20ms      490ms (flat, cum)  0.71% of Total
         .          .    1312ab0: GS MOVQ GS:0x8a0, CX
         .          .    1312ab9: CMPQ 0x10(CX), SP
         .          .    1312abd: JBE 0x1312b5e
         .          .    1312ac3: SUBQ $0x48, SP
         .          .    1312ac7: MOVQ BP, 0x40(SP)
         .          .    1312acc: LEAQ 0x40(SP), BP
         .          .    1312ad1: MOVQ 0x50(SP), AX
         .          .    1312ad6: MOVQ 0x58(SP), CX
...&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="heap-profile"&gt;
&lt;h3&gt;Heap profile&lt;a class="headerlink" href="#heap-profile" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Run the heap profiler:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/heap&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default it shows the amount of memory currently in-use:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;(pprof) top
512.17kB of 512.17kB total (  100%)
Dropped 85 nodes (cum &amp;lt;= 2.56kB)
Showing top 10 nodes out of 13 (cum &amp;gt;= 512.17kB)
      flat  flat%   sum%        cum   cum%
  512.17kB   100%   100%   512.17kB   100%  runtime.mapassign
         0     0%   100%   512.17kB   100%  main.leftpadHandler
         0     0%   100%   512.17kB   100%  main.timedHandler.func1
         0     0%   100%   512.17kB   100%  net/http.(*Request).FormValue
         0     0%   100%   512.17kB   100%  net/http.(*Request).ParseForm
         0     0%   100%   512.17kB   100%  net/http.(*Request).ParseMultipartForm
         0     0%   100%   512.17kB   100%  net/http.(*ServeMux).ServeHTTP
         0     0%   100%   512.17kB   100%  net/http.(*conn).serve
         0     0%   100%   512.17kB   100%  net/http.HandlerFunc.ServeHTTP
         0     0%   100%   512.17kB   100%  net/http.serverHandler.ServeHTTP&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we are more interested in the number of allocated objects. Call pprof with &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-alloc_objects&lt;/span&gt;&lt;/span&gt; option:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;-alloc_objects&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/heap&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Almost 70% of all objects was allocated only by two functions - &lt;span class="docutils literal"&gt;leftpad&lt;/span&gt; and &lt;span class="docutils literal"&gt;StatsD.Send&lt;/span&gt;, we'll need to look at them closer:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;(pprof) top
559346486 of 633887751 total (88.24%)
Dropped 32 nodes (cum &amp;lt;= 3169438)
Showing top 10 nodes out of 46 (cum &amp;gt;= 14866706)
      flat  flat%   sum%        cum   cum%
 218124937 34.41% 34.41%  218124937 34.41%  main.leftpad
 116692715 18.41% 52.82%  218702222 34.50%  main.(*StatsD).Send
  52326692  8.25% 61.07%   57278218  9.04%  fmt.Sprintf
  39437390  6.22% 67.30%   39437390  6.22%  strconv.FormatFloat
  30689052  4.84% 72.14%   30689052  4.84%  strings.NewReplacer
  29869965  4.71% 76.85%   29968270  4.73%  net/textproto.(*Reader).ReadMIMEHeader
  20441700  3.22% 80.07%   20441700  3.22%  net/url.parseQuery
  19071266  3.01% 83.08%  374683692 59.11%  main.leftpadHandler
  17826063  2.81% 85.90%  558753994 88.15%  main.timedHandler.func1
  14866706  2.35% 88.24%   14866706  2.35%  net/http.Header.clone&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Other useful options to debug memory issues are &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-inuse_objects&lt;/span&gt;&lt;/span&gt; - displays the count of objects in-use and &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-alloc_space&lt;/span&gt;&lt;/span&gt; - shows how much memory has been allocated since the program start.&lt;/p&gt;
&lt;p&gt;Automatic memory management is convenient, but nothing is free in the world. Dynamic allocations are not only significantly slower than stack allocations but also affect the performance indirectly. Every piece of memory you allocate on the heap adds more work to the GC and makes it use more CPU resources. The only way to make the application spend less time on garbage collection is to reduce allocations.&lt;/p&gt;
&lt;section id="escape-analysis"&gt;
&lt;h4&gt;Escape analysis&lt;a class="headerlink" href="#escape-analysis" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Whenever you use the &lt;span class="docutils literal"&gt;&amp;amp;&lt;/span&gt; operator to get a pointer to a variable or allocate a new value using &lt;span class="docutils literal"&gt;make&lt;/span&gt; or &lt;span class="docutils literal"&gt;new&lt;/span&gt; it doesn't necessary mean that it's allocated on the heap.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&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="w"&gt;
      &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&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="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="kd"&gt;func&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;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the example above &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;make([]string,&lt;/span&gt; 8)&lt;/span&gt; is allocated on stack. Go uses escape analysis to determine if it's safe to allocate memory on stack instead of the heap. You can add &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-gcflags=-m&lt;/span&gt;&lt;/span&gt; option to see the results of escape analysis:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;X&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="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;9&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="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&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="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;x&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;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;X&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="mi"&gt;13&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-gcflags&lt;span class="o"&gt;=&lt;/span&gt;-m&lt;span class="w"&gt;
&lt;/span&gt;./main.go:7:&lt;span class="w"&gt; &lt;/span&gt;foo&lt;span class="w"&gt; &lt;/span&gt;x&lt;span class="w"&gt; &lt;/span&gt;does&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;escape&lt;span class="w"&gt;
&lt;/span&gt;./main.go:12:&lt;span class="w"&gt; &lt;/span&gt;main&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;X&lt;span class="w"&gt; &lt;/span&gt;literal&lt;span class="w"&gt; &lt;/span&gt;does&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;escape&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Go compiler is smart enough to turn some dynamic allocations into stack allocations. Things get worse for example when you start dealing with interfaces:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example 1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Fooer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&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;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&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="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;FooerX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FooerX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&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="w"&gt;
      &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&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="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="kd"&gt;func&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;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="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// make([]string, 8) escapes to heap&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fooer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Fooer&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nx"&gt;fooer&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;FooerX&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nx"&gt;fooer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// Example 2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&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="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stringer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&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="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;func&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;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// make([]string, 8) escapes to heap&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/view" target="_blank"&gt;Go Escape Analysis Flaws&lt;/a&gt; paper by Dmitry Vyukov describes more cases that escape analysis is unable to handle.&lt;/p&gt;
&lt;p&gt;Generally speaking, you should prefer values over pointers for small structures that you don't need to change.&lt;/p&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;For big structures, it might be cheaper to pass a pointer than to copy the whole structure and pass it by value.&lt;/p&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="goroutine-profile"&gt;
&lt;h3&gt;Goroutine profile&lt;a class="headerlink" href="#goroutine-profile" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Goroutine profile dumps the goroutine call stack and the number of running goroutines:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/goroutine&lt;/code&gt;&lt;/pre&gt;
&lt;img alt="" src="https://artem.krylysov.com/images/2017-goprofex/web-goroutine.png" style="width: 520px;" /&gt;
&lt;p&gt;There are only 18 active goroutines, which is very low. It's not uncommon to have thousands of running goroutines without significant performance degradation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-profile"&gt;
&lt;h3&gt;Block profile&lt;a class="headerlink" href="#block-profile" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Blocking profile shows function calls that led to blocking on synchronization primitives like mutexes and channels.&lt;/p&gt;
&lt;p&gt;Before running the block contention profile, you have to set a profiling rate using &lt;a class="reference external" href="https://golang.org/pkg/runtime/#SetBlockProfileRate" target="_blank"&gt;runtime.SetBlockProfileRate&lt;/a&gt;. You can add the call to your &lt;span class="docutils literal"&gt;main&lt;/span&gt; or &lt;span class="docutils literal"&gt;init&lt;/span&gt; function.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;pprof&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8080/debug/pprof/block&lt;/code&gt;&lt;/pre&gt;
&lt;img alt="" src="https://artem.krylysov.com/images/2017-goprofex/web-block.png" style="width: 224px;" /&gt;
&lt;p&gt;&lt;span class="docutils literal"&gt;timedHandler&lt;/span&gt; and &lt;span class="docutils literal"&gt;leftpadHandler&lt;/span&gt; spend a lot of time waiting on a mutex inside &lt;span class="docutils literal"&gt;log.Printf&lt;/span&gt;. It happens because &lt;span class="docutils literal"&gt;log&lt;/span&gt; package implementation uses a mutex to synchronize access to a file shared across multiple goroutines.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="benchmarking"&gt;
&lt;h3&gt;Benchmarking&lt;a class="headerlink" href="#benchmarking" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As we noticed before, the biggest offenders in terms of performance are &lt;span class="docutils literal"&gt;log&lt;/span&gt; package, &lt;span class="docutils literal"&gt;leftpad&lt;/span&gt; and &lt;span class="docutils literal"&gt;StatsD.Send&lt;/span&gt; functions. Now we found the bottleneck, but before starting to optimize the code, we need a reproducible way to measure the performance of the code we are interested in. The Go &lt;a class="reference external" href="https://golang.org/pkg/testing/" target="_blank"&gt;testing&lt;/a&gt; package includes such a mechanism. You need to create a function in the form of &lt;span class="docutils literal"&gt;func &lt;span class="pre"&gt;BenchmarkXxx(*testing.B)&lt;/span&gt;&lt;/span&gt; in a test file:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStatsD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&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="nx"&gt;statsd&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;StatsD&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;Namespace&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;namespace&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;SampleRate&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.5&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;for&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="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="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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="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;i&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="nx"&gt;statsd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;test&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="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's also possible to benchmark the whole HTTP handler using &lt;a class="reference external" href="https://golang.org/pkg/net/http/httptest/" target="_blank"&gt;net/http/httptest&lt;/a&gt; package:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BenchmarkLeftpadHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&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="nx"&gt;r&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;httptest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GET&amp;quot;&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;/v1/leftpad/?str=test&amp;amp;len=50&amp;amp;chr=*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&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="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="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="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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="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;i&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="nx"&gt;w&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;httptest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewRecorder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;leftpadHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the benchmarks:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;&lt;code&gt;go&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-bench&lt;span class="o"&gt;=&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-benchmem&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It shows the amount of time each iteration takes and the amount of memory/number of allocations:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;BenchmarkTimedHandler-4           200000          6511 ns/op        1621 B/op         41 allocs/op
BenchmarkLeftpadHandler-4         200000         10546 ns/op        3297 B/op         75 allocs/op
BenchmarkLeftpad10-4             5000000           339 ns/op          64 B/op          6 allocs/op
BenchmarkLeftpad50-4              500000          3079 ns/op        1568 B/op         46 allocs/op
BenchmarkStatsD-4                1000000          1516 ns/op         560 B/op         15 allocs/op&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="improving-the-performance"&gt;
&lt;h3&gt;Improving the performance&lt;a class="headerlink" href="#improving-the-performance" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;section id="logging"&gt;
&lt;h4&gt;Logging&lt;a class="headerlink" href="#logging" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A good but not always obvious way to make the application faster is to make it do less work. Other than for debug purposes the line &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;log.Printf(&amp;quot;%s&lt;/span&gt; request took %v&amp;quot;, name, elapsed)&lt;/span&gt; doesn't need to be in the web service. All unnecessary logs should be removed or disabled from the code before deploying it to production. This problem can be solved using a leveled logger - there are &lt;a class="reference external" href="https://github.com/avelino/awesome-go#logging" target="_blank"&gt;plenty&lt;/a&gt; of logging libraries.&lt;/p&gt;
&lt;p&gt;Another important thing about logging (and about all I/O operations in general) is to use buffered input/output when possible which can help reduce the number of system calls. Usually, there is no need to write to a file on every logger call - use &lt;a class="reference external" href="https://golang.org/pkg/bufio/" target="_blank"&gt;bufio&lt;/a&gt; package to implement buffered I/O. We can simply wrap the &lt;span class="docutils literal"&gt;io.Writer&lt;/span&gt; object that we pass to a logger with &lt;span class="docutils literal"&gt;bufio.NewWriter&lt;/span&gt; or &lt;span class="docutils literal"&gt;bufio.NewWriterSize&lt;/span&gt;:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SetOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bufio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewWriterSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="leftpad"&gt;
&lt;h4&gt;leftpad&lt;a class="headerlink" href="#leftpad" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Take a look at the &lt;span class="docutils literal"&gt;leftpad&lt;/span&gt; function again:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leftpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&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;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&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;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&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;s&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="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&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;s&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;s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Concatenating strings in a loop is not the smartest thing to do - every loop iteration allocates a new string. A better way to build a string is to use &lt;a class="reference external" href="https://golang.org/pkg/bytes/#Buffer" target="_blank"&gt;bytes.Buffer&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leftpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&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;buf&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;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Buffer&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="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="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="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;s&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="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;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteRune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&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;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, we can use &lt;a class="reference external" href="https://golang.org/pkg/strings/#Repeat" target="_blank"&gt;string.Repeat&lt;/a&gt; which makes the code slightly shorter:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leftpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&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;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&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;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;s&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;s&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;s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="statsd-client"&gt;
&lt;h4&gt;StatsD client&lt;a class="headerlink" href="#statsd-client" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The next piece of code we need to change is &lt;span class="docutils literal"&gt;StatsD.Send&lt;/span&gt; function:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;StatsD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;float64&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;buf&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;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%s.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;trimmedStat&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;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewReplacer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;:&amp;quot;&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;_&amp;quot;&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;|&amp;quot;&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;_&amp;quot;&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;&amp;#64;&amp;quot;&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;_&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;buf&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;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%s:%s|%s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trimmedStat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;kind&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="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SampleRate&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="mi"&gt;0&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="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SampleRate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;buf&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;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;|&amp;#64;%s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;strconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormatFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SampleRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;'f'&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="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="mi"&gt;64&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;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Discard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buf&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: Write to a socket&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here are some possible improvements:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="docutils literal"&gt;Sprintf&lt;/span&gt; is convenient for string formatting, and it's perfectly fine unless you start calling it thousands of times per second. It spends CPU time to parse the input format string, and it allocates a new string on every call. We can replace it with &lt;span class="docutils literal"&gt;bytes.Buffer&lt;/span&gt; + &lt;span class="docutils literal"&gt;Buffer.WriteString/Buffer.WriteByte&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The function doesn't need to create a new &lt;span class="docutils literal"&gt;Replacer&lt;/span&gt; instance every time, it can be declared as a global variable or as a part of &lt;span class="docutils literal"&gt;StatsD&lt;/span&gt; structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;span class="docutils literal"&gt;strconv.FormatFloat&lt;/span&gt; with &lt;span class="docutils literal"&gt;strconv.AppendFloat&lt;/span&gt; and pass it a buffer allocated on stack to prevent additional heap allocations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;StatsD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;float64&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;buf&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;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&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;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reservedReplacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&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;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AppendFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&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;24&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;'f'&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="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="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&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;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kind&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="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SampleRate&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="mi"&gt;0&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="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SampleRate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;|&amp;#64;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AppendFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&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;24&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SampleRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;'f'&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="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="mi"&gt;64&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;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Discard&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: Write to a socket&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That reduces the number of allocations from 14 to 1 and makes &lt;span class="docutils literal"&gt;Send&lt;/span&gt; run about 4x faster:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;BenchmarkStatsD-4                5000000           381 ns/op         112 B/op          1 allocs/op&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="measuring-the-result"&gt;
&lt;h3&gt;Measuring the result&lt;a class="headerlink" href="#measuring-the-result" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The benchmarks show a very nice performance boost after all optimizations:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;benchmark                     old ns/op     new ns/op     delta
BenchmarkTimedHandler-4       6511          1181          -81.86%
BenchmarkLeftpadHandler-4     10546         3337          -68.36%
BenchmarkLeftpad10-4          339           136           -59.88%
BenchmarkLeftpad50-4          3079          201           -93.47%
BenchmarkStatsD-4             1516          381           -74.87%

benchmark                     old allocs     new allocs     delta
BenchmarkTimedHandler-4       41             5              -87.80%
BenchmarkLeftpadHandler-4     75             18             -76.00%
BenchmarkLeftpad10-4          6              3              -50.00%
BenchmarkLeftpad50-4          46             3              -93.48%
BenchmarkStatsD-4             15             1              -93.33%

benchmark                     old bytes     new bytes     delta
BenchmarkTimedHandler-4       1621          448           -72.36%
BenchmarkLeftpadHandler-4     3297          1416          -57.05%
BenchmarkLeftpad10-4          64            24            -62.50%
BenchmarkLeftpad50-4          1568          160           -89.80%
BenchmarkStatsD-4             560           112           -80.00%&lt;/code&gt;&lt;/pre&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;I used &lt;a class="reference external" href="http://golang.org/x/perf/benchstat" target="_blank"&gt;benchstat&lt;/a&gt; to compare the results.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Run &lt;span class="docutils literal"&gt;ab&lt;/span&gt; again:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;Requests per second:    32619.54 [#/sec] (mean)
Time per request:       0.030 [ms] (mean, across all concurrent requests)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The web service can handle about 10000 additional requests per second now!&lt;/p&gt;
&lt;/section&gt;
&lt;section id="optimization-tips"&gt;
&lt;h3&gt;Optimization tips&lt;a class="headerlink" href="#optimization-tips" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Avoid unnecessary heap allocations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prefer values over pointers for not big structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preallocate maps and slices if you know the size beforehand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't log if you don't have to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use buffered I/O if you do many sequential reads or writes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your application extensively uses JSON, consider utilizing parser/serializer generators (I personally prefer &lt;a class="reference external" href="https://github.com/mailru/easyjson" target="_blank"&gt;easyjson&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Every operation matters in a hot path.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="conclusion"&gt;
&lt;h3&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes the bottleneck may be not what you are expecting - profiling is the best and sometimes the only way to understand the real performance of your application.&lt;/p&gt;
&lt;p&gt;You can find the full source code on &lt;a class="reference external" href="https://github.com/akrylysov/goprofex" target="_blank"&gt;GitHub&lt;/a&gt;. The initial version is tagged as &lt;a class="reference external" href="https://github.com/akrylysov/goprofex/tree/v1" target="_blank"&gt;v1&lt;/a&gt; and the optimized version is tagged as &lt;a class="reference external" href="https://github.com/akrylysov/goprofex/tree/v2" target="_blank"&gt;v2&lt;/a&gt;. Here is &lt;a class="reference external" href="https://github.com/akrylysov/goprofex/compare/v1...v2" target="_blank"&gt;the link&lt;/a&gt; to compare these two versions.&lt;/p&gt;
&lt;/section&gt;</description><author>Artem Krylysov</author><pubDate>Mon, 13 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://artem.krylysov.com/blog/2017/03/13/profiling-and-optimizing-go-web-applications/</guid></item><item><title>Logan</title><link>https://olshansky.info/movie/logan/</link><description>Olshansky's review of Logan</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 13 Mar 2017 01:10:25 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/logan/</guid></item><item><title>Getting started with JSONB in Postgres</title><link>/2017/03/12/getting-started-with-jsonb-in-postgres/</link><description>&lt;p&gt;JSONB is an awesome datatype in Postgres. I find myself using it on a weekly basis these days. Often in using some API (such as &lt;a href="https://www.clearbit.com"&gt;clearbit&lt;/a&gt;) I&amp;rsquo;ll get a JSON response back, instead of parsing that out into a table structure it&amp;rsquo;s really easy to throw it into a JSONB then query for various parts of it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re not familiar with JSONB, it&amp;rsquo;s a binary representation of JSON in your database. You can read a bit more about it vs. JSON &lt;a href="https://www.citusdata.com/blog/2016/07/14/choosing-nosql-hstore-json-jsonb/"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In working with JSONB here&amp;rsquo;s a few quick tips to get up and running with it even faster:&lt;/p&gt;
&lt;h3 id="indexing"&gt;
&lt;div&gt;
Indexing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;For the most part you don&amp;rsquo;t have to think to much about this. With Postgres powerful indexing types you can add one index and have everything within the JSON document, all the keys and all the values, automatically indexed. The key here is to add a &lt;code&gt;GIN&lt;/code&gt; index. Once this is done queries should be much faster where you&amp;rsquo;re searching for some value:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;CREATE&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;INDEX&lt;/span&gt; idx_data &lt;span style="color: #66d9ef;"&gt;ON&lt;/span&gt; companies &lt;span style="color: #66d9ef;"&gt;USING&lt;/span&gt; GIN (&lt;span style="color: #66d9ef;"&gt;data&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="querying"&gt;
&lt;div&gt;
Querying
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Querying is a little bit more work, but once you get the basics it can be pretty straight forward. There&amp;rsquo;s a few new operators you&amp;rsquo;ll want to quickly ramp up on and from there querying becomes easy.&lt;/p&gt;
&lt;p&gt;For the most basic part you now have an operator so traverse down the various keys. First let&amp;rsquo;s get some idea of what the JSON looks like so we can have something to work with. Here&amp;rsquo;s a sample set of data that we get back from Clearbit:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{
"domain": "citusdata.com",
"company": {
"id": "b1ff2bdf-0d8d-4d6d-8bcc-313f6d45996a",
"url": "http:\/\/citusdata.com",
"logo": "https:\/\/logo.clearbit.com\/citusdata.com",
"name": "Citus Data",
"site": {
"h1": null,
"url": "http:\/\/citusdata.com",
"title": "Citus Data",
},
"tags": [
"SAAS",
"Enterprise",
"B2B",
"Information Technology &amp;amp; Services",
"Technology",
"Software"
],
"domain": "citusdata.com",
"twitter": {
"id": "304455171",
"bio": "Builders of Citus, the extremely scalable PostgreSQL database.",
"site": "https:\/\/t.co\/hKpZjIy7Ej",
"avatar": "https:\/\/pbs.twimg.com\/profile_images\/630900468995108865\/GJFCCXrv_normal.png",
"handle": "citusdata",
"location": "San Francisco, CA",
"followers": 3770,
"following": 570
},
"category": {
"sector": "Information Technology",
"industry": "Internet Software &amp;amp; Services",
"subIndustry": "Internet Software &amp;amp; Services",
"industryGroup": "Software &amp;amp; Services"
},
"emailProvider": false
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sorry it&amp;rsquo;s a bit long, but it gives us a good example to work with.&lt;/p&gt;
&lt;h3 id="basic-lookups"&gt;
&lt;div&gt;
Basic lookups
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s query something fairly basic, the domain:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;#&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;data&lt;/span&gt;&lt;span style="color: #f92672;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'domain'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; companies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;WHERE&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;domain&lt;/span&gt;&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'citusdata.com'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;LIMIT&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #f92672;"&gt;?&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;column&lt;/span&gt;&lt;span style="color: #f92672;"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;-----------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;"citusdata.com"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;-&amp;gt;&lt;/code&gt; is likely the first operator you&amp;rsquo;ll use in JSONB. It&amp;rsquo;s helpful to traverse the JSON. Though of you&amp;rsquo;re looking to get the value as text you&amp;rsquo;ll actually want to use &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt;. Instead of giving you some quoted response back or JSON object you&amp;rsquo;re going to get it as text which will be a bit cleaner:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;#&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;data&lt;/span&gt;&lt;span style="color: #f92672;"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'domain'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; companies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;WHERE&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;domain&lt;/span&gt;&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'citusdata.com'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;LIMIT&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #f92672;"&gt;?&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;column&lt;/span&gt;&lt;span style="color: #f92672;"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;-----------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt; citusdata.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="filtering-for-values"&gt;
&lt;div&gt;
Filtering for values
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Now with something like clearbit you may want to filter out for only certain type of companies. We can see in the example data that there&amp;rsquo;s a bunch of tags. If we wanted to find only companies that had the tag B2B we could use the &lt;code&gt;?&lt;/code&gt; operator once we&amp;rsquo;ve targetted down to that part of the JSON. The &lt;code&gt;?&lt;/code&gt; operator will tell us if some part of JSON has a top level key:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #f92672;"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; companies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;WHERE&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;data&lt;/span&gt;&lt;span style="color: #f92672;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'company'&lt;/span&gt;&lt;span style="color: #f92672;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'tags'&lt;/span&gt; &lt;span style="color: #f92672;"&gt;?&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;'B2B'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="jsonb-but-pretty"&gt;
&lt;div&gt;
JSONB but pretty
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;In querying JSONB you&amp;rsquo;ll typically get a nice compressed set of JSON back. While this is all fine if you&amp;rsquo;re putting it into your application, if you&amp;rsquo;re manually debugging and testing things you probably want something a bit more readable. Of course Postgres has your back here and you can wrap your JSONB with a pretty print function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; jsonb_pretty(&lt;span style="color: #66d9ef;"&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; companies;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="much-more"&gt;
&lt;div&gt;
Much more
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a lot more in the &lt;a href="https://www.postgresql.org/docs/9.5/static/functions-json.html"&gt;docs&lt;/a&gt; that you can find handy for the specialized cases when you need them. &lt;code&gt;jsonb_each&lt;/code&gt; will expand a JSONB document into individual rows. So if you wanted to count the number of occurences of every tag for a company, this would help. Want to parse out a JSONB to a row/record in Postgres there&amp;rsquo;s &lt;code&gt;jsonb_to_record&lt;/code&gt;. The docs are your friends for about everything you want to do but hopefully these few steps help kick start things if you want to get started with &lt;code&gt;JSONB&lt;/code&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 12 Mar 2017 22:55:56 GMT</pubDate><guid isPermaLink="true">/2017/03/12/getting-started-with-jsonb-in-postgres/</guid></item><item><title>Becoming Warren Buffett</title><link>https://olshansky.info/movie/becoming_warren_buffett/</link><description>Olshansky's review of Becoming Warren Buffett</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 12 Mar 2017 16:21:08 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/becoming_warren_buffett/</guid></item><item><title>After Yahoo, it's Amazon's turn to show why a percloud is needed</title><link>https://stop.zona-m.net/2017/03/after-yahoo-its-amazons-turn-to-show-why-a-percloud-is-needed/</link><description>On February 28th, 2017, a &amp;ldquo;cockup at Amazon facility in Virginia, US&amp;rdquo; caused its S3 cloud storage to fail.
  This fault led to &amp;ldquo;major websites and services - including Imgur, Medium, Trello, Yahoo webmail, the Docker Registry Hub.. falling offline, losing images, or left running like treacle. Basically, that outage &amp;ldquo;knackered half the internet, it seems, because it all relies on S3 to store data online&amp;rdquo;.
Just to stress: this is one S3 region that has become inaccessible, yet web apps are tripping up and vanishing as their backend evaporates away.</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 12 Mar 2017 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/03/after-yahoo-its-amazons-turn-to-show-why-a-percloud-is-needed/</guid></item><item><title>Unity Fireworks</title><link>https://www.swilliams.io/w/unity-fireworks</link><description>&lt;p&gt;In the March Southampton Code Dojo, I was tasked with creating fireworks within the 2 hour time limit and, for a change from seeing the usual JavaScript or
    Python entries, I decided to do this using Unity.&lt;/p&gt;
&lt;p&gt;The scene consists of a fireworks spawner game object which randomly instantiates firework rockets around itself which move upwards and, after a random
    amount of time, explode. The firework sparkles explode outwards by the physics collision engine doing its thing since they are all spawned roughly in the
    same place. Against a backdrop of a night sky, the effect is decent.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src="fireworks.png" href="fireworks.png" alt="Fireworks implemented in Unity." style="height:250px;width:500px;"&gt;
    &lt;figcaption&gt;Fireworks implemented in Unity!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Obviously, since everything is a cube, this Unity scene requires a small amount of artisitic license.&lt;/p&gt;
&lt;h2&gt;See also&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a name="fn-2" href="https://github.com/s-williams/Fireworks"&gt;Link to the Github repository.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>SWilliams.io</author><pubDate>Sun, 12 Mar 2017 03:01:01 GMT</pubDate><guid isPermaLink="true">https://www.swilliams.io/w/unity-fireworks</guid></item><item><title>Links - March 12th, 2017</title><link>https://faingezicht.com/links/2017/03/12/links/</link><description>This post has been sitting half-baked on my draft list for far too long. In an effort to motivate myself, and to write more, I decided to post it as is and move on. My apologies to the authors of the uncommented links.</description><author>Avy Faingezicht</author><pubDate>Sun, 12 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/03/12/links/</guid></item><item><title>I'm Joining SalesLoft</title><link>https://solomon.io/im-joining-salesloft/</link><description>Some of you already know, but Monday I’m joining SalesLoft as a product designer. From this point forward I will no longer be contributing to Trustfuel.</description><author>Sam Solomon</author><pubDate>Sun, 12 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/im-joining-salesloft/</guid></item><item><title>What the CIA director forgot to say about millennials</title><link>https://stop.zona-m.net/2017/03/what-the-cia-director-forgot-to-say-about-millennials/</link><description>Former CIA director Michael Hayden recently said that millennials may leak secrets because they are &amp;ldquo;culturally different&amp;rdquo;. OK but.. please let me point out some of the culprits for such a difference, and the fact that those same culprits had been clearly named and described more than three years ago.
Mr. Hayden said that millennials have different instincts than the people who hired them and this cultural difference may be the reason why &amp;ldquo;millennials leak secrets&amp;rdquo;:</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 11 Mar 2017 16:10:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/03/what-the-cia-director-forgot-to-say-about-millennials/</guid></item><item><title>Benchmarking ScyllaDB</title><link>https://michael.mior.ca/blog/scylladb-benchmarks/</link><description>&lt;p&gt;&lt;a href="http://www.scylladb.com/"&gt;ScyllaDB&lt;/a&gt; is an alternative to &lt;a href="https://cassandra.apache.org/"&gt;Apache Cassandra&lt;/a&gt; which claims to have 10x higher throughput than Cassandra while remaining the same positive properties of scalability and ease of use.
Scylla functions as a drop-in replacement for Cassandra applications using &lt;a href="https://docs.datastax.com/en/cql/3.1/index.html"&gt;CQL&lt;/a&gt; (currently with some &lt;a href="http://www.scylladb.com/technology/status/"&gt;disparity in features&lt;/a&gt;).
Fortunately, my &lt;a href="https://michael.mior.ca/projects/NoSE/"&gt;past work&lt;/a&gt; in NoSQL schema design for Cassandra only makes use of features supported by Scylla.&lt;/p&gt;
&lt;p&gt;I’ve been meaning to do my own tests on Scylla for a while, but recently &lt;a href="https://cs.uwaterloo.ca/~jimmylin/"&gt;a faculty member&lt;/a&gt; shared about Scylla on our group’s Slack channel and suggested I share some results.
I decided to run the same set of experiments I used to evaluate a schema I designed for the &lt;a href="http://rubis.ow2.org/"&gt;RUBiS&lt;/a&gt; online auction benchmark.
First, several column families are created and loaded with data.
Next, the different types of transactions in the RUBiS benchmark are executed while measuring the response time.
Before I continue, first a disclaimer that the methodology behind the results is not as rigorous as it could be, but still leaves me skeptical of some of the claims made by Scylla.&lt;/p&gt;
&lt;p&gt;These experiments were run using single node installations of Cassandra 3.0.9 and Scylla 1.6.1.
While this is not a typical setup, much of the reasons for performance improvements claimed by Scylla (e.g. lock-free data structures and improved memory management) should still manifest themselves on a single node.
One of the nice things about Scylla is the &lt;code&gt;scylla_setup&lt;/code&gt; command that attempts to configure the OS for optimal performance including benchmarking the disk storing the data directory.
This configuration was used for both Scylla and Cassandra and otherwise the default settings were used for both systems.&lt;/p&gt;
&lt;p&gt;The first striking difference is that the on-disk size of the data for Scylla (9.8 GB) is nearly twice that of Cassandra (5.2 GB).
Despite this, there was not a large difference in load times with Cassandra taking 3 hours 43 minutes and Scylla taking 3 hours 59 minutes.
Below is a graph with the write throughput of the SSD storing the data files in each case.
Scylla seems to push the drive much harder but it’s able to keep up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: After looking at the number of keys in each table for both Scylla and Cassandra, it seems as though Scylla was storing significantly more data. Repeating the experiment seems to have resolved this issue with no significant impact on performance.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Write throughput while loading" src="/blog/scylladb-benchmarks/write-throughput.png" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, the results of running the actual benchmark.
RUBiS consists of a number of “interactions” which corresponds to user requests for web pages.
The graph below shows the top eight interactions by frequency and the average response times for both Cassandra and Scylla.
I won’t go into a detailed analysis here, but the performance claims made by Scylla don’t seem to play out here.&lt;/p&gt;
&lt;p&gt;&lt;img alt="RUBiS benchmark comparison" src="/blog/scylladb-benchmarks/compare.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: A discussion with the CEO of Scylla suggests that Scylla &lt;del&gt;is primarily optimized for throughput and&lt;/del&gt; isn’t likely to show much improvement in the case of this benchmark which is single-threaded and focused on latency. Rerunning the same experiment concurrently with 10 threads doesn’t show significant changes. However, I wasn’t measuring the load on the system during these experiments and I can imagine that performance improvements would start to manifest as the system becomes more heavily loaded. Excited to see the continued work of the Scylla team!&lt;/p&gt;</description><author>Michael Mior</author><pubDate>Sat, 11 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://michael.mior.ca/blog/scylladb-benchmarks/</guid></item><item><title>Deploying FreeBSD on Linode unattended in minutes</title><link>http://notes.eatonphil.com/deploying-freebsd-on-linode-unattended-in-minutes.html</link><description>&lt;p&gt;I became a FreeBSD user over 2 years ago when I wanted to see what all
the fuss was about. I swapped my y410p dual-booting Windows / Ubuntu
with FreeBSD running Gnome 3. I learned a lot during the transition
and came to appreciate FreeBSD as a user. I soon began running FreeBSD
as my OS of choice on cloud servers I managed. So naturally, when I
started working at Linode a year ago I wanted to run FreeBSD servers
on Linode too.&lt;/p&gt;
&lt;p&gt;Linode is a great platform for running random unofficial images
because you have much control over the configuration. I followed
&lt;a href="https://www.linode.com/docs/tools-reference/custom-kernels-distros/install-freebsd-on-linode/"&gt;existing&lt;/a&gt; &lt;a href="https://forum.linode.com/viewtopic.php?f=20&amp;amp;t=12080"&gt;guides&lt;/a&gt; closely and was soon able to get a number of
operating systems running on Linodes by installing them manually:
FreeBSD, OpenBSD, NetBSD, Minix3, and SmartOS to date.&lt;/p&gt;
&lt;p&gt;Unofficial images come at a cost though. In particular, I became
frustrated having to reinstall using the installer every time I
managed to trash the disk. So over the past year, I spent time trying
to understand the automated installation processes across different
operating systems and Linux distributions.&lt;/p&gt;
&lt;p&gt;Unattended installations are tough. The methods for doing them differ
wildly. On RedHat, Fedora, and CentOS there is &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/installation_guide/ch-kickstart2"&gt;Kickstart&lt;/a&gt;. On
Debian and Ubuntu there is &lt;a href="https://wiki.debian.org/DebianInstaller/Preseed"&gt;preseeding&lt;/a&gt;. Gentoo, Arch, and FreeBSD
don't particularly have a framework for unattended installs, but the
entire installation process is well-documented and inherently
scriptable (if you put in the effort). OpenBSD has
&lt;a href="http://man.openbsd.org/OpenBSD-6.0/man8/autoinstall.8"&gt;autoinstall&lt;/a&gt;. Trying to understand each and every one of these
potential installation methods was pretty defeating for getting
started on a side-project.&lt;/p&gt;
&lt;p&gt;A few weeks ago, I finally had the silly revelation that I didn't need
to script the installation process -- at least initially. I only had
to have working images available somewhere that could be copied to new
Linodes. Some OSs / distributions may provide these images, but there
is no guarantee that they exist or work. If I tested and hosted them
for Linodes, anyone could easily run their own copy.&lt;/p&gt;
&lt;p&gt;I began by running the installation process as normal for
FreeBSD. After the disk had FreeBSD installed on it, I rebooted into
&lt;a href="https://www.linode.com/docs/troubleshooting/rescue-and-rebuild/"&gt;Finnix&lt;/a&gt;, &lt;a href="https://wiki.archlinux.org/index.php/disk_cloning#Create_disk_image"&gt;made a compressed disk image&lt;/a&gt;, and transferred it to
an "image host" (another Linode in Fremont running an FTP
server). Then I tested the reversal process manually to make sure a
new Linode could grab the image, dd it to a disk, reboot and have a
working filesystem and networking. (This transfer occurs over private
networking to reduce bandwidth costs and thus limits Linode creation
to the datacenter of the image host, Fremont.)&lt;/p&gt;
&lt;p&gt;Then it was time to script the process. I looked into the existing
Linode API client wrappers and noticed none of them were
documented. So I took a day to write and document a good part of a
&lt;a href="https://github.com/eatonphil/python3-linode_api3"&gt;new Linode Python client&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I got to work and out came the &lt;a href="https://github.com/eatonphil/linode_deploy_experimental"&gt;linode-deploy-experimental&lt;/a&gt;
script. To run this script, you'll need an &lt;a href="https://www.linode.com/docs/platform/api/api-key/"&gt;API token&lt;/a&gt;. This
script will allow you to deploy from the hosted images (which now
include FreeBSD 11.0 and OpenBSD 6.0). Follow the example line in the
git repo and you'll have a Linode running OpenBSD or FreeBSD in
minutes.&lt;/p&gt;
&lt;p&gt;Clearly there's a lot of work to do on both this script and on the
images:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fremont datacenter has the only image host.&lt;/li&gt;
&lt;li&gt;The script does not change the default password: "password123".
You'll want to change this immediately.&lt;/li&gt;
&lt;li&gt;The script does not automatically grow the file system after
install.&lt;/li&gt;
&lt;li&gt;The TTY config for these images currently requires you to use
Glish instead of Weblish.&lt;/li&gt;
&lt;li&gt;And &lt;a href="https://github.com/eatonphil/linode_deploy_experimental/issues"&gt;more&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if many of these issues do get sorted out (I assume they will),
keep in mind that these are unofficial, unsupported images. Some
things will probably never work: backups, password reset, etc. If you
need help, you are probably limited to community support. You can also
find me with any questions (peaton on OFTC). But for me this is at
least a slight improvement on having to run through the install
process every time I need a new FreeBSD Linode.&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Deploy FreeBSD and OpenBSD unattended on Linode &lt;a href="https://t.co/j5A46ROqNM"&gt;https://t.co/j5A46ROqNM&lt;/a&gt; &lt;a href="https://t.co/HSqrIvBMFj"&gt;https://t.co/HSqrIvBMFj&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/840736360864591872?ref_src=twsrc%5Etfw"&gt;March 12, 2017&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 11 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/deploying-freebsd-on-linode-unattended-in-minutes.html</guid></item><item><title>Dealing with Passwords</title><link>https://www.mikekasberg.com/blog/2017/03/10/dealing-with-passwords.html</link><description>&lt;p&gt;Jeff Atwood wrote a
&lt;a href="https://blog.codinghorror.com/password-rules-are-bullshit/"&gt;post&lt;/a&gt; on Coding
Horror today calling out bullshit password rules. And he’s dead on. Password
rules, as most sites implement them today, are &lt;strong&gt;not&lt;/strong&gt; improving security. They
might actually be hurting it. Even
&lt;a href="https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/"&gt;NIST&lt;/a&gt;
agrees.&lt;/p&gt;

&lt;p&gt;Personally, I agree with everything Jeff says. He makes several really
well-researched points. But there’s one particular topic he did &lt;em&gt;not&lt;/em&gt;
mention that I want to bring to attention. &lt;strong&gt;Password expiration is bad&lt;/strong&gt; (within
reason). I’ve heard of (and, unfortunately, used) services that expire passwords
as frequently as every 3 months. That’s just stupid. Seriously. Sometimes I
don’t even visit a website that frequently! Why does it need to expire that
soon? What, they store their passwords in MD5 and expect to be hacked 4 times a
year? There’s no reason to expire passwords that frequently. Moreover, it’s
actually harmful - what do most people do when their password expires so often
they can’t remember it? &lt;em&gt;They write it down on a sticky note next to their
monitor.&lt;/em&gt; Yeah, real secure.&lt;/p&gt;

&lt;p&gt;Really, the only time a user should &lt;em&gt;need&lt;/em&gt; to change their password is if a
website is hacked and a database is compromised. If your database hasn’t been
compromised and you make your users change their password on a regular time
interval, you’re providing a bad user experience with no real benefit for your
users.&lt;/p&gt;

&lt;p&gt;OK. Now that that’s off my chest, let’s talk about solutions. As a user of
websites with vastly different password rules, your options are somewhat limited
and they kind of suck.&lt;/p&gt;

&lt;div class="warning"&gt;
&lt;p&gt;&lt;b&gt;July 2020 Update&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I originally wrote this blog post back in 2017! I've left most of it as it
was originally written because it's still accurate, but my personal views on
password managers have evolved a bit since I wrote this. I'd now highly
recommend using &lt;a href="https://bitwarden.com/"&gt;Bitwarden&lt;/a&gt; to manage your
passwords.  Read about why in my posts &lt;a href="https://www.mikekasberg.com/blog/2017/03/25/how-i-manage-passwords-with-keepass.html"&gt;here&lt;/a&gt; and &lt;a href="https://www.mikekasberg.com/blog/2018/11/20/keepass-vs-bitwarden.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id="what-makes-a-password-secure"&gt;What Makes a Password Secure?&lt;/h2&gt;

&lt;h3 id="length"&gt;Length&lt;/h3&gt;

&lt;p&gt;As it turns out, password length is probably the biggest factor in making your
password more secure. &lt;a href="https://blog.codinghorror.com/password-rules-are-bullshit/"&gt;Jeff’s post&lt;/a&gt; has
all the data to back this up. Today, lots of computing power is easily available
with things like Amazon EC2 and GPU parallel processing. Passwords around 8
characters in length can be cracked in minutes. &lt;em&gt;The best weapon against
these attacks is password length&lt;/em&gt; because each additional character increases
the number of possible passwords &lt;em&gt;exponentially&lt;/em&gt;. A “secure” password would be
roughly 14 characters or longer.&lt;/p&gt;

&lt;h3 id="dont-use-stupid-passwords"&gt;Don’t Use Stupid Passwords&lt;/h3&gt;

&lt;p&gt;Password dumps &lt;a href="https://wiki.skullsecurity.org/Passwords"&gt;exist&lt;/a&gt; on the
internet. If the password you’re using exists in one of these dumps (even on
someone else’s account), it’s not secure. As you might imagine, that means you
can’t use simple words, “123456”, or anything like that.&lt;/p&gt;

&lt;h3 id="different-passwords-on-different-sites"&gt;Different Passwords on Different Sites&lt;/h3&gt;

&lt;p&gt;You’ve probably heard it before. Don’t use the same password for your email
account that you use for your bank account. Websites get broken into
&lt;a href="https://en.wikipedia.org/wiki/Cloudbleed"&gt;all&lt;/a&gt;
&lt;a href="https://en.wikipedia.org/wiki/2012_LinkedIn_hack"&gt;the&lt;/a&gt;
&lt;a href="https://www.theguardian.com/technology/2016/aug/31/dropbox-hack-passwords-68m-data-breach"&gt;time&lt;/a&gt;.
If you use the same password on every website, a hack on any of the websites you
visit becomes a hack on all the websites you visit. If you use a different
password for each website, you limit your exposure in case any of the websites
you use gets compromised.&lt;/p&gt;

&lt;h3 id="multi-factor-authentication"&gt;Multi-Factor Authentication&lt;/h3&gt;

&lt;p&gt;Where it’s offered, &lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"&gt;multi-factor
authentication&lt;/a&gt; can
provide better security than a password alone. Multi-factor authentication fixes
many of the problems with passwords. Accounts protected with multi-factor
authentication are likely to be difficult to compromise even if the password
protecting them is weak.&lt;/p&gt;

&lt;h2 id="what-are-the-options"&gt;What are the Options&lt;/h2&gt;

&lt;p&gt;As a user, it’s hard to use good passwords. Passwords (or even password
algorithms) that work on one site often won’t work on another. Websites make you
change your password at random intervals. It can all be very not-user-friendly.
Here are some strategies that can help.&lt;/p&gt;

&lt;h3 id="use-single-sign-on"&gt;Use Single Sign-On&lt;/h3&gt;

&lt;p&gt;Many websites are allowing their users to sign in using a Google or Facebook
account. Where it’s available, I think this is a great option. I’m usually
already logged in to my Google account anyway. And I trust Google to do a better
job verifying my identity than most other websites. If other websites can use
Google to verify my identity, that’s one less password I need to manage.&lt;/p&gt;

&lt;h3 id="use-a-password-manager"&gt;Use a Password Manager&lt;/h3&gt;

&lt;p&gt;A password manager like &lt;a href="https://bitwarden.com"&gt;Bitwarden&lt;/a&gt;,
&lt;a href="https://1password.com/"&gt;1Password&lt;/a&gt;, &lt;a href="https://www.lastpass.com/"&gt;LastPass&lt;/a&gt;,
&lt;a href="https://www.passwordstore.org/"&gt;Pass&lt;/a&gt;, or even
&lt;a href="https://passwords.google.com"&gt;Google&lt;/a&gt; can remember your passwords for you. Good
ones will generate new randomized passwords for you when you sign up to new
websites. Many people find this option attractive. Personally, I’m hesitant to
use a password manager. Mainly because I don’t want to have to rely on it to be
able to log in to all my other websites. And because I don’t like the idea of
having all my passwords in one place if that service were to be hacked. But
perhaps this &lt;em&gt;is&lt;/em&gt; the way of the future - maybe I need to get over it.&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;2020 Update:&lt;/strong&gt; I did get over it. Despite all the advantages of password
algorithms, which I describe below, they have many disadvantages too.
They break on sites that require you to change your password frequently
or that disallow special characters. I’ve been using
&lt;a href="https://bitwarden.com"&gt;Bitwarden&lt;/a&gt; for well over a year now. It’s unobtrusive,
open-source, and the code’s been audited. Read more about my new thinking
&lt;a href="https://www.mikekasberg.com/blog/2017/03/25/how-i-manage-passwords-with-keepass.html"&gt;here&lt;/a&gt; and
&lt;a href="https://www.mikekasberg.com/blog/2018/11/20/keepass-vs-bitwarden.html"&gt;here&lt;/a&gt;.)&lt;/p&gt;

&lt;h3 id="use-a-password-algorithm"&gt;Use a Password Algorithm&lt;/h3&gt;

&lt;p&gt;I’ve been using this trick for a while on some websites. It solves the problem
of using a different password on different websites without having to remember a
large number of different passwords (and without using a password manager). It
works like this: Start with a “base” password. For example, &lt;code class="language-plaintext highlighter-rouge"&gt;ILikeDoughnuts&lt;/code&gt;.
Then, add something about the name of the website you’re logging in to. If
you’re logging into your bank, you might use &lt;code class="language-plaintext highlighter-rouge"&gt;BILikeDoughnutsank&lt;/code&gt;, combining the
works &lt;code class="language-plaintext highlighter-rouge"&gt;Bank&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;ILikeDoughnuts&lt;/code&gt; to form your password. Now you’ve got a
different password for each site, but you only have to remember one algorithm.&lt;/p&gt;

&lt;h2 id="wrapping-up"&gt;Wrapping Up&lt;/h2&gt;

&lt;p&gt;Unfortunately, passwords are in some ways a necessary evil. Something that isn’t
ideal but something we have to deal with. Understanding the different approaches
to dealing with them and the trade-offs between the approaches is really
important.&lt;/p&gt;

&lt;p&gt;What password strategies do you use? How can software developers make the login
experience more user-friendly?&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Fri, 10 Mar 2017 20:08:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/03/10/dealing-with-passwords.html</guid></item><item><title>Higher-order reactive graph programming</title><link>https://mattkeeter.com/blog/2017-03-10-higher</link><description/><author>Matt Keeter</author><pubDate>Fri, 10 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2017-03-10-higher</guid></item><item><title>A Case Against Misinterpretations</title><link>https://venam.net/blog/psychology/2017/03/10/a-case-against-misunderstanding.html</link><description>It has become rampant nowadays to find many persons misinterpreting or skewing evolutionary psychology studies to praise or blame the stance they fancy or despise. The slants are non-sense and blot this relatively new field of social science by conflating it with bigotry and excruciatingly non-scientific arguments.  Many of the pernicious individuals that advance them are confabulating and fabricating ideas to fit their world view. Their truculent piffles are due to multiple complex misunderstandings and internal fears.  One of them relates to a common confusion about the definition of the term "scientific theory". A so common confusion that it has become an adage that the ignoramus abuses to spurt out, officiously, blatantly wrong statements.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Fri, 10 Mar 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2017/03/10/a-case-against-misunderstanding.html</guid></item><item><title>Being a tech lead, the thing I miss the most</title><link>https://muffinman.io/blog/being-a-tech-lead/</link><description>&lt;article class="article"&gt;&lt;p&gt;I started leading teams relatively early in my career.
Mentoring and leading younger developers is something I tremendously enjoy.
But there is one thing I really miss about being a &amp;quot;regular&amp;quot; developer.&lt;/p&gt;
&lt;p&gt;And that is - being able to put my headphones, play some rock &amp;#x27;n roll,
and code for a couple of hours without any distractions.&lt;/p&gt;
&lt;p&gt;Something that is almost impossible today. I&amp;#x27;m not complaining,
but the truth is that I really miss it.
Luckily, I can fulfill my geek needs working on pet projects.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Thu, 09 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/being-a-tech-lead/</guid></item><item><title>The Americans: Season 1</title><link>https://olshansky.info/tv/the_americans_season_1/</link><description>Olshansky's review of The Americans: Season 1</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 08 Mar 2017 15:26:08 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/the_americans_season_1/</guid></item><item><title>Misusing error interface</title><link>https://divan.dev/posts/misusing_error_interface/</link><description>&lt;p&gt;I used to think that misunderstanding interfaces in Go can lead, at most, to not very readable code and worse maintainability. From my observations misusing interfaces becomes visible usually during refactorings, where you questioning what this type or abstraction actually represents. But, at least, the code tends to work and it&amp;rsquo;s not buggy.&lt;/p&gt;
&lt;h1 id="the-bug"&gt;The bug&lt;/h1&gt;
&lt;p&gt;But here is the interesting piece of code that actually was buggy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-go"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #a6e22e;"&gt;err&lt;/span&gt; &lt;span style="color: #f92672;"&gt;:=&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;SomeFunc&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;if&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;_&lt;/span&gt;, &lt;span style="color: #a6e22e;"&gt;ok&lt;/span&gt; &lt;span style="color: #f92672;"&gt;:=&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;err&lt;/span&gt;.(&lt;span style="color: #a6e22e;"&gt;MyError&lt;/span&gt;); !&lt;span style="color: #a6e22e;"&gt;ok&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #a6e22e;"&gt;log&lt;/span&gt;.&lt;span style="color: #a6e22e;"&gt;Println&lt;/span&gt;(&lt;span style="color: #a6e22e;"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Quite idiomatic, right?  Error type naming is good, following &lt;a href="https://github.com/golang/go/wiki/Errors#naming"&gt;recommended way to name error types and variables&lt;/a&gt;.  We use here normal &lt;a href="https://golang.org/doc/effective_go.html#interface_conversions"&gt;type assertion&lt;/a&gt;, &amp;ldquo;extracting&amp;rdquo; underlying static type from an interface. If an error doesn&amp;rsquo;t have this type inside, we should log it.&lt;/p&gt;</description><author>divan's blog</author><pubDate>Wed, 08 Mar 2017 13:07:40 GMT</pubDate><guid isPermaLink="true">https://divan.dev/posts/misusing_error_interface/</guid></item><item><title>Python support in Visual Studio 2017 or the lack thereof</title><link>https://nicolaiarocci.com/python-support-in-visual-studio-2017-or-the-lack-thereof/</link><description>&lt;p&gt;So yesterday Visual Studio 2017 was released. Big news. Lots of &lt;a href="https://www.visualstudio.com/vs/whatsnew/"&gt;cool
stuff&lt;/a&gt;. As I write this I am watching the &lt;a href="https://launch.visualstudio.com"&gt;live stream&lt;/a&gt; of the
2 days-long launch event. If you want to learn about Python support in VS2017
though, you have to dig deeper and head over to the &lt;a href="https://blogs.msdn.microsoft.com/pythonengineering/2017/03/07/python-support-in-vs2017/"&gt;Python Engineering&lt;/a&gt;
blog at Microsoft.&lt;/p&gt;
&lt;p&gt;As &lt;a href="https://nicolaiarocci.com/python-workload-pulled-off-visual-studio-2017-rc3/"&gt;expected&lt;/a&gt;, the official release is actually coming out with no support for
Python. It will come in a few months. Bummer. In the meanwhile however you can go and grab the
(also newly released) &lt;a href="https://visualstudio.com/vs/preview?wt.mc_id=blogs_msdn_python"&gt;Visual Studio Preview&lt;/a&gt;. This new kid on the block
has the ability to be installed and used side-by-side with the official release
and will be used - you guessed it - as an early preview of what’s coming next for Visual Studio.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Wed, 08 Mar 2017 11:41:17 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/python-support-in-visual-studio-2017-or-the-lack-thereof/</guid></item><item><title>The building blocks of React Native animations</title><link>https://goshacmd.com/react-native-animated-building-blocks/</link><author>Gosha Spark</author><pubDate>Wed, 08 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/react-native-animated-building-blocks/</guid></item><item><title>A Different Man</title><link>https://honestmusings.wordpress.com/2017/03/07/a-different-man/</link><description>Once there was a God, And once there was a fire, God looked upon the fire, Burning and searing, And then there was a Man, who yelped, &amp;#8220;O God! Help! There is a fire! God cried, &amp;#8220;Let there be water&amp;#8221;, He said, And Man received water, But the man complained, &amp;#8220;O Lord, you are merciful,&amp;#8221; &amp;#8230; &lt;a class="more-link" href="https://honestmusings.wordpress.com/2017/03/07/a-different-man/"&gt;Continue reading &lt;span class="screen-reader-text"&gt;A Different Man&lt;/span&gt;&lt;/a&gt;</description><author>Honest Musings</author><pubDate>Tue, 07 Mar 2017 19:43:57 GMT</pubDate><guid isPermaLink="true">https://honestmusings.wordpress.com/2017/03/07/a-different-man/</guid></item><item><title>Inner Workings</title><link>https://blog.yiningkarlli.com/2017/03/inner-workings.html</link><description>&lt;div style="display: none;"&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;

&lt;div class="tableofcontents"&gt;
    &lt;div class="tableofcontents-row"&gt;
        &lt;div class="tableofcontents-column3"&gt;
            &lt;div class="tableofcontents-content"&gt;
                1. &lt;a href="/2016/02/zootopia.html#2017-03-07-notes"&gt;Making Inner Workings&lt;/a&gt;&lt;br /&gt;
                2. &lt;a href="/2016/02/zootopia.html#2017-03-07-frames"&gt;Frames from the Short&lt;/a&gt;&lt;br /&gt;
                3. &lt;a href="/2016/02/zootopia.html#2017-03-07-references"&gt;References&lt;/a&gt;&lt;br /&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class="tableofcontents-column3"&gt;
        &lt;/div&gt;
        &lt;div class="tableofcontents-column3"&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="2017-03-07-notes"&gt;&lt;/div&gt;

&lt;p&gt;Along with &lt;em&gt;&lt;a href="/2016/11/moana.html"&gt;Moana&lt;/a&gt;&lt;/em&gt;’s theatrical release last fall, Disney Animation also released a short film titled &lt;em&gt;Inner Workings&lt;/em&gt;, which is also rendered using Disney’s Hyperion Renderer.
The Blu-ray release for &lt;em&gt;Moana&lt;/em&gt; is out today, and &lt;em&gt;Inner Workings&lt;/em&gt; is included with the Blu-ray and digital releases.
I didn’t work on &lt;em&gt;Inner Workings&lt;/em&gt; directly aside from the usual support and bug fixing that our team provides for all projects and artists using Hyperion, but I thought I’d share a few technical notes about &lt;em&gt;Inner Workings&lt;/em&gt; along with a handful of my favorite frames to celebrate the occasion of the Blu-ray release.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_010.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_010.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Inner Workings&lt;/em&gt; follows our hero, Paul, and his internal organs as he goes through a typical work day.
We see how his different organs represent his different emotions and desires and how they represent Paul’s internal struggle between being rational logical and being free-spirited and adventurous.
&lt;em&gt;Inner Workings&lt;/em&gt; was made with essentially the same version of Hyperion which was used on &lt;em&gt;&lt;a href="/2016/02/zootopia.html"&gt;Zootopia&lt;/a&gt;&lt;/em&gt;, but &lt;em&gt;Inner Workings&lt;/em&gt; was not rendered &lt;em&gt;entirely&lt;/em&gt; using Hyperion; the other renderer using on &lt;em&gt;Inner Workings&lt;/em&gt; was the human hand!
A large chunk of &lt;em&gt;Inner Workings&lt;/em&gt; is traditional hand-drawn animation made using Disney Animation’s Meander tool &lt;a href="https://doi.org/10.1145/2343045.2343071"&gt;[Whited et al. 2012]&lt;/a&gt;, which was previously used on &lt;em&gt;Paperman&lt;/em&gt; and &lt;em&gt;Feast&lt;/em&gt; &lt;a href="https://history.siggraph.org/learning/the-art-and-science-behind-walt-disney-animation-studios-paperman-by-kahrs-osborne-sathe-turley-and-whited/"&gt;[Kahrs et al. 2012&lt;/a&gt;, &lt;a href="https://history.siggraph.org/learning/feast-a-look-at-walt-disney-animation-studios-newest-short-by-osborne-and-staub/"&gt;Osborne and Staub 2015]&lt;/a&gt;!
Every time Paul’s brain imagines a future scenario, all of the animation is wonderful hand-drawn work that is in the director, Leo Matsuda’s, personal style.
It looks absolutely fantastic, and this type of merger between cutting edge CG and beautiful traditional animation speaks towards Disney Animation’s combination of modern technology with rich artistic legacy.&lt;/p&gt;

&lt;p&gt;The opening shot of &lt;em&gt;Inner Workings&lt;/em&gt; is an anatomy textbook with clear plastic pages flipping to show overlays of different body systems inside of Paul.
This shot seems pretty simple but is actually a great example of a type of shot that is pretty easy with a modern ray tracing renderer and insanely difficult using older rasterized rendering; with Hyperion’s ray tracing, there are no compositing hacks required to see through all of the clear sheets, and the printing on each sheet just automatically and naturally casts soft shadows onto the sheets below, lending depth and realism.
The design of Paul’s insides made for a bit of a fun rendering problem; all of the organs are cartoony and friendly and squishy, which from a rendering perspective means they are all gummy objects with tons of subsurface scattering but also lots of internal glow.
The final look of the organs is made up of a mish-mash of subsurface scattering, diffuse transmission, and internal volumetrics.
In general a lot of the look of &lt;em&gt;Inner Workings&lt;/em&gt; follows a sort of heightened cartoony physicality, which I think really showcases the flexibility and power of Hyperion’s Disney Principled BSDF shading model &lt;a href="https://doi.org/10.1145/2776880.2787670"&gt;[Burley 2015]&lt;/a&gt;.
&lt;em&gt;Inner Workings&lt;/em&gt; is also the last project made using our older pre-&lt;em&gt;Moana&lt;/em&gt; water rendering system; &lt;em&gt;Moana&lt;/em&gt; features a brand new, from-the-ground-up approach to water rendering &lt;a href=""&gt;[Palmer et al. 2017]&lt;/a&gt;.
Despite the older water rendering tech, I think the handful of ocean beach shots in &lt;em&gt;Inner Workings&lt;/em&gt; look great!
Really this just goes to show that while better rendering technology always helps, at the end of the day the most important factor to making really nice looking films is the artists.&lt;/p&gt;

&lt;p&gt;Here are a handful of frames from &lt;em&gt;Inner Workings&lt;/em&gt; pulled from the Blu-ray and presented in random order, to showcase how Hyperion was used on this short.
Get &lt;em&gt;Inner Workings&lt;/em&gt; with a copy of &lt;em&gt;Moana&lt;/em&gt; (digital or physical) and see it on the biggest screen you can!&lt;/p&gt;

&lt;div id="2017-03-07-frames"&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_001.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_001.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_011.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_011.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_008.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_008.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_002.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_002.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_012.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_012.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_006.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_006.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_015.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_015.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_004.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_004.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_014.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_014.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_005.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_005.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_007.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_007.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_003.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_003.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_016.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_016.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_009.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_009.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_013.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2017/Mar/innerworkings/BODY_013.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All images in this post are courtesy of and the property of Walt Disney Animation Studios.&lt;/p&gt;

&lt;div id="2017-03-07-references"&gt;&lt;/div&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;

&lt;p&gt;Brent Burley. 2015. &lt;a href="https://doi.org/10.1145/2776880.2787670"&gt;Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2015 Course Notes: &lt;a href="https://blog.selfshadow.com/publications/s2015-shading-course"&gt;Physically Based Shading in Theory and Practice&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;John Kahrs, Patrick Osborne, Amol Sathe, Jeff Turley, Brian Whited, and Darrin Butters. 2012. &lt;a href="https://history.siggraph.org/learning/the-art-and-science-behind-walt-disney-animation-studios-paperman-by-kahrs-osborne-sathe-turley-and-whited/"&gt;The Art and Science Behind Walt Disney Animation Studios’ “Paperman”&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2012 Production Sessions&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Patrick Osborne and Josh Staub. 2014. &lt;a href="https://history.siggraph.org/learning/feast-a-look-at-walt-disney-animation-studios-newest-short-by-osborne-and-staub/"&gt;Feast – A Look at Walt Disney Animation Studios’ Newest Short&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2014 Production Sessions&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sean Palmer, Jonathan Garcia, Sara Drakeley, Patrick Kelly, and Ralf Habel. 2017. &lt;a href="https://dl.acm.org/citation.cfm?id=3085067"&gt;The Ocean and Water Pipeline of Disney’s &lt;em&gt;Moana&lt;/em&gt;&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2017 Talks&lt;/em&gt;. Article 29.&lt;/p&gt;

&lt;p&gt;Brian Whited, Eric Daniels, Michael Kaschalk, Patrick Osborne, and Kyle Odermatt. 2012. &lt;a href="https://doi.org/10.1145/2343045.2343071"&gt;Computer-Assisted Animation of Line and Paint in Disney’s Paperman&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2012 Talks&lt;/em&gt;. Article 19.&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Tue, 07 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2017/03/inner-workings.html</guid></item><item><title>React animate height (slide up/down) component</title><link>https://muffinman.io/blog/react-animate-height-slide-up-down/</link><description>&lt;article class="article"&gt;&lt;p&gt;Most JavaScript developers used jQuery&amp;#x27;s &lt;code&gt;.slideUp()&lt;/code&gt; and &lt;code&gt;.slideDown()&lt;/code&gt; methods,
and got used to them. As component based frameworks usually do not include such functionality,
the first logic choice is to turn to CSS. But alas, CSS transitions do not work with &lt;code&gt;height: auto&lt;/code&gt;.
(Transitions can do a tween only between two numeric values.)&lt;/p&gt;
&lt;p&gt;As we use this a lot in our company, I tried to find React component that does it.
Found a couple, didn&amp;#x27;t like them, as most of them rely on a tone of dependencies.
Again, I decided to write my own - small, fast and with no dependencies.&lt;/p&gt;
&lt;h2 id="demo"&gt;Demo &lt;a class="anchor-link" href="#demo"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can see it live &lt;a href="https://muffinman.io/react-animate-height/"&gt;here&lt;/a&gt;.
Same page has the documentation and links to the npm and GitHub.&lt;/p&gt;
&lt;p&gt;Component can animate from (and to) &lt;code&gt;0&lt;/code&gt; (collapsed), &lt;code&gt;auto&lt;/code&gt; (expanded),
and to any specific value in pixels.&lt;/p&gt;
&lt;h2 id="usage"&gt;Usage &lt;a class="anchor-link" href="#usage"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Install it from npm&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;npm&lt;/span&gt; &lt;span class="token function"&gt;install&lt;/span&gt; &lt;span class="token parameter variable"&gt;--save&lt;/span&gt; react-animate-height
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Import it in your React project, and wrap the content you want to animate in it.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token maybe-class-name"&gt;AnimateHeight&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-animate-height&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token class-name"&gt;AnimateHeight&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;  &lt;span class="token attr-name"&gt;duration&lt;/span&gt;&lt;span class="token script language-javascript"&gt;&lt;span class="token script-punctuation punctuation"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token number"&gt;500&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;  &lt;span class="token attr-name"&gt;height&lt;/span&gt;&lt;span class="token script language-javascript"&gt;&lt;span class="token script-punctuation punctuation"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;auto&amp;#x27;&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;  &lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;Your content goes here&lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;  &lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;Put as many React or HTML components here.&lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="token plain-text"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token plain-text"&gt;&lt;/span&gt;&lt;span class="token tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="token class-name"&gt;AnimateHeight&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For more detailed documentation and all props explained,
check the &lt;a href="https://github.com/Stanko/react-animate-height"&gt;GitHub repo&lt;/a&gt;,&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works &lt;a class="anchor-link" href="#how-it-works"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Component is using CSS transitions, but with a small trick to make it work.
We mentioned that transitions only work between two numeric values.
We&amp;#x27;ll replace &lt;code&gt;auto&lt;/code&gt; with numeric value just before transition happens.&lt;/p&gt;
&lt;p&gt;There are three possible cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Specific height to the other specific height&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the easiest one. Element will have &lt;code&gt;overflow: hidden&lt;/code&gt; and translate from
one height value to the other. Piece of cake.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Specific height (0 included) to auto&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This one is a bit more interesting. As we can&amp;#x27;t transition to &lt;code&gt;auto&lt;/code&gt;,
component will take the content height, apply it to the element, and transition will happen.
But important thing is that after the transition is complete,
component will reset &lt;code&gt;height&lt;/code&gt; to &lt;code&gt;auto&lt;/code&gt; and &lt;code&gt;overflow&lt;/code&gt; to &lt;code&gt;visible&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is important if you add more content to the component, it will natively grow.
As well for the potential absolute elements that you want to go outside of the container.
Note that when specific height is applied element will always have &lt;code&gt;overflow: hidden&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Auto to specific height (0 included)&lt;/strong&gt;
Similar to the previous case but reversed. Component will grab the expanded height and
apply it to the element. Then with a timeout of 0, apply specific height.
(Check &lt;a href="/talks-i-like/#what-the-heck-is-the-event-loop-anyway-brsmallphilip-roberts-2014small"&gt;this&lt;/a&gt; if you are confused about the timeout of 0.) Again, transition will work as it goes between two numeric values.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion &lt;a class="anchor-link" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I guess everyone took slide up/down for granted, but in the end there is a little
logic that needs to be put in to make it work properly.
On the other hand some people are solving it by pilling up the 3rd party code.
Please, when you are open sourcing a library, keep it small and simple!&lt;/p&gt;
&lt;p&gt;Hope you&amp;#x27;ll use it!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 06 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-animate-height-slide-up-down/</guid></item><item><title>Passing by Alan Spence</title><link>https://ho.dges.online/words/commonplace/passing-by-alan-spence/</link><description>&lt;p&gt;Sometimes you hear a perfect sonnet line,&lt;br /&gt;
spoken in passing, the word on the street&lt;br /&gt;
fall easily, but as if by design&lt;br /&gt;
into that good, old pentameter beat.&lt;br /&gt;
So on this late September afternoon,&lt;br /&gt;
summer winding down, shading into fall,&lt;br /&gt;
the day, the year, this life, passing too soon,&lt;br /&gt;
i almost hear the meaning of it all&lt;br /&gt;
as a young mother calls out to her son&lt;br /&gt;
running daft in this scrap of city park.&lt;br /&gt;
She calls, knowing this time will soon be done,&lt;br /&gt;
but as if love might yet hold back the dark,&lt;br /&gt;
‘Just play a while and then we have to go.’&lt;br /&gt;
Just play a while and then we have to go.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Mon, 06 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/passing-by-alan-spence/</guid></item><item><title>March 2017 Projects</title><link>https://venam.net/blog/psychology/2017/03/06/projets-2017.html</link><description>Hello fellow readers,  This is the first post of 2017, let's recap what I've been up to since the start of the year.  Show me how you spend your day and I'll tell you what you care about</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Mon, 06 Mar 2017 00:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2017/03/06/projets-2017.html</guid></item><item><title>Agency or Indie Band?</title><link>https://solomon.io/agency-or-indie-band/</link><description>Last week I was having a beer with a friend who’s starting a marketing agency. We begin talking about the business and services he’s planning to offer.</description><author>Sam Solomon</author><pubDate>Sun, 05 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/agency-or-indie-band/</guid></item><item><title>Couple of talks I really liked</title><link>https://muffinman.io/blog/talks-i-like/</link><description>&lt;article class="article"&gt;&lt;p&gt;In this post you can find seven talks I really liked in no particular order, most of them development related. I&amp;#x27;ll explain why I liked them, and why I should recommend watching every single one of them.&lt;/p&gt;
&lt;p&gt;Every talks is embedded, but link to a website or youtube is included as well.&lt;/p&gt;
&lt;p&gt;Please comment with the talks you think are worth watching.&lt;/p&gt;
&lt;h3 id="wat"&gt;Wat &lt;a class="anchor-link" href="#wat"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Gary Bernhardt, 2012&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The talk I shared too many times. Gary talks about weird stuff in Ruby and JavaScript.
It is witty and educational at the same time. I guarantee it will make you laugh.
Only four minutes long, give it a try.&lt;/p&gt;
&lt;figure class="video__figure"&gt;&lt;video class="" controls="" height="768" preload="none" src="./wat.mp4#t=0.001" style="background: black;" width="1024"&gt;&lt;/video&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://www.destroyallsoftware.com/talks/wat"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="live-react-hot-reloading-with-time-travel"&gt;Live React: Hot Reloading with Time Travel &lt;a class="anchor-link" href="#live-react-hot-reloading-with-time-travel"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Dan Abramov, 2015&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We all know Dan Abramov and what he has done for the React/JS community.
This is the talk that made him famous and he ended up working for Facebook.
It is about hot reloading in React, which he made mainstream.&lt;/p&gt;
&lt;p&gt;It is best described with a YouTube comment: &amp;quot;All that was missing was the mic drop at the end.﻿&amp;quot;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=xsSnOQynTHs"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="what-the-heck-is-the-event-loop-anyway"&gt;What the heck is the event loop anyway? &lt;a class="anchor-link" href="#what-the-heck-is-the-event-loop-anyway"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Philip Roberts, 2014&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Every&lt;/em&gt; JavaScript developer should watch this. Philip explained what event loop is, how it works, in a simple language using beautiful examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="the-early-days-of-id-software"&gt;The Early Days of id Software &lt;a class="anchor-link" href="#the-early-days-of-id-software"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;John Romero, 2016&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Wow! This reminded me why I started programming, and how I ended up where I am today.
I started with the only one thing in mind - to write games.&lt;/p&gt;
&lt;p&gt;Historical talk about couple of kids who wanted to do exactly that.
How they started, what they principles were. For those who don&amp;#x27;t know, id Software is behind
Doom, Quake, Commander Keen, Wolfenstein and many more games.
Don&amp;#x27;t get scared because it is almost one hour long, talk itself if about thirty minutes.&lt;/p&gt;
&lt;p&gt;It got me thinking about writing games again,
and hopefully I will have a blog post about that soon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=E2MIpi8pIvY"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="adjusting-the-dials-in-the-circuits-of-the-human-brain-with-deep-by-brain-stimulation"&gt;Adjusting the Dials in the Circuits of the Human Brain with Deep by Brain Stimulation &lt;a class="anchor-link" href="#adjusting-the-dials-in-the-circuits-of-the-human-brain-with-deep-by-brain-stimulation"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Dr Andres Lozan, 2016&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I watched this one live at ng-conf 2016, and it blew me away.
It has nothing to do with a development, but medicine.
How doctors are able to adjust brain functions by applying electricity to a certain parts.&lt;/p&gt;
&lt;p&gt;It still sounds like a science fiction to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=IEMLGrKJeK0"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="heres-what-happens-when-an-18-year-old-buys-a-mainframe"&gt;Here&amp;#x27;s What Happens When an 18 Year Old Buys a Mainframe &lt;a class="anchor-link" href="#heres-what-happens-when-an-18-year-old-buys-a-mainframe"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Connor Krukosky, 2016&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Title is self-explanatory - young enthusiast got his hands on an old mainframe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=45X4VP8CGtk"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="do-schools-kill-creativity"&gt;Do schools kill creativity &lt;a class="anchor-link" href="#do-schools-kill-creativity"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Sir Ken Robinson, 2007&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Last, but not the least. This is the most watched TED talk on YouTube.
Sir Ken Robinson needs no introduction, and he talks about the school system,
and how it may be killing kid&amp;#x27;s creativity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=iG9CE55wbtY"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hope you found some of these interesting to watch, and that you learned something new.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sun, 05 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/talks-i-like/</guid></item><item><title>Add This Directory to Your PATH</title><link>https://bfontaine.net/2017/03/04/add-this-directory-to-your-path/</link><description>&lt;p&gt;You’ve probably read this instruction quite a few times in online tutorials
about installing command-line tools. What is this &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; for? Why should we
add directories “to” it? This is the subject of this post.&lt;/p&gt;

&lt;h2 id="how-the-shell-finds-executables"&gt;How the Shell Finds Executables&lt;/h2&gt;

&lt;p&gt;When you type something like &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt;, your shell has to find what is this &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt;
program you’re trying to run. Typical shells only have a handful predefined
commands like &lt;code class="language-plaintext highlighter-rouge"&gt;cd&lt;/code&gt;; most of the commands you use everyday are standalone
programs.&lt;/p&gt;

&lt;p&gt;In order to find that &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt; program; your shell looks in a few directories.
Those directories are stored in an environment variable called &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;; you can
look up its value in most shells using the following command:&lt;/p&gt;

&lt;div class="language-sh highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see it contains a list of paths separated by colons. Finding a program
in these is just a matter of checking each directory to see if it contains an
executable with the given name. This lookup is implemented by the &lt;code class="language-plaintext highlighter-rouge"&gt;which&lt;/code&gt;
program. The algorithm is pretty simple and goes like this:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;cmd = "ls"
for directory in $PATH.split(":") {
    candidate = $directory/$cmd ;
    if candidate exists and is executable {
        return candidate ;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is pseudo-code, but there are implementations in various languages:
&lt;a href="https://github.com/clibs/which/blob/641a91a8a509877e1f27d223299e6615472c9ec8/src/which.c#L35-L36"&gt;C&lt;/a&gt;, &lt;a href="https://github.com/bfontaine/which/blob/eb85e63e18a74984175ed2425b148f06a0428431/which/which.go#L41-L57"&gt;Go&lt;/a&gt;, &lt;a href="https://github.com/Homebrew/brew/blob/370c711da23fa0f7c7944f7d15928e44a67656a9/Library/Homebrew/utils.rb#L299-L311"&gt;Ruby&lt;/a&gt;, &lt;a href="https://github.com/dart-lang/which/blob/b92330b876b832e3c632629288d0ee1eca9571c5/lib/src/which_impl.dart#L38"&gt;Dart&lt;/a&gt;, &lt;a href="https://github.com/search?q=which"&gt;etc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you can see, the order of these directories matters because the first
matching candidate is used. That means if you have a custom &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt; program in
&lt;code class="language-plaintext highlighter-rouge"&gt;/my/path&lt;/code&gt;, putting &lt;code class="language-plaintext highlighter-rouge"&gt;/my/path&lt;/code&gt; at the beginning of the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable will
cause &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt; to always refer to &lt;em&gt;your&lt;/em&gt; version instead of e.g. &lt;code class="language-plaintext highlighter-rouge"&gt;/bin/ls&lt;/code&gt; because
&lt;code class="language-plaintext highlighter-rouge"&gt;/bin&lt;/code&gt; appears &lt;em&gt;after&lt;/em&gt; &lt;code class="language-plaintext highlighter-rouge"&gt;/my/path&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can perform this lookup using the &lt;code class="language-plaintext highlighter-rouge"&gt;which&lt;/code&gt; command. Add &lt;code class="language-plaintext highlighter-rouge"&gt;-a&lt;/code&gt; to get all
matching executables in the order in which they’re found. This is what
&lt;code class="language-plaintext highlighter-rouge"&gt;which python&lt;/code&gt; gives on my machine:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ which python
/usr/local/bin/python

$ which -a python
/usr/local/bin/python
/usr/bin/python
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see I have two &lt;code class="language-plaintext highlighter-rouge"&gt;python&lt;/code&gt;’s but the shell picks the one in
&lt;code class="language-plaintext highlighter-rouge"&gt;/usr/local/bin&lt;/code&gt; instead of &lt;code class="language-plaintext highlighter-rouge"&gt;/usr/bin&lt;/code&gt; because it appears first in my &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;.
You can bypass this lookup by giving a &lt;em&gt;path&lt;/em&gt; to your executable. This is why
you run executables in the current directory by prefixing them with &lt;code class="language-plaintext highlighter-rouge"&gt;./&lt;/code&gt;:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;./my-program
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This tells the shell you want to run the program called &lt;code class="language-plaintext highlighter-rouge"&gt;my-program&lt;/code&gt; in the
&lt;em&gt;current&lt;/em&gt; directory. It won’t search in the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; for it. It also works with
absolute paths. The following command runs my &lt;code class="language-plaintext highlighter-rouge"&gt;python&lt;/code&gt; in &lt;code class="language-plaintext highlighter-rouge"&gt;/usr/bin&lt;/code&gt; regardless
of what’s in my &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;/usr/bin/python
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For performance reasons a shell like Bash won’t look executables up all the
time. It’ll cache the information for the current session and will hence do
this lookup only once per command. This is why you must reload your shell to
have your &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; modifications taken into account. You can force Bash to clear
its current cache with the &lt;code class="language-plaintext highlighter-rouge"&gt;hash&lt;/code&gt; builtin:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that we know how our shell find executables; let’s see how this &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;
variable is populated.&lt;/p&gt;

&lt;h2 id="where-does-that-path-come-from"&gt;Where Does That &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; Come From?&lt;/h2&gt;

&lt;p&gt;This part depends on both your shell and your operating system. Bash reads
&lt;code class="language-plaintext highlighter-rouge"&gt;/etc/profile&lt;/code&gt; when it starts. It contains some setup instructions, including
initial values for the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable. On macOS, it executes
&lt;code class="language-plaintext highlighter-rouge"&gt;/usr/libexec/path_helper&lt;/code&gt; which in turns looks in &lt;code class="language-plaintext highlighter-rouge"&gt;/etc/paths&lt;/code&gt; for the initial
paths.&lt;/p&gt;

&lt;p&gt;The file looks like this on my machine:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ cat /etc/paths
/usr/bin
/bin
/usr/sbin
/sbin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The actual code to set the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable (or any variable for that matter) in
Bash is below:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/one/directory:/another/directory:/another/one"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, Bash doesn’t pass its variables to the child processes. That is, if
you set a variable in Bash then try to use it in a program it’ll fail:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ myvar=foo
$ ruby -e 'puts ENV["myvar"] || "nope :("'
nope :(
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Bash allows one to mark a variable as exported to subprocesses with the &lt;code class="language-plaintext highlighter-rouge"&gt;export&lt;/code&gt; builtin command:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ myvar=foo
$ export myvar
$ ruby -e 'puts ENV["myvar"] || "nope :("'
foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is usually done when setting the variable:&lt;/p&gt;

&lt;div class="language-text highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ export myvar=foo
$ ruby -e 'puts ENV["myvar"] || "nope :("'
foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Technically Bash doesn’t need you to export the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable to use it but
it’s better if for example a program you use executes another program; in this
case the former must be able to find the latter using the correct &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="how-do-we-modify-it"&gt;How Do We Modify It?&lt;/h2&gt;

&lt;p&gt;Each shell has its own file in the user directory to allow per-user setup
scripts. For Bash, it’s &lt;code class="language-plaintext highlighter-rouge"&gt;~/.bash_profile&lt;/code&gt;, which often sources &lt;code class="language-plaintext highlighter-rouge"&gt;~/.bashrc&lt;/code&gt;.
You can use this file to override the default &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;. It’ll be loaded when
starting a session; meaning you have to either reload your shell either
re-source this file after modifying it.&lt;/p&gt;

&lt;p&gt;We saw in the previous section how to set the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable; but most of the
time we don’t want to manually set the whole directories list; we only want to
&lt;em&gt;modify&lt;/em&gt; its value to add our own directories.&lt;/p&gt;

&lt;p&gt;We won’t dive into the details in that post, but Bash has a syntax to get the
value of a variable by prefixing it with a dollar symbol:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;myvar  &lt;span class="c"&gt;# prints "myvar"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$myvar&lt;/span&gt; &lt;span class="c"&gt;# prints "foo", i.e. myvar's value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Bash also supports string interpolation using double quotes: You can include
the value of a variable in a double-quotes string by just writing &lt;code class="language-plaintext highlighter-rouge"&gt;$&lt;/code&gt; followed
by its name:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello I'm &lt;/span&gt;&lt;span class="nv"&gt;$myvar&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# prints "hello I'm foo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We use this feature to append or prepend directories to the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; variable:
prepending means setting the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;’s value to that directory followed by a
colon followed by the previous &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;’s value:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/my/directory:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You usually don’t need to re-mark this variable as exported but using &lt;code class="language-plaintext highlighter-rouge"&gt;export&lt;/code&gt;
at the beginning of the command doesn’t hurt.&lt;/p&gt;

&lt;h2 id="wrapping-things-up"&gt;Wrapping Things Up&lt;/h2&gt;

&lt;p&gt;Modifying the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt; is not something we do very often because most tools are
installed in standard locations—already in our &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;. Most package managers
install executables in their own location and need the user to modify their
&lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;. &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt;, for example, installs them under &lt;code class="language-plaintext highlighter-rouge"&gt;/usr/local/bin&lt;/code&gt; and
&lt;code class="language-plaintext highlighter-rouge"&gt;/usr/local/sbin&lt;/code&gt; by default. If those are not already in the &lt;code class="language-plaintext highlighter-rouge"&gt;PATH&lt;/code&gt;, one needs
to add them:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c"&gt;# In e.g. ~/.bash_profile&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/bin:/usr/local/sbin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This means the shell will first look in these directories for executables. It
allows one to “override” existing tools with more up-to-date ones.&lt;/p&gt;</description><author>Baptiste Fontaine’s Blog</author><pubDate>Sat, 04 Mar 2017 22:19:00 GMT</pubDate><guid isPermaLink="true">https://bfontaine.net/2017/03/04/add-this-directory-to-your-path/</guid></item><item><title>How I Spent Spring Break in Cuba</title><link>https://ben.bolte.cc/posts/2017-03-04-cuba</link><description>A field guide to traveling to Cuba, written by naive college students for naive college students, mostly as exposition.</description><author>Ben Bolte</author><pubDate>Sat, 04 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ben.bolte.cc/posts/2017-03-04-cuba</guid></item><item><title>2017-03-04/01</title><link>https://ho.dges.online/pictures/2017-03-04-01/</link><description/><author>ho.dges.online</author><pubDate>Sat, 04 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-03-04-01/</guid></item><item><title>2017-03-04/02</title><link>https://ho.dges.online/pictures/2017-03-04-02/</link><description/><author>ho.dges.online</author><pubDate>Sat, 04 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-03-04-02/</guid></item><item><title>Engineering Team Metrics to Drive Performance</title><link>https://james-carr.org/posts/engineering-team-metrics-to-drive-performance/</link><description>As a newly promoted engineering manager, I am still learning about the various ways to improve my team&amp;rsquo;s performance. One of the most important aspects of this task is understanding and measuring the metrics that will drive success. Here are some of the books and articles that I have found to be valuable resources in understanding and implementing engineering team metrics.
Key Metrics The first book that I found to be extremely helpful is &amp;ldquo;Managing the Unmanageable: Rules, Tools, and Insights for Managing Software People and Teams&amp;rdquo; by Mickey W.</description><author>James Carr</author><pubDate>Fri, 03 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://james-carr.org/posts/engineering-team-metrics-to-drive-performance/</guid></item><item><title>Abstract: The Art of Design: Season 1</title><link>https://olshansky.info/tv/abstract_the_art_of_design_season_1/</link><description>Olshansky's review of Abstract: The Art of Design: Season 1</description><author>🦉 olshansky 🦁</author><pubDate>Thu, 02 Mar 2017 14:57:49 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/abstract_the_art_of_design_season_1/</guid></item><item><title>Service Discovery With Node.js and Consul at SF Node</title><link>https://thomashunter.name/posts/2017-03-02-service-discovery-nodejs-consul</link><author>Thomas Hunter II</author><pubDate>Thu, 02 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-03-02-service-discovery-nodejs-consul</guid></item><item><title>Which Linux File System Should You Use?</title><link>https://justingarrison.com/blog/2017-03-01-htg-explains-which-linux-file-system-should-you-choose/</link><description>If you’re not sure which Linux file system to use, use Ext4</description><author>Justin Garrison's Homepage</author><pubDate>Wed, 01 Mar 2017 18:23:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2017-03-01-htg-explains-which-linux-file-system-should-you-choose/</guid></item><item><title>Metaparameters in mgmt</title><link>https://purpleidea.com/blog/2017/03/01/metaparameters-in-mgmt/</link><description>&lt;p&gt;In &lt;a href="https://github.com/purpleidea/mgmt/"&gt;mgmt&lt;/a&gt; we have &lt;em&gt;meta parameters&lt;/em&gt;. They are similar in concept to what you might be familiar with from other tools, except that they are more clearly defined (in a single struct) and vastly more powerful.&lt;/p&gt;
&lt;p&gt;In mgmt, a meta parameter is a parameter which is codified entirely in the engine, and which can be used by any resource. In contrast with &lt;a href="https://docs.puppet.com/puppet/4.6/metaparameter.html#require"&gt;Puppet, require/before are considered meta parameters&lt;/a&gt;, whereas in mgmt, the equivalent is a graph edge, which is not a meta parameter. [1]&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Wed, 01 Mar 2017 18:11:59 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/03/01/metaparameters-in-mgmt/</guid></item><item><title>One project per month during 2017. Here are my first two for January and february</title><link>https://jfoucher.com/2017/03/one-project-per-month-first-budget-tracking.html</link><description>&lt;p&gt;So at the start of January I discovered the &lt;a href="https://github.com/1ppm/1ppmLog"&gt;One Project per Month&lt;/a&gt; project, and decided to give it a go. You can follow my progress &lt;a href="https://github.com/1ppm/1ppmLog/blob/master/HallOfFame.md#jfoucher"&gt;here&lt;/a&gt; and I’ll also try to post here somewhat regularly about my experiences.&lt;/p&gt;

&lt;p&gt;The first project was an app that does &lt;a href="https://budgt.eu"&gt;budget tracking&lt;/a&gt;. Well, not really budgeting, more like to track what I was spending. I’ve been wondering where all the money went, and this app was made to help me achieve some visibility about that. It’s great, &lt;a href="https://budgt.eu"&gt;check it out&lt;/a&gt; ! If the queen of england needed a way to track her spending, she told me she’d definitely use it !&lt;/p&gt;

&lt;p class="image"&gt;&lt;img alt="Queen of England says budgt is the best app to track your spending" src="/assets/img/posts/queen-says-budgt-is-best-tracking-app.jpeg" /&gt;&lt;/p&gt;

&lt;p&gt;Not that you care, but if you did you could go to the &lt;a href="https://github.com/jfoucher/budgetTracker"&gt;github repo&lt;/a&gt; and there you might be able to find out that it was made with React, PouchDB and quite a few more nice things.&lt;/p&gt;

&lt;p&gt;Anyway, the second project was the February one (that’s what one per month means, for all of you following from your nursing home bed). I wanted to try my hand at native iOS apps. I looked at the Swift docs, installed Xcode but then I saw got bored and saw on hackernews that someone had built an app with react native and liked, so I said to myself : “Jonathan : do the right and be lazy. The important thing is to get this ready before the 28th” (Yes February was limited to 28 days by royal decree this year, and well, most years really… Who knows why ?) Anyway, so since &lt;a href="http://blogoscoped.com/archive/2005-08-24-n14.html"&gt;all good programmers are lazy&lt;/a&gt; I didn’t feel too bad about myself.&lt;/p&gt;

&lt;p class="image"&gt;&lt;img alt="One does not simply become lazy" src="/assets/img/posts/become-lazy.jpeg" /&gt;&lt;/p&gt;

&lt;p&gt;So react-native is was then. Let me tell you, this thing is great ! It works perfectly, you can design stuff with CSS like ease, and all the logic is in javascript. Easy peasy. You can’t get it anywhere though because Apple wants 100€ so that I can upload my free app. But do come by my house and I’ll gladly install it on your phone. If you have an android maybe I’ll just keep for a little while to do a bit of testing. But I’ll give it back. Eventually.&lt;/p&gt;

&lt;p&gt;So yes. So far so good. No idea for March though. Maybe I’ll just do a react-native app for the &lt;a href="https://budgt.eu"&gt;budget tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any ideas ? &lt;a href="/contact"&gt;Contact me&lt;/a&gt;.&lt;/p&gt;</description><author>Geeky Nuggets</author><pubDate>Wed, 01 Mar 2017 10:17:07 GMT</pubDate><guid isPermaLink="true">https://jfoucher.com/2017/03/one-project-per-month-first-budget-tracking.html</guid></item><item><title>Open Sourcing Google Adwords Downloader</title><link>https://blog.tafkas.net/2017/03/01/open-sourcing-google-adwords-downloader/</link><description>Google Ads, the globally renowned advertising platform, empowers numerous businesses to strategically place ads, reach prospective customers, and grow their presence. The kaleidoscope of data that Google Ads provides forms the bedrock of insightful business decisions, higher return on investment, and the optimization of AdWords campaigns.
While Google Ads features a user-friendly interface for data access and management, some tasks often benefit from a programmatic approach. In response to this need, Google provides the AdWords API.</description><author>Tafkas Blog</author><pubDate>Wed, 01 Mar 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/2017/03/01/open-sourcing-google-adwords-downloader/</guid></item><item><title>Alien: Covenant</title><link>https://olshansky.info/movie/alien_covenant/</link><description>Olshansky's review of Alien: Covenant</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 28 Feb 2017 15:21:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/alien_covenant/</guid></item><item><title>Strat-O-Magic</title><link>https://mbutler.org/strat-o-magic/</link><description>After a late-night conversation with my brother about the Strat-O-Matic baseball game, I wondered if there was a way to generate realistic looking cards using real-world data. I remembered seeing a website by Bruce Bundy, which detailed a series of formulas he derived after years of trial-and-error. I spent a couple of days sifting through [&amp;#8230;]</description><author>mbutler</author><pubDate>Mon, 27 Feb 2017 04:37:03 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/strat-o-magic/</guid></item><item><title>Faster golang builds</title><link>https://purpleidea.com/blog/2017/02/26/faster-golang-builds/</link><description>&lt;p&gt;I&amp;rsquo;ve been hacking in &lt;a href="https://en.wikipedia.org/wiki/Golang"&gt;golang&lt;/a&gt; since before version 1.4, and the speed at which my builds finished has been mostly trending downwards. Let&amp;rsquo;s look into the reasons and some fixes. TL;DR click-bait title: &amp;ldquo;Get 4x faster golang builds with this one trick!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Here are the three reasons my builds got slower:&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;The compiler&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Before version 1.5, the compiler was written in C but &lt;a href="https://golang.org/doc/go1.5#c"&gt;with that release, it moved to being pure golang&lt;/a&gt;. This unfortunately reduced build performance quite measurably, even though it was the right decision for the project.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Sun, 26 Feb 2017 19:02:35 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/02/26/faster-golang-builds/</guid></item><item><title>Setting the default timezone in AppVeyor build worker (and C# 7.0 support)</title><link>https://nicolaiarocci.com/setting-the-default-timezone-in-appveyor-and-c-sharp-7-support/</link><description>&lt;p&gt;So yesterday I pushed some code over to GitHub, then went off to work on
a different project. A few seconds later I got an email from &lt;a href="https://www.appveyor.com"&gt;AppVeyor&lt;/a&gt;
telling me that my CI build worker was reporting a failure. I was surprised as
just ahead of the push I had tests all green in local.&lt;/p&gt;
&lt;p&gt;Turned out failure was on an equality assertion between two date values:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://nicolaiarocci.com/images/appveyor-failure-on-date-fields.png" /&gt;&lt;/p&gt;
&lt;p&gt;As you can see the mismatch was &lt;em&gt;precisely&lt;/em&gt; two hours. That always rings a Time
Zone alarm bell in my head. I was under the assumption that since my time zone
was correctly set in my account settings, the workers would pick it up. Well as
it turns out, that is not the case as that setting is only used for
notifications and NuGet feeds. The AppVeyor app worker runs on UTC by default.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Sat, 25 Feb 2017 17:48:09 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/setting-the-default-timezone-in-appveyor-and-c-sharp-7-support/</guid></item><item><title>From OSX to Linux</title><link>https://blog.nobugware.com/post/2017/back_from_osx_to_linux/</link><description>I&amp;rsquo;ve been a long time UNIX user, ditched Microsoft back in the 90s for FreeBSD, Solaris and Linux on the desktop, but when Apple released MacOS X, I&amp;rsquo;ve used it as a workstation.
For the last years I&amp;rsquo;ve used Linux desktops but not on my main computer, today here I am switching back to Linux.
This post is not about the reasons I&amp;rsquo;m switching, they are simple.
My typical work day is mostly about parsing giant files, running VM and Dockers, coding in Go and not about developing for iOS anymore.</description><author>Fabrice Aneche</author><pubDate>Sat, 25 Feb 2017 16:57:56 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2017/back_from_osx_to_linux/</guid></item><item><title>The future of smartphones</title><link>https://jasoneckert.github.io/myblog/the-future-of-smartphones/</link><description>&lt;p&gt;&lt;img alt="SP1" src="sp1.png#center" title="SP1" /&gt;&lt;/p&gt;
&lt;p&gt;As you can see from the picture at the top of this post, last week BlackBerry’s smartphone market share fell to 0% in the global marketplace. In all fairness, this number reflects the number of devices running BlackBerry OS (not the number of BlackBerry-branded Android devices, which together with all other Android devices, comprise 82% of the market).&lt;/p&gt;
&lt;p&gt;If you think back to 2007, BlackBerry pretty much owned the smartphone world that they created - they were too big to fail, and too proud to accept that Apple and Google could eat their cake.  But 10 years later, they’re a niche company trying to peddle their security and smartphone management software to any Fortune 500 company that still has fond memories of their brand.  It’s a stark reminder of how quickly the tech industry can change, and how unforgiving it can be to those left behind.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Fri, 24 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/the-future-of-smartphones/</guid></item><item><title>Best baby advice I ever got</title><link>https://honza.pokorny.ca/2017/02/best-baby-advice-i-ever-got/</link><description>&lt;p&gt;When I became a father, I didn&amp;rsquo;t know much about babies.  Fatherhood is one of
those &amp;ldquo;learn on the job&amp;rdquo; situations.  With a new infant in the house, one piece
of advice made my life much easier.&lt;/p&gt;
&lt;p&gt;Infants cry a lot.  The noise they emit is high-pitch, and designed to be
irritating to adults.  It&amp;rsquo;s irritating because otherwise you would just ignore
the poor child.&lt;/p&gt;
&lt;p&gt;Now, to the advice: when your infant starts to scream in the middle of the
night, look at the clock.  Yes, look at the clock.  Before you roll out of bed,
before you stumble your way to the nursery, check the clock, and remember what
time it is.  This is the best advice I ever got.&lt;/p&gt;
&lt;p&gt;When you are sleep-deprived and tired, holding a screaming infant in the middle
of the night for one minute can seem like 10.  Noting the time can put things
into perspective.  You&amp;rsquo;ll calm down and have more patience when you realize that
the &lt;em&gt;eternity&lt;/em&gt; of constant scream is only 10 minutes.&lt;/p&gt;
&lt;p&gt;Look at the clock.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Thu, 23 Feb 2017 15:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/02/best-baby-advice-i-ever-got/</guid></item><item><title>Survive being hacked by using _write-only_ backups</title><link>https://www.databasesandlife.com/write-only-backups/</link><description>&lt;p class="intro"&gt;
One of the functions of backups is to be able to restore the system and data in the case of a successful hacking attack. Without write-only backups, if the servers have access to the backups, then the hacker who has access to the servers has access to the backups too.
&lt;/p&gt;
&lt;p&gt;It is generally understood that backups which don&amp;rsquo;t happen automatically get forgotten at some point. Without automatic backups, when a restore is required, the team realizes that a backup hasn&amp;rsquo;t happened recently, and the backups can&amp;rsquo;t recover current or near-current data. Therefore, automated jobs are set up on the servers to perform backups.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Tue, 21 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/write-only-backups/</guid></item><item><title>3 common approaches to side-effects in Redux apps</title><link>https://goshacmd.com/redux-side-effect-approaches/</link><author>Gosha Spark</author><pubDate>Tue, 21 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/redux-side-effect-approaches/</guid></item><item><title>Send Kapacitor Alerts to Slack Through a Proxy</title><link>https://btmiller.com/2017/02/20/send-kapacitor-alerts-to-slack-through-a-proxy.html</link><description>&lt;p&gt;Kapacitor does not have the ability to work behind an HTTP(S) proxy, and while that is indeed &lt;a href="https://github.com/influxdata/kapacitor/issues/841"&gt;in the works&lt;/a&gt;, you might need something working today.&lt;/p&gt;

&lt;p&gt;The normal Kapacitor config for Slack integration looks something like:&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;[slack]&lt;/span&gt;
  &lt;span class="py"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
  &lt;span class="c"&gt;# you're going to update the url in a moment
&lt;/span&gt;  &lt;span class="py"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://hooks.slack.com/services/Y0UR/70K3N/H3R3"&lt;/span&gt;
  &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"#alerts"&lt;/span&gt;
  &lt;span class="py"&gt;global&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
  &lt;span class="py"&gt;state-changes-only&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’re going to make one change, but first you’ll need to setup a relay to Slack. Go install that with:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;relay2slack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The webhook relay is a simple app that starts a Flask server and listens locally for requests to forward onto Slack. This solution will work as long as we’re running relay2slack on the same server as Kapacitor. To daemonize the relay, &lt;a href="https://github.com/blaketmiller/relay2slack/tree/master/docs/systemd"&gt;follow the documentation&lt;/a&gt; in the project’s repository.&lt;/p&gt;

&lt;p&gt;Now that you have your Slack webhook relay running, you can now update Kapacitor to point to it:&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;[slack]&lt;/span&gt;
  &lt;span class="py"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
  &lt;span class="c"&gt;# url now points to relay2slack running locally
&lt;/span&gt;  &lt;span class="py"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:5000/relay"&lt;/span&gt;
  &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"#alerts"&lt;/span&gt;
  &lt;span class="py"&gt;global&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
  &lt;span class="py"&gt;state-changes-only&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Voila! Kapacitor can successfully send its requests to the relay on your localhost, and the relay forwards the JSON payload to your Slack webhook address using your proxy. This is not limited to just Kapacitor: the same strategy can be applied to any application that cannot be configured to use system proxy settings.&lt;/p&gt;</description><author/><pubDate>Tue, 21 Feb 2017 00:25:00 GMT</pubDate><guid isPermaLink="true">https://btmiller.com/2017/02/20/send-kapacitor-alerts-to-slack-through-a-proxy.html</guid></item><item><title>Ivana reading</title><link>https://rybakov.com/blog/ivana3d/</link><description>&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="ivana3d" loop="true" poster="/video/ivana3d/ivana3d.jpg"&gt;
      &lt;source src="../video/ivana3d/ivana3d.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="ivana3dbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="ivana3dpaused"&gt;&lt;/div&gt;
&lt;/div&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Mon, 20 Feb 2017 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/ivana3d/</guid></item><item><title>The utility of money is a stairway to heaven</title><link>http://dimitarsimeonov.com/2017/02/20/the-utility-of-money-is-a-stairway-to-heaven</link><description>&lt;p&gt;Under normal situations, the usefulness of money doesn’t scale
linearly. The more dollars you have, the less each additional dollar
is worth it for you. If you initially have $100K and then you suddenly
gain another $100K, for a total of $200K, this is a BIG DEAL. Doubling
your money will really enhance your quality of life. But if instead
you had $1M before that, then the additional $100K would bump you to
$1.1M which is likely a much less significant change in quality of
life.&lt;/p&gt;

&lt;p&gt;That idea is often circulated in economics textbooks and popular
literature. According to them the utility function of money is
&lt;em&gt;concave&lt;/em&gt;, meaning that each additional dollar provides less and less
utility, fun or gusto.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Utilty as a CONCAVE function of money" class="img-responsive" src="/assets/image/20170220_concave_utility/concave.png" /&gt;&lt;/p&gt;

&lt;p&gt;While this makes sense, it is a simplification of the
reality. Simplifications are great, because they allow us to reason
about “what-if” situation, ignoring most of the details.&lt;/p&gt;

&lt;p&gt;But with utility of money, this simplification is misleading. Assuming
that for every person, in every situation, money has concave utility,
will lead to wrong predictions about what these people will do. Not
only that, but it will lead to wrong advice, which can be dangerous
and reckless.&lt;/p&gt;

&lt;p&gt;In real life, each of us has options. Money enables options. There are
certain actions that are impossible to do unless you have a certain
amount of money. And each option has certain utility. If there was
only one option available, then your utility function of money would
be a step function. You either have the money to afford the option, or
not.&lt;/p&gt;

&lt;p&gt;Therefore, the utility function for money for every person is
step-wise function. Yes, it is true that looked from a far, it might
look concave. But if you look closely, you will notice that it has
sections of flatness and then sudden jumps. Like a stairway to
heaven…&lt;/p&gt;

&lt;p&gt;&lt;img alt="Utilty as a STEP-WISE concave function of money" class="img-responsive" src="/assets/image/20170220_concave_utility/step_concave.png" /&gt;&lt;/p&gt;

&lt;p&gt;Lets revisit the example from the previous essay. A medical operation
which is likely to cure you from a deadly disease might cost $200K. If
you are unlucky enough to have that disease, then this option has a
great utility to you.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Utilty as a STEP function of money" class="img-responsive" src="/assets/image/20170220_concave_utility/step_only.png" /&gt;&lt;/p&gt;

&lt;p&gt;In such case, if you had $100K and gambling was legal, then you can
gamble your money on roulette, and potentially win a chance to undergo
that operation. In this case, gambling will give you approximately 43%
chance of survival, so in reality your expected utility is positive.&lt;/p&gt;

&lt;p&gt;This provides a little bit of detail about why it might make sense to
gamble in this case…  that is if you buy my arguments about the step
function and if you buy into the concept of utility.&lt;/p&gt;

&lt;p&gt;Now, here is the twist. I actually don’t agree that there is a single
scalar utility function to desribe our preferences in life. It is a
neat mathematical concept but deriving its existence requires us to
make assumptions about human nature which are not true.  The stairway
to heaven metaphor is nice for our imagination, and thinking, and is
strictly more accurate than the smooth concave model of utility.&lt;/p&gt;

&lt;p&gt;Eventually, as we dig deeper, it will be imprecise and we’ll switch to
a more accurate, but less neat model of preference.&lt;/p&gt;

&lt;p&gt;But lets leave that discussion for the future essays. I am first going
to discuss the stairway model in some practical examples.&lt;/p&gt;</description><author>D13V</author><pubDate>Mon, 20 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/02/20/the-utility-of-money-is-a-stairway-to-heaven</guid></item><item><title>Reduce bugs by: not using `toString()`</title><link>https://www.databasesandlife.com/tostring/</link><description>&lt;p class="intro"&gt;
The trouble with &lt;code&gt;toString()&lt;/code&gt; in Java (or &lt;code&gt;ToString()&lt;/code&gt; in C#) is that every object implements it. If you want to extract information from your object, define your own method, like &lt;code&gt;getName()&lt;/code&gt;, as opposed to overriding &lt;code&gt;toString()&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;In order to leverage the Java type-checker, you might want to define a class like &lt;code&gt;FooName&lt;/code&gt; to wrap a &lt;code&gt;String&lt;/code&gt;, as opposed to simply using a &lt;code&gt;String&lt;/code&gt;. That way, a method that expects a &lt;em&gt;name of a foo&lt;/em&gt; is both more self-documenting, and will now fail when pass the &lt;em&gt;name of a bar&lt;/em&gt;.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Mon, 20 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/tostring/</guid></item><item><title>Filtering domain names on Domcomp.com with regex</title><link>https://sean.lane.sh/posts/2017/02/Filtering-domain-names-on-Domcomp.com-with-regex/</link><description>&lt;p&gt;Lately, I&amp;rsquo;ve been looking around for another domain name that&amp;rsquo;s a little shorter and more flexible than seanlane.net. My purposes for that can be explained another time, but I have been trying to search domain names that have top-level domains (the .com part of google.com, for example) that are shorter in length, alongside some other attributes. There are a number of good tools to use for searching for available domain names, but I have not found any that allow for searching by the length of top-level domain.&lt;/p&gt;
&lt;p&gt;One of the tools I am a huge fan of is &lt;a href="https://domcomp.com"&gt;DomComp&lt;/a&gt;, but I feel like it could be a bit refined. It shows whether a domain is registered or not, but I would rather that the registered ones were hidden. With that, and the other goals I had, I wrote a JavaScript function that filters out the results from DomComp&amp;rsquo;s search functionality:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-javascript"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;// Filter domcomp.com results to show what I'm interested in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;function&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;clr&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #75715e;"&gt;// Google Global TLDs as of Jan 2017
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt;    &lt;span style="color: #66d9ef;"&gt;var&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;g_tlds&lt;/span&gt; &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; [&lt;span style="color: #e6db74;"&gt;'ad'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'as'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'bz'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'cc'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'cd'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'co'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'dj'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'fm'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'io'&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;                  &lt;span style="color: #e6db74;"&gt;'la'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'me'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'ms'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'nu'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'sc'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'sr'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'su'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'tv'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'tk'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'ws'&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #66d9ef;"&gt;var&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt; &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; document.&lt;span style="color: #a6e22e;"&gt;getElementsByClassName&lt;/span&gt;(&lt;span style="color: #e6db74;"&gt;'price_table'&lt;/span&gt;)[&lt;span style="color: #ae81ff;"&gt;0&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #66d9ef;"&gt;var&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;re&lt;/span&gt; &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;/^[a-z0-9]+$/i&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #66d9ef;"&gt;for&lt;/span&gt; (&lt;span style="color: #66d9ef;"&gt;var&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt; &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;; &lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt; &lt;span style="color: #f92672;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt;.&lt;span style="color: #a6e22e;"&gt;length&lt;/span&gt;; &lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt;&lt;span style="color: #f92672;"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        &lt;span style="color: #66d9ef;"&gt;if&lt;/span&gt; (&lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt;[&lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;classList&lt;/span&gt;.&lt;span style="color: #a6e22e;"&gt;contains&lt;/span&gt;(&lt;span style="color: #e6db74;"&gt;'registered'&lt;/span&gt;)    &lt;span style="color: #f92672;"&gt;||&lt;/span&gt;      &lt;span style="color: #75715e;"&gt;// Don't show registered TLDs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt;            &lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt;[&lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;attributes&lt;/span&gt;[&lt;span style="color: #e6db74;"&gt;'tld'&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;value&lt;/span&gt;.&lt;span style="color: #a6e22e;"&gt;length&lt;/span&gt; &lt;span style="color: #f92672;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;2&lt;/span&gt;  &lt;span style="color: #f92672;"&gt;||&lt;/span&gt;      &lt;span style="color: #75715e;"&gt;// Don't show TLDs logner than 2 chars
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt;            &lt;span style="color: #75715e;"&gt;// $.inArray(rows[i].attributes['tld'].value, g_tlds) == -1 // Only show Google Global TLDs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt;            &lt;span style="color: #a6e22e;"&gt;re&lt;/span&gt;.&lt;span style="color: #a6e22e;"&gt;exec&lt;/span&gt;(&lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt;[&lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;attributes&lt;/span&gt;[&lt;span style="color: #e6db74;"&gt;'tld'&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;value&lt;/span&gt;) &lt;span style="color: #f92672;"&gt;==&lt;/span&gt; &lt;span style="color: #66d9ef;"&gt;null&lt;/span&gt;)   &lt;span style="color: #75715e;"&gt;// Don't TLDs with non-English chars
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;            &lt;span style="color: #a6e22e;"&gt;rows&lt;/span&gt;[&lt;span style="color: #a6e22e;"&gt;i&lt;/span&gt;].&lt;span style="color: #a6e22e;"&gt;style&lt;/span&gt;.&lt;span style="color: #a6e22e;"&gt;display&lt;/span&gt; &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;'None'&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The process for using the function is a little raw, but it gets the job done. The steps are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://domcomp.com"&gt;domcomp.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Under &amp;lsquo;New&amp;rsquo; domains, search for a domain name. Like &amp;lsquo;seanlane&amp;rsquo; for example&lt;/li&gt;
&lt;li&gt;Scroll down once or twice to make sure enough results load&lt;/li&gt;
&lt;li&gt;Open a developer console in your browser
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/tools/chrome-devtools/console/#open_as_panel"&gt;How to open a console in Google Chrome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console#Opening_the_Browser_Console"&gt;How to open a console in Mozilla Firefox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Copy and paste in the script above
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This is dangerous to do with code you do not completely understand, as this allows for malicious code to potentially be ran on your browser. I would hope that the script above is plain enough, but you should be very wary of doing this without making sure you understand what is being ran&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;In the console, call the function by entering &lt;code&gt;clr()&lt;/code&gt; and pressing enter.&lt;/li&gt;
&lt;li&gt;Repeat step 6 as necessary to filter out the results&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the script above, I have filtered out registered domain names, any domain names with TLDs longer than 2 characters, and domains that contain non-English characters. Commented out, but still there is a clause to only retain domains with TLDs that are within the list of what Google considers &lt;a href="https://support.google.com/webmasters/answer/62399?hl=en"&gt;Generic Country Code Top Level Domains (ccTLDs)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is probably a much better way to go about this, the least of which would be running it as the results load in automatically, but it works well enough for the time being.&lt;/p&gt;</description><author>Posts on Sean Lane</author><pubDate>Mon, 20 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2017/02/Filtering-domain-names-on-Domcomp.com-with-regex/</guid></item><item><title>Contact me</title><link>https://blog.tafkas.net/page/contact/</link><description>If you want to get in contact with me, shoot me an email or connect via
 https://twitter.com/Tafkas https://github.com/Tafkas https://gitlab.com/Tafkas https://linkedin.com/in/stadeschuldt https://google.com/+ChristianStadeSchuldt</description><author>Tafkas Blog</author><pubDate>Mon, 20 Feb 2017 01:17:42 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/page/contact/</guid></item><item><title>About me</title><link>https://blog.tafkas.net/page/about/</link><description/><author>Tafkas Blog</author><pubDate>Sun, 19 Feb 2017 23:33:45 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/page/about/</guid></item><item><title>Go Time</title><link>https://anisse.astier.eu/go-time.html</link><description>&lt;p&gt;For the Go 1.8 Release Party in Paris I gave a lightning talk on monotonic clocks. It's essentially a talk version of the &lt;a href="https://golang.org/design/12914-monotonic"&gt;Russ Cox's design document on monotonic clocks&lt;/a&gt;, which is really well written and sourced. You should go read it !&lt;/p&gt;
&lt;p&gt;Here are the &lt;a href="https://anisse.github.io/gotime"&gt;slides export&lt;/a&gt; and their …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Sun, 19 Feb 2017 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/go-time.html</guid></item><item><title>Right tool for the job</title><link>https://peterlyons.com/problog/2017/02/right-tool-for-the-job/</link><description>&lt;p&gt;"Use the right tool for the job" is an oft-repeated aphorism in the tech world. In my experience, I have found this aphorism to be said a lot but actually implemented rarely and to also omit the reality of how technology choices are made. So this post will be calling bullshit on this phrase. I hear "Use the right tool for the job", but what is see is more like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We are unable to learn new tools, so everything is built in the tools we already know
&lt;ul&gt;
&lt;li&gt;My point here is not "and this is bad and we are bad because of this", it's just the actual reality on the ground, and it's fine.&lt;/li&gt;
&lt;li&gt;Learning new programming languages is hard and takes time, money, effort, and determination. Even then many developers never achieve a level of capability and confidence that matches their primary language.&lt;/li&gt;
&lt;li&gt;New databases almost by definition are harder to develop against and operate than one you are already competent with, so you end up with slow development speed, slow queries, or operational issues and the project is deemed a failure and you abandon it and move back to the old database&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Any new tool is inherently "right" because ignorance biases positive
&lt;ul&gt;
&lt;li&gt;We have a thorough understanding of the shortcomings of our current tools due to our operational experience with them. The marketing materials for the new tool clearly indicate all of these problems are solved in the new tool. We have no operational experience with the new tool so we don't know that it comes with its own different set of shortcomings, so we are constantly switching to new tools assuming they are better. Sometimes they are, often they are worse, often they are essentially on par with the old tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;We have an 8x8 tool shed
&lt;ul&gt;
&lt;li&gt;There's only so much staff and time we have, and we do a lot of "jobs". If we actually used the right tool for each job, we'd have an unmanageable number of tools and expertise in none of them.&lt;/li&gt;
&lt;li&gt;So what happens is you use a core set of tools that does most of what you need well and if something can be done with this core set of tools adequately but not "the right way", you just do it adequately because just like physical tools, software tools take space to store, maintain, repair, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my world, the specific tool being considered when this phrase is repeated is usually a programming language, framework, library, database, or SaaS product. My TL;DR for each of these would probably be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Programming language&lt;/strong&gt;: There are teams that can add or switch programming languages and there are projects that can only accomplish this with new staff. Safe to assume your team is not the kind that can switch programming languages unless you have solid evidence indicating you can.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;library/framework&lt;/strong&gt;: In my experience these projects often do "succeed". I usually feel the end state is not significantly better than the start state and a lot of libraries/frameworks are at the end of the day basically the same tool. However, if your developers enjoy the switch and have more fun in the new framework, it might be worth the business cost, but I'd urge you to be clear with yourself that you are allowing the team X months to port to a framework basically as a job perk for retention purposes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;databases&lt;/strong&gt;: The switching cost tends to be very high. This can work out if the problems with the current database are crystal clear and the new database's ability to relieve them well-known. But most of the time when I see a project running 8 or 9 different databases, they'd probably be better off overall sticking to 2 or 3 and having real expertise in them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SaaS Products&lt;/strong&gt;: I think developers don't advocate "right tool" to promote switching between competing SaaS products that often because there's credit cards involved in comparing/contrasting. Thus I don't see as much spurious swapping of these. I think if you stick to products with well-defined functions you'll be OK and won't end up using them for the wrong job. If you use more "platform" type things (think Salesforce, CMSes, CRM) there's more potential to get into wrong tool for the job territory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall I think this in an interesting topic for me. Please share you experiences and thoughts using the comments below (this blog does have disqus comments but they are rarely used) or on twitter, etc.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 18 Feb 2017 22:28:04 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/02/right-tool-for-the-job/</guid></item><item><title>localstorage Analogy</title><link>https://peterlyons.com/problog/2017/02/localstorage-analogy/</link><description>&lt;p&gt;I was working with a friend on her dev bootcamp project writing a little wish list management single page web application just backed by localstorage in the browser. This was her first time working with localstorage. As we gradually built features into the app, when it came time to interact with localstorage, I could see she was unclear on what needed to be done, in what order, and why. So I made this analogy and I think that gave her a good frame of reference.&lt;/p&gt;
&lt;p&gt;In the browser, localstorage is (essentially) a javascript object. Our application was modeling a wish list as a javascript array (the list/array correspondence should be fairly clear). In that array each wish was initially just a string (whatever you typed in the "add wish" input text box). Later we would switch these to being objects so we could have proper IDs and timestamps, but for v1 we were shooting for the absolute simplest thing.&lt;/p&gt;
&lt;p&gt;So as we were dealing with cold start, adding wishes, reloading the page with data already saved, etc, I made this analogy. Think of localstorage like a desk drawer. Inside that desk drawer is piece of paper (our wish list, which in code maps to the array) and on that paper we are writing our wishes (the javascript strings are the wishes).&lt;/p&gt;
&lt;p&gt;So I said imagine you show up a new house (browser), go over to the desk, open the drawer and find there's no paper in there. It's empty. In real life, the presence/absence of paper is determined just by looking. In code, we need an &lt;code&gt;if&lt;/code&gt; conditional statement to see if our &lt;code&gt;localstorage.wishes&lt;/code&gt; property is there or not. When our condition evaluates to false, we need to get a new blank piece of paper to be our wish list, which we do in code with &lt;code&gt;var wishList = [];&lt;/code&gt;. Then to add a wish, we write it on the paper with &lt;code&gt;wishList.push(newWish)&lt;/code&gt;. Then we put the paper in the drawer for storage by &lt;code&gt;localstorage.wishes = wishList;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Similarly, once we have some wishes stored, if we reload the page, it's like walking into a house where the wishlist in the desk is already there and has some wishes, so we just render those wishes to the DOM instead of starting from a blank slate.&lt;/p&gt;
&lt;p&gt;It felt like this analogy made it clearer how the wishes array and localstorage needed to be manipulated at each point in the app/data lifecycle.&lt;/p&gt;
&lt;p&gt;That's all, just wanted to share this in case others find it helpful.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 18 Feb 2017 21:43:01 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/02/localstorage-analogy/</guid></item><item><title>The Balloon</title><link>https://rybakov.com/blog/balloon/</link><description>&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="balloon" loop="true" poster="/video/balloon/balloon.jpg"&gt;
      &lt;source src="../video/balloon/balloon.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="balloonbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="balloonpaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;There is something magical in such videos - since you are basically making something from nothing. The technique is borrowed from impro theater: you write the screenplay together as a group, with every participant saying one simple sentence on his or her turn. One by one a story is built. Then just film it using the simplest means, and you have a non-trivial movie in a day.&lt;/p&gt;
&lt;p&gt;I used this technique in workshops with &lt;a href="http://usanii-lab.com"&gt;USANII-Lab&lt;/a&gt; in Nairobi, resulting in two short films in two days, the beautifully absurd &lt;a href="https://vimeo.com/68944693"&gt;My ambition for survival is the only way to eat my food&lt;/a&gt; and the more polished &lt;a href="https://vimeo.com/68947929"&gt;To painfully swallow the pain of being unnoticed&lt;/a&gt;.&lt;br /&gt;
As for the video above, that was just reviving this excercise for Ivana and me.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sat, 18 Feb 2017 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/balloon/</guid></item><item><title>Python Workload pulled off Visual Studio 2017 RC3</title><link>https://nicolaiarocci.com/python-workload-pulled-off-visual-studio-2017-rc3/</link><description>&lt;p&gt;So how do you install the awesome &lt;a href="https://www.visualstudio.com/vs/python/"&gt;Python Development Tools&lt;/a&gt; on the latest
Visual Studio 2017 RC? That might seem a stupid question considering that the
Data Science and Python Development workload has been available with every
Release Candidate so far. You simply select the workload during the
installation and you&amp;rsquo;re done, right? Not quite.&lt;/p&gt;
&lt;p&gt;I found out the hard way this morning as I wanted to install VS 2017 RC3 on my
development machine and, to my surprise, I could not find Python Development
anywhere on the workloads window (which itself is a huge improvement over the
VS 2015 install experience, by the way). Easy, I thought, they moved it to some
secondary &amp;ldquo;optional workloads&amp;rdquo; tab, but a quick scan did not reveal any of
that.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Sat, 18 Feb 2017 11:48:29 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/python-workload-pulled-off-visual-studio-2017-rc3/</guid></item><item><title>JavaScript Errors and Stack Traces in Depth</title><link>https://lucasfcosta.com/blog/JavaScript-Errors-and-Stack-Traces/</link><description>Hi, everyone! After a few weeks without writing about JavaScript, it's about time we talk about it again!

This time we're going to talk about errors and stack traces and how to manipulate them.

S...</description><author>Lucas F. Costa - Blog</author><pubDate>Fri, 17 Feb 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/JavaScript-Errors-and-Stack-Traces/</guid></item><item><title>More Binary Tree Properties</title><link>https://denvaar.dev/posts/more_binary_tree_properties.html</link><description>Height and depth of a tree and determining if it's balanced.</description><author>denvaar's website</author><pubDate>Fri, 17 Feb 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/more_binary_tree_properties.html</guid></item><item><link>http://michaelhoney.com/writing/2017/2/16/kls2dmi5mbznrw345078cl2hgug8ji</link><description>&lt;figure class="
              sqs-block-image-figure
              intrinsic
            "&gt;
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                &lt;img alt="" height="208" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1487234156510-BXN1PO82EGX283RGESNI/image-asset.png?format=1000w" width="825" /&gt;

            
          
        
          
        

        
          
          &lt;figcaption class="image-caption-wrapper"&gt;
            &lt;p&gt;Security cameras for and by the community, accessible to all&lt;/p&gt;
          &lt;/figcaption&gt;
        
      
        &lt;/figure&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Thu, 16 Feb 2017 10:36:36 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2017/2/16/kls2dmi5mbznrw345078cl2hgug8ji</guid></item><item><title>Links - February 16, 2017</title><link>https://faingezicht.com/links/2017/02/16/links/</link><description>Unintentionally, there's a lot of money/banking/finance content in this post. At least its not all about Trump, right?</description><author>Avy Faingezicht</author><pubDate>Thu, 16 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/02/16/links/</guid></item><item><title>Go closures</title><link>https://www.danielcorin.com/posts/2017/2017-02-15-go-closures/</link><description>Go closures</description><author>Thought Eddies</author><pubDate>Wed, 15 Feb 2017 23:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danielcorin.com/posts/2017/2017-02-15-go-closures/</guid></item><item><title>Dumbphone is the new Smartphone. Especially for traveling</title><link>https://stop.zona-m.net/2017/02/dumbphone-is-the-new-smartphone.-especially-for-traveling/</link><description>&lt;p&gt;On the left: the &amp;ldquo;new&amp;rdquo; Nokia cell phone. On the right: why they may be a HUGE commercial success.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 15 Feb 2017 21:20:16 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/02/dumbphone-is-the-new-smartphone.-especially-for-traveling/</guid></item><item><title>Binary Search Tree</title><link>https://denvaar.dev/posts/data_structures_binary_search_tree.html</link><description>Review of the basic data structure Binary Search Tree (BST)</description><author>denvaar's website</author><pubDate>Wed, 15 Feb 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/data_structures_binary_search_tree.html</guid></item><item><title>Southampton Game Jam 2017</title><link>https://www.swilliams.io/w/southampton-game-jam-2017</link><description>&lt;p&gt;Over the past weekend, I participated in a Game Jam hosted at the University of Southampton during which I helped develop from scratch a game in Unity with
    four others. The game was called Jesticles and its basic premise was to walk around outside a nightclub, stopping fights between NPC's, and directing the
    agents across the road onto a bus, hopefully avoiding them being ran over. The game name is derived from the Jesticle, a cocktail from Southampton's local
    dive nightclub Jesters. It was vaguely related to the jam's theme of Revolution since if you didn't act fast enough, a revolution would occur, ending the
    game.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src="jesticlesScreenshot.png" href="jesticlesScreenshot.png" alt="Screenshot from Jesticles." style="height:250px;width:500px;"&gt;
    &lt;figcaption&gt;Jesticles: Politicians are stumbling out of Jesters determined to start a revolution- get them safely across the road and onto the bus!
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The game was my, and I suspect most of my team members', first real experience with C# and the Unity engine and it was fun adding stuff and writing code to
    fix in-depth issues wherever it was needed. Though, I must confess, how Unity handles control flow and objects is quite confusing and there is no doubt that
    we did not follow best practices during this 48 hour project. Having said that, it was incredible enjoyable.&lt;/p&gt;
&lt;h2&gt;See also&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a name="fn-1" href="https://itch.io/jam/sotongamejam17/rate/118925"&gt;Link to the itch.io page.&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a name="fn-2" href="https://github.com/ImranBepari97/game-jam17"&gt;Link to the Github repository.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>SWilliams.io</author><pubDate>Wed, 15 Feb 2017 03:01:01 GMT</pubDate><guid isPermaLink="true">https://www.swilliams.io/w/southampton-game-jam-2017</guid></item><item><title>3: Season 1</title><link>https://olshansky.info/tv/3_season_1/</link><description>Olshansky's review of 3: Season 1</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 14 Feb 2017 12:27:03 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/3_season_1/</guid></item><item><title>The 100: Season 4</title><link>https://olshansky.info/tv/the_100_season_4/</link><description>Olshansky's review of The 100: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 13 Feb 2017 23:54:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/the_100_season_4/</guid></item><item><title>Binary Tree Traversal</title><link>https://denvaar.dev/posts/binary_tree_traversal.html</link><description>Overview of Breadth and Depth first traversal in a Binary Tree.</description><author>denvaar's website</author><pubDate>Mon, 13 Feb 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/binary_tree_traversal.html</guid></item><item><title>2017-02-13</title><link>https://ho.dges.online/pictures/2017-02-13/</link><description/><author>ho.dges.online</author><pubDate>Mon, 13 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2017-02-13/</guid></item><item><title>How-to Debug a Running Docker Container from a Separate Container</title><link>https://justingarrison.com/blog/2017-02-13-how-to-debug-a-running-docker-container-from-a-separate-container/</link><description>Debugging a stripped down Docker container from a separate container</description><author>Justin Garrison's Homepage</author><pubDate>Mon, 13 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2017-02-13-how-to-debug-a-running-docker-container-from-a-separate-container/</guid></item><item><title>Setup up ConcourseCI 2.6.0 behind Nginx with Self Signed Certificates on Ubuntu 16.04</title><link>https://boyter.org/2017/02/setup-concourseci-2-6-0-nginx-signed-certificates-ubuntu-16-04/</link><description>&lt;p&gt;[Concourse CI][1] is a very nice continuous integration server.&lt;/p&gt;
&lt;p&gt;However for installs there are a few gotcha&amp;rsquo;s you need to keep in mind. Mostly these relate to how TLS/SSL works.&lt;/p&gt;
&lt;p&gt;The first is that while it is possible to run concourse inside Docker I found this to cause a lot of issues with workers dying and not recovering. I would suggest installing the binarys on bare machines. When I moved from a docker cluser using Amazon&amp;rsquo;s ECS to a single t2.large instance not only were builds faster but it was a far more reliable solution.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 12 Feb 2017 23:56:58 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/02/setup-concourseci-2-6-0-nginx-signed-certificates-ubuntu-16-04/</guid></item><item><title>Links - February 12th, 2017</title><link>https://faingezicht.com/links/2017/02/12/links/</link><description>This is a podcast heavy list. I have been reading plenty of books lately (this year I've already finished 4, and I'm partially through 3!), so I've been spending more and more time on podcast land. There are a couple of programm-y things, but everything else is sadly about Politics.</description><author>Avy Faingezicht</author><pubDate>Sun, 12 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/02/12/links/</guid></item><item><title>So You Want to Learn Docker</title><link>https://www.mikekasberg.com/blog/2017/02/11/so-you-want-to-learn-docker.html</link><description>&lt;h2 id="everyones-learning-docker"&gt;Everyone’s Learning Docker&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; is the cool new technology. Last year, it had
264% YoY growth in Stack Overflow questions.&lt;sup id="fnref:1"&gt;&lt;a class="footnote" href="https://www.mikekasberg.com/blog/2017/02/11/so-you-want-to-learn-docker.html#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; And with good reason. Docker
solves a lot of software development and systems engineering challenges. It
provides a great solution for development and testing environments, enabling
developers to test their code in an environment very similar to production
(assuming production runs on containers). Even if production doesn’t run on
containers, many developers still prefer Docker over virtual machines for
development and testing because of the advantages it provides for speed and
consistent state.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Docker Logo" src="https://www.mikekasberg.com/images/so-you-want-to-learn-docker/docker_small_h-trans.png" /&gt;&lt;/p&gt;

&lt;p&gt;With the rapid growth Docker is experiencing, it seems like everyone is trying
to learn how to use the technology. In fact, I’ve invested many over the last
year in teaching &lt;em&gt;myself&lt;/em&gt; to use Docker. When I was just starting out, I spent a
lot of time searching for the quickest, easiest way to learn.&lt;/p&gt;

&lt;h2 id="how-we-learn"&gt;How we Learn&lt;/h2&gt;

&lt;p&gt;When I learned Git many years earlier, I used a really great website called &lt;a href="https://gitimmersion.com/"&gt;Git
Immersion&lt;/a&gt;. Essentially, this walks you through pretty
much everything you might want to do with a Git repository. It assumes nothing,
and starts with the most basic principals. But by the time you reach lab 15 or
20, you start to feel like you really know what you’re doing. You start to feel
&lt;em&gt;comfortable&lt;/em&gt; using Git because you’ve been actively using it as part of every
lesson.&lt;/p&gt;

&lt;p&gt;And there’s actually reason behind this learning methodology. Educators know
that people learn more by doing things than they do by reading about them. If
you read a book about a new technology, even if it feels like you learn a lot
from the book, you won’t feel at-home when you start to use it for the first
time. You won’t feel &lt;em&gt;comfortable&lt;/em&gt; with it. Git Immersion is based on the
premise, “to know a thing is to do it.” When you work through Git Immersion, you
don’t just read about Git. You &lt;em&gt;use&lt;/em&gt; it. You &lt;em&gt;build something&lt;/em&gt; with it. And this
is critical for the effectiveness with which it helps you learn.&lt;/p&gt;

&lt;h2 id="container-immersion"&gt;Container Immersion&lt;/h2&gt;

&lt;p&gt;When I began teaching myself Docker, I was looking for something that would
teach me Docker in the same way Git Immersion taught me Git. A walk-through of
sorts, that would teach me how to build things with Docker from the ground up.
While I found a few good books and reference materials, I never found exactly
what I was looking for. (But I do recommend &lt;a href="https://dockerbook.com/"&gt;The Docker
Book&lt;/a&gt; if you’re serious about learning Docker.)&lt;/p&gt;

&lt;p&gt;Now that I know Docker pretty well, I’ve decided to create the type of lessons
that I wish I had when I was learning. &lt;a href="https://mkasberg.github.io/container-immersion/"&gt;Container
Immersion&lt;/a&gt; is a “guided tour”
for Docker, written in the spirit of Git Immersion. It is hosted on Github via
Github Pages, so it is open source and anybody can use or contribute to it. I
don’t know if it will ever turn into a very popular project, but I enjoyed
writing it and I hope someone finds it useful.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Image: &lt;a href="https://www.flickr.com/photos/lord_yo/4554730854/"&gt;https://www.flickr.com/photos/lord_yo/4554730854/&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;
      &lt;p&gt;&lt;a href="https://blog.newrelic.com/2016/06/16/docker-container-infographic/"&gt;https://blog.newrelic.com/2016/06/16/docker-container-infographic/&lt;/a&gt; &lt;a class="reversefootnote" href="https://www.mikekasberg.com/blog/2017/02/11/so-you-want-to-learn-docker.html#fnref:1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sat, 11 Feb 2017 19:50:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/02/11/so-you-want-to-learn-docker.html</guid></item><item><title>De-Risking Your Startup (SaaStr 2017 Talk)</title><link>https://www.codingvc.com/p/saastr-2017</link><description>This page contains info on a 15-minute talk I gave at the SaaStr conference called &amp;#8220;De-Risking Your Startup.&amp;#8221;</description><author>Coding VC</author><pubDate>Sat, 11 Feb 2017 08:47:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/saastr-2017</guid></item><item><title>Dynamically calling a Function in FSharp</title><link>https://daniellittle.dev/dynamically-calling-a-function-in-fsharp</link><description>Sometimes you just want to make a dynamic call. There is no equivalent for  in  so I guess we'll have to roll our own.  In this post I'll go…</description><author>Daniel Little Dev</author><pubDate>Sat, 11 Feb 2017 08:16:03 GMT</pubDate><guid isPermaLink="true">https://daniellittle.dev/dynamically-calling-a-function-in-fsharp</guid></item><item><title>Streets in Asheville</title><link>https://josh.works/asheville-streets</link><description>&lt;h2 id="quick-and-dirty-street-analysis-in-asheville-nc"&gt;Quick-and-dirty street analysis in Asheville, NC&lt;/h2&gt;

&lt;p&gt;A few months ago, I visited Asheville, NC. It’s a nice town, and has a great pedestrian life, as far as I can tell.&lt;/p&gt;

&lt;p&gt;As a thought experiment, I decided to see how well I could make the case for reducing the road width of a few streets.&lt;/p&gt;

&lt;p&gt;The reasons are simple - wide roads are hard to cross by pedestrians, encourage faster driving, and are (as I’m going to try to prove) bad for cities.&lt;/p&gt;

&lt;p&gt;It’s common for “walkable” streets to have two wide lanes traffic (one each way) plus a lane for parking on each side, plus, perhaps, one or two bicycle lanes, and perhaps a small buffer between traffic going each way.&lt;/p&gt;

&lt;p&gt;This &lt;em&gt;seems&lt;/em&gt; like a tolerable idea, except it means all of a sudden your little road is difficult to cross.&lt;/p&gt;

&lt;p&gt;I’ll be examining &lt;a href="https://www.google.com/maps/dir/35.5965063,-82.5531438/35.5964338,-82.553156/@35.596531,-82.5533667,348m/data=!3m1!1e3"&gt;45-61 W Walnut St, Asheville, NC&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Pictures are of these streets" src="/squarespace_images/static_556694eee4b0f4ca9cd56729_56035dbbe4b07ebf58d79d16_589664a5f7e0ab698b31c458_1486251199245__img.jpg_" /&gt; Pictures are of these streets&lt;/p&gt;

&lt;p&gt;There’s a few lenses that you can evaluate these streets for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Car-friendly&lt;/li&gt;
  &lt;li&gt;Pedestrian-friendly/bike-friendly&lt;/li&gt;
  &lt;li&gt;Financial implications for city&lt;/li&gt;
  &lt;li&gt;Financial implications for businesses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets take a quick stab at each of these:&lt;/p&gt;

&lt;h2 id="for-cars"&gt;For cars&lt;/h2&gt;

&lt;!--more--&gt;

&lt;p&gt;This street/road is very drivable. Here’s the intersection looking north:&lt;/p&gt;

&lt;p&gt;&lt;img alt="green for cars, yellow for bikes" src="/squarespace_images/static_556694eee4b0f4ca9cd56729_56035dbbe4b07ebf58d79d16_589664cf15d5db588fef6a14_1486251224928__img.jpg_" /&gt; green for cars, yellow for bikes&lt;/p&gt;

&lt;p&gt;The speed limit is, I believe, 20 MPH. It’s on a similar looking street two blocks over.&lt;/p&gt;

&lt;p&gt;Parking seems pretty easy, too. I’m going to make a case for eliminating the on-street parking, so here’s all of the off-street parking available:&lt;/p&gt;

&lt;p&gt;&lt;img alt="surface lots and parking garages within about two blocks" src="/squarespace_images/static_556694eee4b0f4ca9cd56729_56035dbbe4b07ebf58d79d16_589664e41b10e38edfe14657_1486251247603__img.jpg_" /&gt; surface lots and parking garages within about two blocks&lt;/p&gt;

&lt;p&gt;Each of those parking garages is six stories high.&lt;/p&gt;

&lt;p&gt;Now, there is tons of space allocated on the street to parked cars, but that has two problems:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Periods of low-use times, the on-street parking generates no value to anyone, and encourages high speeds.&lt;/li&gt;
  &lt;li&gt;Periods of high-use times, the on-street parking is so scarce that no one can expect it to be available, and it encourages “browsing around” in your vehicle instead of heading for the closest dedicated parking area.
    &lt;ul&gt;
      &lt;li&gt;Further, when the on-street parking is filled, it brings in almost no revenue to the city. It costs $2/hr to park, which is such a low amount it does not encourage people to be quick, or to use a more expensive parking structure.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At almost 45 feet wide, this street takes quite a while to cross.&lt;/p&gt;

&lt;p&gt;Since this is a walkable street with lots of shops, we would expect people to cross regularly.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.usroads.com/journals/p/rej/9710/re971001.htm"&gt;A slow-walking person (elderly person, child, or regular person with a stroller) would take 10 seconds to cross this entire street&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The painful thing is, though, about half of the width of the street is low-value or wasted space.&lt;/p&gt;

&lt;p&gt;There’s a bike lane, which is required because the street traffic is expected to go much faster than bikes. At a twenty-mile-an-hour speed limit, this shows that the road is expected to primarily serve drivers passing through.&lt;/p&gt;

&lt;p&gt;For cyclists, a reasonable average speed is 11 mph. If all drivers actually drive the posted speed limit, it would be pretty easy to share the road with someone traveling 11 mph on a bike. At 30 mph, though, it becomes dangerous for the cyclist to have to survive in the same space as a driver.&lt;/p&gt;

&lt;p&gt;A bike lane solves the wrong problem, and in some cases makes it worse.&lt;/p&gt;

&lt;p&gt;When the bike lane is not used, that unused space encourages drivers to speed up. Further, when the on-street parking is empty, it encourages drivers to go even faster, as the space dedicated to travel in both directions is extremely wide.&lt;/p&gt;

&lt;p&gt;A speed limit sign is an inappropriate method to limit vehicle speeds. It treats the symptom, rather than the cause. Study after study has shown that traffic flows at safe speeds given road conditions. If traffic is “too fast”, the road is too wide and too straight, or is too close to pedestrians that don’t handle large chunks of metal flying around.&lt;/p&gt;

&lt;p&gt;So, if you want people to go slower, reduce the space this vehicle has to drive.&lt;/p&gt;

&lt;h2 id="pedestrianbike-friendly"&gt;Pedestrian/Bike friendly&lt;/h2&gt;

&lt;p&gt;Pedestrians (or “people” as I’ll refer to them for the rest of this post) have different interests than drivers.&lt;/p&gt;

&lt;p&gt;People are best served by fractal and dense cityscapes. This means that in the course of walking a block, or a quarter mile, a person will encounter a range of services and shops. If a person has to walk 200 yards between points of interest, they’re going to visit those places less, and they are more likely to visit that place in a car.&lt;/p&gt;

&lt;p&gt;A 45 foot wide road is not pedestrian-friendly. Traffic moves quickly, and if you want to cross the street you have to either stand between parked cars as you wait for a break in traffic, or you have to travel to a crosswalk, which is a hassle.&lt;/p&gt;

&lt;p&gt;&lt;img alt="a narrow road, fine for drivers but good for people" src="/squarespace_images/static_556694eee4b0f4ca9cd56729_56035dbbe4b07ebf58d79d16_589665082e69cfe9328ebbf4_1486251295122__img.jpg_" /&gt; a narrow road, fine for drivers but good for people&lt;/p&gt;

&lt;h2 id="city-friendly"&gt;City-friendly&lt;/h2&gt;

&lt;p&gt;A city (government) wants things that make itself money while also keeping it’s constituents peaceful. I suspect that the most persuasive case that could be made to a city planner is “plan A, for which I advocate, will result in a larger addition to the tax base than plan B, which I oppose.”&lt;/p&gt;

&lt;p&gt;All else being equal, the more profitable option will win. Nothing else is equal, of course, and there are many influences advocating for different plans.&lt;/p&gt;

&lt;p&gt;Most money for infrastructure comes from the federal government, so the easiest way to bring $10mm in to your city is to sign up for a big project and fund 20% of the project. The federal/state government will provide the other 80%.&lt;/p&gt;

&lt;p&gt;This dynamic is dangerous and perverse. That’s how you get city governments spending money they don’t have to build infrastructure they don’t need, without having a tax base to support the ongoing maintenance of this infrastructure.&lt;/p&gt;

&lt;h2 id="business-friendly"&gt;Business friendly&lt;/h2&gt;

&lt;p&gt;If you’re building new construction (or considering buying a parcel of land), you need to consider how people are going to visit your business. Will you get foot traffic, or vehicle traffic?&lt;/p&gt;

&lt;p&gt;If you are going to get foot traffic, will there be foot traffic?&lt;/p&gt;

&lt;p&gt;If you’re aiming for vehicle traffic, do you need an on-site parking lot, or is there suitable parking near enough to your store that you can avoid building a parking lot?&lt;/p&gt;

&lt;p&gt;If I had a store on Walnut or Lexington Ave in Asheville, I’d expect walk-in traffic, and I would NOT plan on building a parking lot. Look at the available off-street parking in the area. There’s plenty available. Furthermore, I would want to maximize the space available to me to generate revenue.&lt;/p&gt;

&lt;p&gt;If I had a restaurant, I’d want space for tables. If I had a store, I’d want the biggest retail area. If I were building things, I’d want as much space for my workshop + display area.&lt;/p&gt;

&lt;p&gt;All of these desires would result in my maximizing the footprint of usable space to me.&lt;/p&gt;

&lt;p&gt;A parking lot flies in the face of this need.&lt;/p&gt;

&lt;p&gt;Here’s a better treatment of why small, dense lots will always be healthier and out-perform auto-oriented businesses: &lt;a href="https://www.strongtowns.org/journal/2017/1/29/the-cost-of-auto-orientation-rerun"&gt;The Cost of Auto Orientation&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="why-this-matters-to-me"&gt;Why this matters to me&lt;/h2&gt;

&lt;p&gt;I’ve been noodling on this idea for a while. A while back I read &lt;a href="https://likewise.am/2016/05/08/why-suburbia-sucks/"&gt;Why Suburbia Sucks&lt;/a&gt;, and about that time I stumbled across &lt;a href="www.strongtowns.org"&gt;StrongTowns&lt;/a&gt;. My wife and I spent about six months outside the USA, across the Americas and Europe, and I got to thinking why almost every environment I’ve ever lived in has been universally distasteful to me.&lt;/p&gt;

&lt;p&gt;Turns out that cities oriented for cars and not people are not pleasant places to live.&lt;/p&gt;

&lt;p&gt;I want to live in a place that is pleasing to me, and I believe cities and towns can create environments that are not hostile to this act of creation. And, of course, as one block fills with a dense and fractal mix of uses, the next one over will do the same. Ironically, &lt;a href="https://www.strongtowns.org/journal/2016/8/11/reclaiming-redneck-urbanism-what-urban-planners-can-learn-from-trailer-parks"&gt;the general vibe of trailer parks has immense appeal to me&lt;/a&gt;. Most of us raise our nose at trailer parks, and go about making it even more difficult for this kind of dense urbanism to be built.&lt;/p&gt;

&lt;p&gt;I’m priced out of every market I would want to live in right now. This is because of bad policy, not supply and demand. &lt;a href="https://www.strongtowns.org/journal/2016/9/22/the-50000-san-francisco-studio-apartment"&gt;Here’s how to build and buy a $50k property in San Francisco&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I feel like the thing that I want doesn’t exist in most of America, and I want it to. Further, I believe small, dense, self-sufficient urban areas can be financially self-sufficient, which will matter if the massive stream of money from the federal government ever slows down.&lt;/p&gt;

&lt;p&gt;Even more tactically, I really like Golden. But it’s succumbing to the same influences the rest of American towns are. I want to push back against that negative influence here, so that Golden can become an affordable place for normal people. (It’s not affordable to purchase property in Golden right now.)&lt;/p&gt;

&lt;p&gt;Here’s some of the parking madness that is in Golden right now:&lt;/p&gt;

&lt;p&gt;&lt;img alt="So much available parking and streets are still 50-70 feet wide" src="/squarespace_images/static_556694eee4b0f4ca9cd56729_56035dbbe4b07ebf58d79d16_5896652e2e69cfe9328ebd69_1486251323513__img.jpg_" /&gt; So much available parking and streets are still 50-70 feet wide&lt;/p&gt;

&lt;p&gt;Phew. That was a brain dump. I write to help organize my own thinking, and this has moved me in that direction, despite how disorganized all the proceeding words were.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Sat, 11 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/asheville-streets</guid></item><item><title>A Few of My Favorite Things</title><link>https://xavd.id/blog/post/a-few-of-my-favorite-things/</link><description>A look back at the best (and worst) of media in 2016&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/a-few-of-my-favorite-things/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Sat, 11 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/a-few-of-my-favorite-things/</guid></item><item><title>Checkbot for Chrome: Public beta</title><link>https://www.seanw.org/blog/checkbot-for-chrome-public-beta/</link><description>Today I&amp;rsquo;m releasing the first public beta release of my new project: Checkbot for Chrome! Checkbot is a Chrome extension that crawls the pages on your site to suggest SEO, web speed and web security improvements. Checkbot aims to be a comprehensive website testing tool that gives you everything you need to identify, understand and fix website issues.
Checkbot guides you in following web best practices by helping you fix problems such as broken links, duplicate page titles, insecure login forms, redirect chains and much more.</description><author>Sean Wilson, Web app designer &amp;amp; developer, Edinburgh, UK on Sean Wilson's homepage</author><pubDate>Fri, 10 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.seanw.org/blog/checkbot-for-chrome-public-beta/</guid></item><item><title>Counting words in TeX documents under version control</title><link>https://bastian.rieck.me/blog/2017/counting_words_git/</link><description>&lt;p&gt;Most of the time, &lt;a href="http://phdcomics.com"&gt;PhD comics&lt;/a&gt; hits too close to
home. Recently, they ran a strip showing the temporal evolution of
a typical thesis document. As expected, &lt;a href="http://phdcomics.com/comics/archive.php?comicid=1915"&gt;the comic&lt;/a&gt; proves that efforts are “doubly redoubled” when the deadline approaches. Naturally, I wondered how my own thesis—still under review—fares in that regard.&lt;/p&gt;
&lt;p&gt;I keep my thesis under version control because I am a paranoid and
cranky person when it comes to data security and backups. Consequently,
I required a script for reconstructing the amount of changes I did to
the thesis sources over time. Here’s what I came up with:&lt;/p&gt;

&lt;p&gt;If I let this script run, with the output being stored in a file
somewhere, I can use the &lt;a href="http://gnuplot.info"&gt;venerable gnuplot&lt;/a&gt; to
create a nice graph. This is what it looks like for my dissertation:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/thesis_over_time.svg"&gt;&lt;img alt="Word count in my thesis over time" src="https://bastian.rieck.me/images/thesis_over_time.svg" width="800" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Note that the script is unable to count “proper” words for
now. Hence, changes in the LaTeX markup will also result in increasing
the total number of words. I guess the slope of my own efforts is not
too similar to the comic. At the same time, you can see that most of the
content of the thesis was added in a comparatively short amount of time.&lt;/p&gt;
&lt;p&gt;Feel free to apply this to your own documents. The code is available &lt;a href="https://gist.github.com/Pseudomanifold/d7b996492dc3020f2acea87b49cc54c3"&gt;as
a gist on
GitHub&lt;/a&gt;.
This is my first real gist—thanks to
&lt;a href="https://twitter.com/conrad784"&gt;Conrad&lt;/a&gt; for the suggestion!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Thu, 09 Feb 2017 22:53:35 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/counting_words_git/</guid></item><item><title>Vero: A Simple Zsh Theme</title><link>https://jmthornton.net/blog/p/vero-zsh-theme</link><description>Announcing the release of Vero, a simple and informative theme for Zsh with git status, version managers, and more.</description><author>Blog by Jade Michael Thornton</author><pubDate>Thu, 09 Feb 2017 17:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/vero-zsh-theme</guid></item><item><title>Fun with Python functions</title><link>http://negfeedback.blogspot.com/2017/02/fun-with-python-functions.html</link><description>&lt;h2&gt;
The problem&lt;/h2&gt;
One of my postgraduate students is writing a simulation code in Python. Some of the requirements have involved us generating files containing Python programs to be executed later. But while I was going through the code today I spotted this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;    dist_code = 'def {0}(random_number):\n    values = {1}\n    cum_integrate = {2}\n    return numpy.interp(' \
                'random_number, cum_integrate, values)'.format(funk_name, list(values), list(cum_integrate))

    return ast.parse(dist_code)
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
What's happening here? We're building a function from arguments. I was intrigued, as I thought this would be basically equivalent to:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-py"&gt;    def f(random_number):
        values = list(values)
        cum_integrate = list(cum_integrate)
    f.__name__ = funk_name
    return f
&lt;/pre&gt;
&lt;br /&gt;
I told him so and went along my way. Later, we had this interesting exchange on Slack which showed that he didn't understand functions as they are. Perhaps you don't either?&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Imponderables&lt;/h2&gt;
Do you understand the output of this code?&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-py"&gt;funcs = []
for i in range(10):
    def f1():
        print(i)
    funcs.append(f1)

funcs[0]()&lt;/pre&gt;
&lt;pre&gt;Output: 9
&lt;/pre&gt;
&lt;br /&gt;
What about this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-py"&gt;i = 1
def f2():
    print(i)

f2()
i = 2
f2()

Output:
1
2
&lt;/pre&gt;
&lt;br /&gt;
The two effects are explained the same. Because a function's internal code isn't executed when it is defined, the name &lt;span&gt;i&lt;/span&gt; will only be looked up when it is run. It will then follow the LEGB rule (Local, Enclosing, Global, Built-in) at the place where it is called. Since &lt;span&gt;i&lt;/span&gt; is local, it will resolve to the same variable and show the same value in the first exaple and different values in the second example.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Solutions&lt;/h2&gt;
&lt;br /&gt;
Here are a couple of ways of getting the desired behaviour of remembering the value the function was defined with. In all cases it involves creating a new name which will take precedence in the scoping rules.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Method 1: Default argument&lt;/h3&gt;
&lt;pre class="prettyprint lang-py"&gt;funcs = []
for i in range(10):
    def f(i=i):  # New name created inside f scope
        print(i)
    funcs.append(f)
&lt;/pre&gt;
&lt;h3&gt;
Method 2: Function in a function&lt;/h3&gt;
&lt;pre class="prettyprint lang-py"&gt;def function_factory(i):  # This i is a new name
    def f():
        print(i)
    return f

funcs = []
for i in range(10):
    funcs.append(function_factory(i))
&lt;/pre&gt;
&lt;h3&gt;
Method 3: Objects&lt;/h3&gt;
&lt;div&gt;
When you think about it, this is the "obvious" way to combine a function with local data. That's exactly what OO is all about.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class="prettyprint lang-py"&gt;class NumberPrinter:
    def __init__(self, i):
        self.i = i  # This is the new name
    def call(self):
        print(self.i)

funcs = []
for i in range(10):
    funcs.append(NumberPrinter(i).call)
&lt;/pre&gt;
&lt;br /&gt;
You can do this in two ways - the other involves redefining a dunder method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-py"&gt;class NumberPrinter:
    def __init__(self, i):
        self.i = i  # This is the new name
    def __call__(self):
        print(self.i)

funcs = []
for i in range(10):
    funcs.append(NumberPrinter(i))
&lt;/pre&gt;
&lt;br /&gt;
Now we don't actually have functions in the list, but objects. We can do a little more introspection this way.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
One last thing&lt;/h2&gt;
I often see people defining functions over and over when they want to do something with a local variable. It typically comes up when people are using higher-order functions to solve equations or minimise a function:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-py"&gt;for i in range(10):
    def f():
        print(i)
    f()
&lt;/pre&gt;
&lt;br /&gt;
Convince yourself that the code above and the code to follow do the same things. This one just does it faster, since we're not incurring the cost of building a new function object.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-py"&gt;def f():
    print(i)

for i in range(10):
   f()
&lt;/pre&gt;</description><author>Negative Feedback</author><pubDate>Thu, 09 Feb 2017 16:48:13 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2017/02/fun-with-python-functions.html</guid></item><item><title>Converting VTK structured grids to matrices</title><link>https://bastian.rieck.me/blog/2017/structured_grid_to_matrix/</link><description>&lt;p&gt;I recently had to convert several structured grids in VTK format for
further processing. Since I could not find any other code for doing
this, here is my quick and dirty approach:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;reDimensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'DIMENSIONS\s+(\d+)\s+(\d+)\s+(\d+)'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;reSpacing&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'SPACING\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rePointData&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'POINT_DATA\s+(\d+)'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;reTableData&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="n"&gt;width&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="n"&gt;depth&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# Contains matrix data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="n"&gt;ii&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="c1"&gt;# Current data index for filling matrix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="c1"&gt;# Stores only those coordinates (given as an x and y position)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="c1"&gt;# that are nonzero. This permits to match adjacent time steps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="c1"&gt;# in a very concise and sparse manner.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="n"&gt;nonZero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reDimensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reDimensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;width&lt;/span&gt;  &lt;span class="o"&gt;=&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;depth&lt;/span&gt;  &lt;span class="o"&gt;=&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Invalid dimensions"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;reSpacing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reSpacing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;sx&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;sy&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;sz&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="c1"&gt;# TODO: I am ignoring the spacing, hence I am only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="c1"&gt;# able to load uniform rectilinear grids.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Invalid spacing"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;rePointData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rePointData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;num&lt;/span&gt;    &lt;span class="o"&gt;=&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Inconsistent dimensions"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;reTableData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reTableData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="n"&gt;d&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;w&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                    &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                    &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                    &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&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;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                    &lt;span class="n"&gt;ix&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                    &lt;span class="n"&gt;iy&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                    &lt;span class="n"&gt;ii&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                        &lt;span class="n"&gt;nonZero&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;iy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;iy&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;# TODO: `data` is now a matrix corresponding to the dimensions of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;# the original grid.Do something with it...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;# Store non-zero coordinates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="n"&gt;outputCoordinates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/tmp/"&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 class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;             &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".txt"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputCoordinates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&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;nonZero&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;            &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;# Store image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="n"&gt;outputImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="s2"&gt;"/tmp/"&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 class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;             &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".png"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code from above iterates over a list of VTK files (assumed to
be in ASCII format) that contains &lt;code&gt;POINT_DATA&lt;/code&gt;, i.e. a scalar value for
each grid cell. Provided that the grid follows uniform spacing, the code
is capable of parsing it and stores the &lt;code&gt;POINT_DATA&lt;/code&gt; values in a &lt;code&gt;numpy&lt;/code&gt;
matrix. Moreover, the list of non-zero coordinates of the matrix is
written to &lt;code&gt;/tmp&lt;/code&gt;, along with a pixel-based image of grid. Both outputs
are highly useful for debugging and understanding the input.&lt;/p&gt;
&lt;p&gt;Feel free to do more with this code—I am hereby releasing it into
the public domain.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Wed, 08 Feb 2017 15:15:17 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2017/structured_grid_to_matrix/</guid></item><item><title>Online Colorscheme Configurator for i3, i3status, dmenu</title><link>https://thomashunter.name/posts/2017-02-08-online-colorscheme-configurator-for-i3-i3status-dmenu</link><author>Thomas Hunter II</author><pubDate>Wed, 08 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2017-02-08-online-colorscheme-configurator-for-i3-i3status-dmenu</guid></item><item><title>Should you gamble? Sometimes</title><link>http://dimitarsimeonov.com/2017/02/08/should-you-gamble-sometimes</link><description>&lt;p&gt;I’m starting a series on essays on gambling and taking risks.  The
premise of the essays is that there are cases where it is
optimal to take risks, and even to gamble, even if the odds are bad,
and maybe even if the system is rigged.&lt;/p&gt;

&lt;p&gt;I’ll start with a simple example, maybe even too simple, and
progressively introduce mathematical concepts, and talk about the
optimal betting strategies, depending on the odds and the goals.&lt;/p&gt;

&lt;p&gt;Lets first consider an extreme scenario. Imagine that you have
$100,000 in your bank account. Sounds pretty good, right? Now imagine
that you have a terminal but curable disease, like skin cancer for
example. To cure your disease, you can undergo an operation, with 90%
guaranteed success, which costs $200,000. And for sake of the example,
lets assume it is not possible to borrow or crowd-raise the remaining
$100,000 for your operation.&lt;/p&gt;

&lt;p&gt;Lets consider two options. This might be too trivial, but bear with me
for a while. The first option is that you do nothing. In this case,
you’ll live for some short time, until the disease wins. The
alternative is for you to go to a casino, and bet all $100,000 on
roulette, on red. This will result in you doubling your money with
about 47% chance, or losing them with about 53% chance. But if you
double your money you can afford the operation. In that case you have
a total chance of 47% * 90% = 42.3% of coming out alive.&lt;/p&gt;

&lt;p&gt;Now it is clear, that among these two options, the better one is to
gamble, as it provides some chance to survive the disease. Of course,
if we want to make this example more realistic, you might think of
other ways to raise money for the operation, but then I’ll devise some
other constraint which sounds realistic and leave only the options of
gambling or not gambling, and still make gambling the better option.&lt;/p&gt;

&lt;p&gt;My main point so far is to show that there exist situations in life
where it really makes sense to gamble. Furthermore, I’ll show you that
there are many of those situations, in all parts of life, when
gambling is better than not gambling. I’ll go beyond gambling and into
taking risks in general.&lt;/p&gt;</description><author>D13V</author><pubDate>Wed, 08 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2017/02/08/should-you-gamble-sometimes</guid></item><item><title>Handle errors gracefully by offering *idempotent* APIs</title><link>https://www.databasesandlife.com/idempotency/</link><description>&lt;p class="intro"&gt;
In the REST specification, there is no way to group individual requests together into a transaction (in the way that it's possible to group multiple modifications to a database into a database transaction, or in a distributed J2EE system use a distributed transaction). Making all APIs idempotent goes some way to compensating for this shortcoming.
&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;A client may well want to access more than one REST API to carry out an action on behalf of the user. For example, if the user buys a product, they may wish to charge the user via a payment API, and then create the access rights to the product: both via REST APIs to different services.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Wed, 08 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/idempotency/</guid></item><item><title>Understanding Dependency Management in Go</title><link>https://lucasfcosta.com/blog/Understanding-Go-Dependency-Management/</link><description>Hi, everyone! As you may have noticed I'm really interested into Go and since I fell in love with this language I'd like to write about it more frequently.

If you don't know Go yet I really think...</description><author>Lucas F. Costa - Blog</author><pubDate>Tue, 07 Feb 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Understanding-Go-Dependency-Management/</guid></item><item><title>Comparing Elixir and Go</title><link>https://www.brightball.com/articles/comparing-elixir-and-go</link><description>Elixir and Go have both grown significantly in popularity over the past few years, and both are often reached for by developers looking for high concurrency solutions. The two languages follow many similar principles, but both have made some core tradeoffs that affect their potential use cases. Let’s compare the two by taking a look at their backgrounds, their programming styles, and how they deal with concurrency.</description><author>Brightball Articles</author><pubDate>Tue, 07 Feb 2017 11:52:51 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/comparing-elixir-and-go</guid></item><item><title>DIY – Tracing lightbox project resources</title><link>https://yasha.solutions/diy-tracing-lightbox-project-resources/</link><description>For a project I am working on I had to find a way to build some lightpad on the cheap. Lightpad or Tracing lights – and I found these 3 different ways to go at it.
 Walmart-style DIY lightpad Not much building-welding-connecting involved. Just buy 20 euros of office supplies and you are done. I might go with that one. Thanks    Makerspace-style lightbox From Instructables, I found this interesting under 30 dollars version.</description><author>Yasha Solutions</author><pubDate>Tue, 07 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/diy-tracing-lightbox-project-resources/</guid></item><item><title>Technical musings - high-speed ocean-traversing craft</title><link>https://walkabout165.blogspot.com/2017/02/technical-musings.html</link><description>&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUHUzYaJh-8NgKuyEbHHfc2DpyR7PdD0zQsfOekvJmz-G57D-xf7psbgVByx5YrR10Amhm2hnlwzRhttF2376eNCYS8GqEaxWJ_zbhpo1hbUvuBWzkJJFIR65yUjiZC3wwiVWbzuuSSZMh/s1600/flyship+80.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUHUzYaJh-8NgKuyEbHHfc2DpyR7PdD0zQsfOekvJmz-G57D-xf7psbgVByx5YrR10Amhm2hnlwzRhttF2376eNCYS8GqEaxWJ_zbhpo1hbUvuBWzkJJFIR65yUjiZC3wwiVWbzuuSSZMh/s320/flyship+80.jpg" width="320" /&gt;&lt;/a&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3oYKnr7naxoTtNmABDYanyGHmurIilTRNOc9Ax7kF3zdXUHMgZdUWdxCeYOCCe5lzfFTj-OV52SpPXRqf1CQ2qaQIhuOpvkZ9K6hM6EBUN9LgZy2v2nTk0AL4mYCsTd1giEVYbHjd3oO/s1600/wing_in_ground_effect_vessel.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3oYKnr7naxoTtNmABDYanyGHmurIilTRNOc9Ax7kF3zdXUHMgZdUWdxCeYOCCe5lzfFTj-OV52SpPXRqf1CQ2qaQIhuOpvkZ9K6hM6EBUN9LgZy2v2nTk0AL4mYCsTd1giEVYbHjd3oO/s320/wing_in_ground_effect_vessel.jpg" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
(Images above come from &lt;a href="http://www.boatdesign.net/forums/boat-design/studing-wig-wing-ground-effect-14818-6.html"&gt;here&lt;/a&gt; and &lt;a href="http://www.portvision.com/news-events/press-releases-news/wing-in-ground-effect-vessels-and-ais"&gt;here&lt;/a&gt;)&lt;br /&gt;
Somewhat out of character for this blog, I wanted to post an item more technical than nature than anything else. &amp;nbsp;This is because somewhere, evidently way deep inside this more managerially oriented head, is something still resembling an engineer. &lt;br /&gt;
&lt;br /&gt;
So what I've been thinking about a in the back of my mind a lot is hydrofoil-borne and Wing-In-Ground (often called ekranoplane) sea-cum-aircraft. &amp;nbsp;I think this is the result of having flown back and forth to Asia so many times, and, frequently missing the place, ponder about how to get there more easily, comfortably, and less expensively. &lt;br /&gt;
&lt;br /&gt;
I believe somewhat bullishly that there is a market opportunity for an alternative to passenger airliners that fly fairly close to the water, at markedly lower speeds for an aircraft, but markedly higher speeds for a watercraft. &amp;nbsp;So, instead of the ~13 hours it currently takes to get to Shanghai from San Francisco, maybe this would become 24 hours or even 36 hours, but in a much more spacious, and therefore more comfortable setting. &amp;nbsp;Also, these craft wouldn't require airports, but could take off from a (perhaps purpose-built) pier, so the costs (esp. real estate) of operating an airport largely go away. &amp;nbsp;Finally, I believe security costs are also reduced, because even if there is a terrorist attack,&lt;br /&gt;
1) There are few targets of value that the craft can fly into&lt;br /&gt;
2) the craft is so close to the water anyways that should an attack disable it, it simply lands in the water in the same way that it does whenever preparing for routine disembarkation. &lt;br /&gt;
Therefore I believe that security-interested national governments / transportation regulatory bodies should have an interest in fostering (or at least facilitating / allowing) such an ecosystem.&lt;br /&gt;
&lt;br /&gt;
With the reduced security and operating requirements, it is my hope that someday itineraries for this craft could be booked in a much more on-demand way than typical commercial air travel - i.e. that schedules could be published by the operator, and people arrive as they need to or book just shortly before without paying excessively for the privilege as happens in traditional air travel. &lt;br /&gt;
&lt;br /&gt;
Capital costs to get to a demonstrable version, and subsequently a commercial grade version, would be substantial (to understate). &amp;nbsp;But I believe it is possible to fund demonstrators today thanks to crowdfunding and that it is possible to finance the commercial grade version with VC / PE funds &amp;nbsp;thanks to the already demonstrated market in the form of commercial airline passenger revenue. &lt;br /&gt;
&lt;br /&gt;
So who are some people who could step up to the plate to bring advocacy to such a venture? &amp;nbsp;Among them I would certainly vote Charles Bombardier, who's already &lt;a href="https://www.wired.com/2016/11/forget-supersonic-lets-make-sea-skimming-cargo-jet/"&gt;written vividly&lt;/a&gt; of unique sea craft, and who is the legacy of a family for whom the development of unique vehicles is their raison-d'etre. &lt;br /&gt;
&lt;br /&gt;
The obstacles (besides funding of course) I see are primarily psychological in nature. &amp;nbsp;You see, ekranoplanes saw the most development under Russian engineering development (see &lt;a href="https://www.google.com/search?site=&amp;amp;tbm=isch&amp;amp;source=hp&amp;amp;biw=1211&amp;amp;bih=640&amp;amp;q=ekranoplan&amp;amp;oq=ekranoplan&amp;amp;gs_l=img.3..0l10.1925.2845.0.2939.12.9.0.3.3.0.114.588.6j1.7.0....0...1ac.1.64.img..2.10.593.0.3P3ptX3yZ5Y"&gt;here&lt;/a&gt;). &amp;nbsp;Because of politics, a technology that owed much to Russian advances (that too especially during the Cold War) will be given short shrift without more open-minded thinking. &lt;br /&gt;
&lt;br /&gt;
As I'm researching just a little for this post, &lt;a href="http://www.nextbigfuture.com/2015/04/wing-in-ground-effect-plane-from-south.html"&gt;here&lt;/a&gt; seems to be this kind of venture in action. &amp;nbsp;I wish them (and any competitors that spring forward) well.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;</description><author>The Walkabout Blog</author><pubDate>Mon, 06 Feb 2017 22:03:51 GMT</pubDate><guid isPermaLink="true">https://walkabout165.blogspot.com/2017/02/technical-musings.html</guid></item><item><title>The state of the Eve REST framework project</title><link>https://nicolaiarocci.com/the-state-of-the-eve-rest-framework-project/</link><description>&lt;p&gt;A new major release of the &lt;a href="http://python-eve.org"&gt;Eve REST API Framework&lt;/a&gt; is finally out with
a number of cool new features (MongoDB Aggregations!), few fixes, and a couple
of minor breaking changes. On the Eve blog you can find a &lt;a href="http://blog.python-eve.org/eve-07-released"&gt;detailed article&lt;/a&gt;
about this important release.&lt;/p&gt;
&lt;p&gt;I am glad to report that the &lt;a href="https://github.com/RedTurtle/eve-sqlalchemy"&gt;Eve-SQLAlchemy&lt;/a&gt; community extension, which
allows SQL databases to serve as Eve backends, has seen a surge of activity
around it. There is a new maintainer, Dominik Kellner, and a bunch of active
contributors. Work is being done to align the extension with latest Eve
release. If interested, please join the efforts there. Speaking of community
extensions, only a few days ago &lt;a href="https://github.com/petrjasek/eve-elastic"&gt;Eve-Elastic&lt;/a&gt; version 2 has been released
too.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Mon, 06 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/the-state-of-the-eve-rest-framework-project/</guid></item><item><title>Trustfuel Gmail Integration</title><link>https://solomon.io/trustfuel-gmail-integration/</link><description>Trustfuel users are primarily account or customer success managers (CSMs). They spend a significant part of their day talking with and emailing customers.</description><author>Sam Solomon</author><pubDate>Mon, 06 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/trustfuel-gmail-integration/</guid></item><item><title>How to include draw.io diagrams into LyX documents</title><link>https://www.databasesandlife.com/draw-io-diagrams-in-lyx/</link><description>&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In draw.io in the browser, go to the File menu, Export submenu, export as PDF. (I did not succeed in getting SVG output to work with LyX.) Select &amp;ldquo;crop&amp;rdquo; in the PDF export dialog. Export the PDF to the same directory where your LyX document is.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In LyX, go to the Insert menu, choose Float, choose Figure. (A &amp;ldquo;float&amp;rdquo; creates the style that the diagram is at the top or bottom of the page, as opposed to inline.)&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Mon, 06 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/draw-io-diagrams-in-lyx/</guid></item><item><title>Trustfuel Salesforce Integration</title><link>https://solomon.io/trustfuel-salesforce-integration/</link><description>Salesforce serves as the defacto CRM for many large and mid-sized businesses. This means Salesforce is often the defacto system for customer success.</description><author>Sam Solomon</author><pubDate>Sun, 05 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/trustfuel-salesforce-integration/</guid></item><item><title>The Edge of Seventeen</title><link>https://olshansky.info/movie/the_edge_of_seventeen/</link><description>Olshansky's review of The Edge of Seventeen</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 04 Feb 2017 21:10:05 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_edge_of_seventeen/</guid></item><item><title>Deepfakes</title><link>https://utf9k.net/blog/deepfakes/</link><description>An exploration of Deepfakes written up when the original subreddit (and creator) was still online</description><author>utf9k</author><pubDate>Sat, 04 Feb 2017 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/deepfakes/</guid></item><item><title>A Simple Trending Products Recommendation Engine in Python</title><link>http://blog.untrod.com/2017/02/recommendation-engine-for-trending-products-in-python.md.html</link><description>&lt;p&gt;Our product recommendations were boring. I knew that because our
customers told us. When surveyed, the #1 thing they wanted from us was
better product discovery. And looking at the analytics data, I could
see customers clicking through page after page of recommendations,
looking for something new to buy. We …&lt;/p&gt;</description><author>Untrod</author><pubDate>Sat, 04 Feb 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">http://blog.untrod.com/2017/02/recommendation-engine-for-trending-products-in-python.md.html</guid></item><item><title>Misc Trustfuel and SidePrize Work</title><link>https://solomon.io/trustfuel-sideprize-work/</link><description>In the world of startups many things don’t quite fit into a case study. This is a collection of those messy things. Those odds and ends.</description><author>Sam Solomon</author><pubDate>Sat, 04 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/trustfuel-sideprize-work/</guid></item><item><title>Literature Review: Writing Great Documentation</title><link>https://blog.harterrt.com/lit-review.html</link><description>&lt;p&gt;I'm working on a big overhaul of my team's documentation.
I've noticed writing documentation is a difficult thing to get right.
I haven't seen any great example for a data product, either.
I don't have much experience in this area,
so I decided to review what's already been written about …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Fri, 03 Feb 2017 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/lit-review.html</guid></item><item><title>AWS API Gateway Misleading Error</title><link>https://peterlyons.com/problog/2017/02/aws-api-gateway-misleading-error/</link><description>&lt;p&gt;Just a quick note from the trenches of AWS Lambda and API Gateway. API Gateway will throw a very misleading HTTP 403 status code error with the JSON body &lt;code&gt;{"message": "Missing Authentication Token"}&lt;/code&gt;. This would naturally lead us to think there's something wrong with authentication. But in my case, my endpoints are public, and this error simply means 404 Not Found that I've fat-fingered the path portion of the URL. Not sure why API Gateway responds this way, but rest assured there's no nasty IAM or API Token issue to debug, it's just an incorrect URL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Here's a link to the &lt;a href="https://forums.aws.amazon.com/thread.jspa?threadID=216684&amp;amp;tstart=0"&gt;AWS Forum Thread regarding this issue&lt;/a&gt;&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 02 Feb 2017 17:47:44 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/02/aws-api-gateway-misleading-error/</guid></item><item><title>That digital divide in Fiumicino airport</title><link>https://stop.zona-m.net/2017/02/that-digital-divide-in-fiumicino-airport/</link><description>&lt;p&gt;&lt;em&gt;(this is a translation of my Italian post of 2012 on the same issue. I&amp;rsquo;ve done it because the problem, and the need to solve it as imagined below, are still there)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The airport of Fiumicino offers a good example of the real, and really serious digital divide that afflicts many Italians. That divide is &lt;strong&gt;not&lt;/strong&gt; the lack of broadband connectivity, smartphone or computers: it is the lack of knowledge and capability of using those tools for doing something that is &lt;em&gt;actually, really useful for themselves&lt;/em&gt;. In the Fiumicino&amp;rsquo;s case, this can be seen by connecting three facts.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 02 Feb 2017 10:10:34 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2017/02/that-digital-divide-in-fiumicino-airport/</guid></item><item><title/><link>http://jrgns.net/2017/02/02/2011-10-14-backend-core-a-restful-mvc-php-framework.html</link><description>&lt;p&gt;I like frameworks. I like working with them, I like writing them. I wrote &lt;a href="http://backend-php.net"&gt;Backend-PHP&lt;/a&gt;, which I’m using personally and at &lt;a href="http://www.brandedinternet.co.za"&gt;Branded Internet&lt;/a&gt;. Unfortunately it has a number of major flaws: It’s not easily unit testable, not really a REST web service, and it doesn’t conform to any popular coding standards. So I wrote &lt;a href="https://github.com/jrgns/backend-core"&gt;Backend-Core&lt;/a&gt; as the first step towards addressing these issues.&lt;!--break--&gt;&lt;/p&gt;

&lt;h2 id="minimal"&gt;Minimal&lt;/h2&gt;

&lt;p&gt;Backend-Core is only intended as a minimal, core system. It doesn’t implement any application logic or data source abstraction. I decided to focus on the core functionality and design of a RESTful MVC system, and make sure that it works as it should. Eventually I’ll extend it with a seperate code base that will include application and data source logic.&lt;/p&gt;

&lt;h2 id="mvc"&gt;MVC&lt;/h2&gt;

&lt;p&gt;The system is structured into Model, View and Controller components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Model - The model contains all the &lt;strong&gt;business&lt;/strong&gt; logic for an application. As this is a core system, the models are empty.&lt;/li&gt;
  &lt;li&gt;View - The view determines how the results of a query will be displayed.&lt;/li&gt;
  &lt;li&gt;Controller - The controller contains the &lt;strong&gt;application&lt;/strong&gt; logic. Once again, this is only the core, not an application, so the controller just calls the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found that a number of MVC systems confuse what should go into the Model and what should go into the Controller. I’m aiming for thin Controllers containing application logic, and thick Models containing the business logic.&lt;/p&gt;

&lt;h2 id="unit-testing"&gt;Unit Testing&lt;/h2&gt;

&lt;p&gt;Backend-PHP used static global classes quite liberally, without even a thought around dependency injection. This makes unit testing unreliable and a real headache to add to the framework.&lt;/p&gt;

&lt;p&gt;Backend-Core, on the other hand, was designed to use &lt;a href="http://martinfowler.com/articles/injection.html#ConstructorVersusSetterInjection"&gt;constructor injection&lt;/a&gt; across the board, and includes a number of unit tests, supported by PHPUnit. This should increase the overall stability of the system.&lt;/p&gt;

&lt;h2 id="restful-service"&gt;RESTful Service&lt;/h2&gt;

&lt;p&gt;Something I didn’t understand about REST when I initial wrote Backend-PHP, was that every REST URL should refer to a noun, with &lt;a href="http://stackoverflow.com/questions/2001773/understanding-rest-verbs-error-codes-and-authentication/2022938#2022938"&gt;the only verbs being GET, POST, PUT and DELETE&lt;/a&gt;, as specified by the HTTP request. This resulted in it &lt;em&gt;not&lt;/em&gt; complying with REST standards, as a lot of the URLs contained extra verbs, or didn’t refer to nouns directly.&lt;/p&gt;

&lt;p&gt;Backend-Core supports the REST / HTTP verbs directly, and uses the same methods as CakePHP to identify which verb to use:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;code class="highlighter-rouge"&gt;_method&lt;/code&gt; POST variable&lt;/li&gt;
  &lt;li&gt;A &lt;code class="highlighter-rouge"&gt;X_HTTP_METHOD_OVERRIDE&lt;/code&gt; header sent with the request&lt;/li&gt;
  &lt;li&gt;The HTTP request’s method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enables it to be used from a Web browser as well as from a REST compliant client.&lt;/p&gt;

&lt;h2 id="documentation-and-coding-standards"&gt;Documentation and Coding Standards&lt;/h2&gt;

&lt;p&gt;The code complies with the &lt;a href="http://framework.zend.com/manual/en/coding-standard.html"&gt;ZEND coding standard&lt;/a&gt;, as enforced by &lt;a href="http://pear.php.net/package/PHP_CodeSniffer/redirected"&gt;PHP Code Sniffer&lt;/a&gt;. It’s documented using the &lt;a href="http://www.phpdoc.org/"&gt;PHPdoc standard&lt;/a&gt;. Hopefully this will make it easier for people to contribute to and extend the system.&lt;/p&gt;

&lt;p&gt;Feel free to fork, comment and use this.&lt;/p&gt;</description><author>Jurgens du Toit</author><pubDate>Thu, 02 Feb 2017 07:34:34 GMT</pubDate><guid isPermaLink="true">http://jrgns.net/2017/02/02/2011-10-14-backend-core-a-restful-mvc-php-framework.html</guid></item><item><title>Existence requires survival</title><link>https://macleodsawyer.com/blog/existence-survival/</link><description>&lt;p&gt;Our entire existence has been fueled on the idea of surviving by any means possible.&lt;/p&gt;
&lt;p&gt;We have lived in pain for the entirety of our existence as a species. Without pain we could not have survived, as we wouldn’t have learned how to adapt or improve our way of life from the cold, the heat, minimal water, excessive water, our digestion, or from our numerous predators. We would not have looked for new and better ways to live, and we would not be innovative to create new methods from the materials or tools surrounding us - We have survived where others have failed - simply because we have been innovating as a society to survive.&lt;/p&gt;
&lt;p&gt;To move forward as a society we must always go through tremendous growing pains. Our current economic system was developed and created through pains of past systems. Does this mean that our current capitalistic economic system is the best and ideal system? No. Our current system is just the creation built on the backbones of all others before and during our period of existence, always learning - always innovating.&lt;/p&gt;
&lt;p&gt;Some may ask “what is the point of it all? What is the goal we have been trying to reach?” the answer to this I believe is to build a truly painless existence.&lt;/p&gt;
&lt;p&gt;The goal in life is to move forward, innovate, and create a world where we no longer suffer from physical depressions while holding onto our mental depressions as without it we can not be motivated to move forward, without a villain standing in front of us (even if it is ourselves), we will never move forward.&lt;/p&gt;
&lt;p&gt;Without pain, there is no innovation. Without pain, we have no reason to fight. What makes us alive is our will to fight to minimize the pain that surrounds us.&lt;/p&gt;
&lt;p&gt;We fight for a selfish reason. We fight for what we believe will make our lives easier. We fight to survive longer and easier. We fight to make our pain go away.&lt;/p&gt;
&lt;p&gt;Some people believe we need to discriminate against others, or impede on others rights and way of life to be a better society to make our immediate personal selves have less pain.&lt;/p&gt;
&lt;p&gt;Others believe, like I do, that we need to be focused more on the inclusion of the people around us. We need be less judgmental of others, we need to stop discriminating against others to stop the cycle of discrimination. We believe in coming together and working towards our goal and purpose - to make life easier.&lt;/p&gt;
&lt;p&gt;We have to be accepting to come together and make life easier together. If we work to make life easier, to make life be less painful, then we can work together to end pain.&lt;/p&gt;
&lt;p&gt;The supposed easy way of existing is to focus purely on yourself and no one else around you, to only work towards betterment of yourself and no one else. This is the easy way of thinking, a way of thinking that has never worked in the history of our society and has always led to the end of all past civilizations, the way of thinking that when others take their own lives more seriously and believe that their happiness is more important than the people around them, they can succeed. I understand this point of view, as the hope to be less pained by being exclusionary and independent gives the idea of complete isolationism, but for the existence of our society we must be inclusionary in every thread that is part of the fabric of our society.&lt;/p&gt;
&lt;p&gt;The harder, more effective, and longer lasting way is by coming together and working together to reach a singular goal. That’s what separates people, those who believe they can make their pain go away by being independent and selfish, and those that know that being inclusive leads to a life free of pain through the unification of ideals and work.&lt;/p&gt;
&lt;p&gt;This is why organizations created by and for the people have always been on the right side of history. This is why, when you look at history, the rights of the most inclusive people always prevail. The freedom of people always prevail. The acceptance of each other always prevail.&lt;/p&gt;
&lt;p&gt;Existence is pain, and our goal in life is to find a way to work together to end pain. Without pain we have no reason to fight. We have to have pain to show us the way to come together.&lt;/p&gt;
&lt;p&gt;Existence is painful, but a very necessary evil for good.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Note: I originally published a spec of this back in early 2017, I have since updated that spec to be more descriptive, and better written than the original - this will be perpetually updated&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;06/25/17, 10/03/18,&lt;/li&gt;
&lt;li&gt;07/04/22 (changed name from “Existence requires pain” to “Existence requires survival”)&lt;/li&gt;
&lt;/ul&gt;</description><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Thu, 02 Feb 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/blog/existence-survival/</guid></item><item><title>Links - January 31, 2017</title><link>https://faingezicht.com/links/2017/01/31/links/</link><description>The Trump Administration has been giving me lots of reasons to read on topics that I otherwise would not read about. I want to spend less time on social media trying to parse truth and facts out of the endless stream of articles, but it _feels_ like I have to.</description><author>Avy Faingezicht</author><pubDate>Tue, 31 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/01/31/links/</guid></item><item><title>That Faint Whiff of Failing Statism</title><link>https://one.mikro2nd.net/pages/failing-statism/</link><description>Bushpig poo. Oooh, the stench! That&amp;rsquo;s what Keira the Mighty Hunting Dog has rolled in. Oh, the joys of washing Bushpig poo off a dog of great fur. The smell can haunt the place for days.
So, too, the stink of kleptocracy and state capture.
Occasionally I get the urge to analyse politics and make predictions, despite considering myself to be crap at politics and having a dim view of politicians.</description><author>one mikro2nd</author><pubDate>Mon, 30 Jan 2017 15:31:39 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/failing-statism/</guid></item><item><title>Repository overview now in searchcode server</title><link>https://boyter.org/2017/01/repository-overview-searchcode-server/</link><description>&lt;p&gt;One feature that I have wanted for a long time in searchcode server was a page which would give an overview of a repository. I wanted the overview to give a very high look at the languages used, the total number of files, estimated cost and who would be the best people to talk to.&lt;/p&gt;
&lt;p&gt;One thing that occurred to me when I started work was that it would be nice to calculate a bus factor for the repository as well. After all we all know that project managers do like to know who are the most critical contributors to any project and what the risk is.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 30 Jan 2017 09:34:35 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2017/01/repository-overview-searchcode-server/</guid></item><item><title>Not Today</title><link>https://faingezicht.com/articles/2017/01/30/not-today/</link><description>I was in a bad mood. My flight to SFO had been delayed significantly, and five hours in, our pilot apologized: “Due to strong winds we’ll have to stop in LAX to refuel.” As soon as we landed, I turned off airplane mode and opened Twitter to pass the time while I waited to take off again. One thing was quickly made clear: due to an Executive Order from the White House, green card and visa holders are being detained in airports around the U.S. _Fuck_.

It took me a few seconds of scrolling to realize that it _probably_ wouldn’t affect me. I clicked past a few headlines to learn that the ban was targeted at specific majority-Muslim countries. I, a white guy, with my fluent English, with a German last name, with a student visa tied to a renowned university, with a job at a large Silicon Valley company, _probably_ wouldn’t get caught up in this coming into San Francisco, of all places. I was, and am, acutely aware of my privilege. _But what if?_ The flight from LAX to SFO felt like hours.

On any other occasion, I would have dealt with the drudgery of going through immigration without any worries. It is, for me, basically just a nuisance. Stand in line, hand my passport and forms over, stamp here, stamp there, answer a few questions, get fingerprinted for the hundredth time, and go on with my life to sleep the jet-lag away at home. Not on 1/27/2017. Now I was nervous. “Please walk down to the aisle and turn right, you’ll see the sign for the Secondary Inspection Office.” _Fuck_, again.

It was not my first time going through a secondary inspection (in fact, it is common for students on the &lt;a href="https://en.wikipedia.org/wiki/Optional_Practical_Training"&gt;Optional Practical Training&lt;/a&gt; extension of their F1 visa to get the extra screening) but I had just been at home in Costa Rica to get my visa renewed, and it hadn’t gone smoothly. My passport had been held at the embassy in "&lt;a href="http://lawandborder.com/administrative-processing-black-hole-visa-applicants/"&gt;administrative processing&lt;/a&gt;." No one could tell me when, or if, I could go back to San Francisco, or even leave Costa Rica, for that matter, since I had to hand over my passport to the U.S. Embassy while they processed my visa renewal. No one could tell me why my visa was delayed beyond a hazy "it is out of our hands, we're waiting for clearance from the Department of Homeland Security." A couple of years ago, an acquaintance in a similar situation had to wait eight months before returning to the U.S. I was afraid I’d be on the same boat.

But after two weeks of "administrative processing," I got the phone call. My visa was approved. After anxiously waiting around my parents' house, and endless hours on the phone on hold with the embassy, I was lucky. I had my visa, and I had my passport back. I had to move some things around at work, but my boss had been understanding about the delay, and my job wasn't at risk. Now I was heading home, but the whole experience made me feel alienated. And now this on the way in?

There were another five or so people in the Secondary Inspection waiting room, which was dead quiet. I handed my papers to a customs officer, sat down, pulled out my copy of 1984, and tried to read. Everyone there looked mildly nervous, except for a Middle Eastern looking man who was pacing back and forth. He was visibly terrified. I wanted to comfort him, but two things made me hesitate: I didn't know his story and didn't know what to say, and I was scared that anything I said to him could affect how I was perceived by the customs officers currently deciding whether or not to let me into the country. I didn’t say anything. And later that night, finally at home in my bed, I deeply regretted it.

With this order, Trump and his administration broke a promise to millions of permanent residents and visa-holders in this country. He reminded us that we can get kicked out at any time, for reasons that have nothing to do with who we are or what we've done. Had Trump decided to start with the Bad Hombres instead of the people with ties to Muslim countries, I could be the one detained at SFO. I have not lived in Costa Rica for 7 years, but I could quickly be turned away from my home in San Francisco, barred from going back to my apartment, to my girlfriend, to my friends, to my job, and to the life I've built in the United States. Just because I was not born here.

The political climate of the past few days can’t be diminished. This is not normal. My current visa expires in 2018, and while I am planning to apply for the H1B lottery in a few months, I am not sure that staying is even going to be a real option anymore. I am deeply conflicted.

This week, for the first time ever, I doubted whether I should publish my thoughts. I doubted whether I should offer comfort to a terrified stranger. I doubted whether I would even want to stay in the U.S. long term. All of this because of deeper doubts about whether the country where I've lived for the past six years, which claims to be a nation of immigrants, will tolerate having immigrants here at all.

---
&lt;small&gt;&lt;em&gt;Photo: taken from Mark Suster's &lt;a href="https://bothsidesofthetable.com/dont-let-anybody-tell-you-not-to-speak-up-here-s-why-71d4d73b2e08"&gt;Never Let Anybody Tell You to Shut Up&lt;/a&gt;, source unknown. Please &lt;a href="/contact"&gt;contact me&lt;/a&gt; if you're the owner.&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Mon, 30 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/01/30/not-today/</guid></item><item><title>Content is king</title><link>https://yasha.solutions/content-is-king/</link><description>That’s not new.
That’s also not something people pay enough attention to.
Content is king for a reason.
Content is the expression of your knowledge.
Content is what help you communicate your brand.
Content is what define if you exist or not on the internet.
Content is what connect people with each other.
Content is what make your voice meaningful.
Content is what help you make a difference
For all these reasons and many others, content is king.</description><author>Yasha Solutions</author><pubDate>Mon, 30 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/content-is-king/</guid></item><item><title>Quick Monitor Buying Guide</title><link>https://nitinnain.com/quick-monitor-buying-guide-screen-resolution-size-and-display-types/</link><description>Deciding the screen size You ought to consider the right physical size in inches with the screen resolution — deviating too much from the following chart would either make the screen too pixelated or you might find the default font size to be too small. Screen Resolution &amp;#124; Size in inches --------------------------------&amp;#124;---------------- Full HD (1080p [&amp;#8230;]</description><author>Nitin Nain</author><pubDate>Sun, 29 Jan 2017 05:05:00 GMT</pubDate><guid isPermaLink="true">https://nitinnain.com/quick-monitor-buying-guide-screen-resolution-size-and-display-types/</guid></item><item><title>Plex does not play movies anymore</title><link>https://www.zufallsheld.de/2017/01/28/plex-does-not-play-movies-anymore/</link><description>&lt;p&gt;I use &lt;a href="https://www.plex.tv/"&gt;Plex&lt;/a&gt; to manage and view all my movies, tv shows and music located at my personal &lt;a href="https://www.zufallsheld.de/2013/11/22/freenas-transmission-couchpotato-sickbeard-dlna-server/"&gt;home storage system&lt;/a&gt;. It consists of two&amp;nbsp;programs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Plex Media Server running on my&amp;nbsp;server&lt;/li&gt;
&lt;li&gt;the Android app running on my Android &lt;span class="caps"&gt;TV&lt;/span&gt; box, connected to my tv in the living …&lt;/li&gt;&lt;/ul&gt;</description><author>zufallsheld</author><pubDate>Sat, 28 Jan 2017 23:00:00 GMT</pubDate><guid isPermaLink="true">https://www.zufallsheld.de/2017/01/28/plex-does-not-play-movies-anymore/</guid></item><item><title>Testing is Hard</title><link>https://www.mikekasberg.com/blog/2017/01/28/testing-is-hard.html</link><description>&lt;p&gt;One of my friends and colleagues writes for the &lt;a href="https://www.pmfordevs.com/"&gt;Project Management for
Developers&lt;/a&gt; blog. He recently wrote &lt;a href="https://www.pmfordevs.com/blog/a-case-for-writing-tests"&gt;an
article&lt;/a&gt; about the
importance of testing. I want to respond to his blog post and provide some
additional insight into testing from a developer perspective.&lt;/p&gt;

&lt;p&gt;I’m going to talk mainly about unit tests here because I believe unit tests are
the foundation and most important part of any test suite. But most of the ideas
apply equally well to other types of tests.&lt;/p&gt;

&lt;h2 id="time--coverage"&gt;Time &amp;amp; Coverage&lt;/h2&gt;

&lt;p&gt;Somehow, it’s always easy to find an excuse &lt;em&gt;not&lt;/em&gt; to write tests. You’re
spending too much time on tests. That component isn’t testable. You tested it
manually right? We need to get this out. It’s just too hard to test. The code’s
too old. It’s not &lt;em&gt;worth it&lt;/em&gt;. If you’re a developer, you’ve heard pretty much
all these excuses at one point or another.&lt;/p&gt;

&lt;p&gt;So here’s my advice: &lt;strong&gt;Just write the tests!&lt;/strong&gt; Wherever you think you don’t need
tests, that’s where the bug will be. Every time. It’s &lt;em&gt;almost always&lt;/em&gt; worth it to
have tests. And as you gain more experience, you’ll find testing to be quicker
and easier than you thought it was. Tests catch your bugs when you’re writing
code, and they prevent you from breaking the code when you add a feature a year
or two later.&lt;/p&gt;

&lt;p&gt;Now that I’ve convinced you how important tests are, I’m going to backpedal a
little bit. You’re not likely to ever reach 100% coverage. In fact, 90% or even
80% will be really hard to hit. So be smart about what you test. Test the
components of your code that have the most logic and are most likely to break.
And write a test whenever you fix a bug.&lt;/p&gt;

&lt;h2 id="testing-patterns"&gt;Testing Patterns&lt;/h2&gt;

&lt;p&gt;I mentioned that as you gain more experience writing tests, it becomes quicker
and easier. It’s true, and one of the main reasons for this is that you start to
recognize patterns in your code. When you’re working with old code that doesn’t
have unit tests, you’ll initially find it hard to test. You need to find what
Michael Feathers calls
&lt;a href="https://www.informit.com/articles/article.aspx?p=359417&amp;amp;seqNum=3"&gt;seams&lt;/a&gt;. Places
in your code where you can inject a mock or a stub and run some tests.&lt;/p&gt;

&lt;p&gt;As you start to look for these seams in older code, you also start adding them
to new code as you’re designing it. You don’t want to have to refactor your new
code just to test it later on, so you make it easy to test from the beginning.
You’ll start thinking about things like &lt;a href="https://en.wikipedia.org/wiki/Dependency_injection#Without_dependency_injection"&gt;dependency
injection&lt;/a&gt;
when you’re writing your constructors. Test driven development forces you to
write code that’s testable. But even if you’re not doing strict test driven
development, your code will be easier to test if you think about how you’ll test
it when you write it. This means less time spent testing, better test coverage,
and more reliable code.&lt;/p&gt;

&lt;h2 id="think-about-your-client"&gt;Think About your Client&lt;/h2&gt;

&lt;p&gt;No matter what type of application you’re working with, well-written tests
provide a huge amount of value that is not immediately apparent. When you write
tests, you’re making an investment in the quality (especially long-term) of your
application. Your clients are always going to want their code sooner, and tests
may seem like a bad trade-off when it delays this week’s release a couple of
days. This is why it’s important to explain to your clients the value that tests
provide. In the long run, you’re better off having tests, and it may even
increase your team’s development speed down the road.&lt;/p&gt;

&lt;h2 id="in-summary"&gt;In Summary&lt;/h2&gt;

&lt;p&gt;As a software developer, your job is to deliver working code to your client.
Tests are one of the tools that enable you do do this. If you’re delivering code
that doesn’t have good test coverage, you’re much more likely to be delivering
buggy code. Experienced developers know this inherently because they find bugs
pretty much every time they write tests. As a professional software developer,
it’s part of your job to understand this, to help your client make informed
decisions, and to deliver well-tested and bug-free software.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sat, 28 Jan 2017 20:30:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2017/01/28/testing-is-hard.html</guid></item><item><title>Hello, TensorFlow</title><link>https://liza.io/hello-tensorflow/</link><description>&lt;p&gt;I&amp;rsquo;ve recently discovered Safari Books Online thanks to a post on HackerNews. One of the first things that caught my eye was one of the Oriole Online Tutorials - Hello, TensorFlow. It was a very quick overview of TensorFlow in a really cool format. There was a video with an accompanying article (which can autoscroll along with the video contents) and code snippets embedded on the page which you can actually work with and run in the browser.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 28 Jan 2017 13:18:18 GMT</pubDate><guid isPermaLink="true">https://liza.io/hello-tensorflow/</guid></item><item><title>New year, new site!</title><link>http://evantravers.com/articles/2017/01/28/new-year-new-site/</link><description>&lt;p&gt;&lt;img alt="Sarah and me, by Meghan Murphy" src="https://images.evantravers.com/articles/2017/01/newyear.jpg" /&gt;&lt;/p&gt;&lt;p&gt;It's been too long guys.  I'm sorry I've been away... I've been... busy.&lt;/p&gt;
&lt;p&gt;&lt;img alt="my wedding" src="https://images.evantravers.com/articles/2017/01/sarahandme.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;It's been a wild ride, but the Lord has been very good, and for some reason I
haven't felt the need to post angsty/honest prayers to the world. I spent a
couple of years praying for joy... and the Lord provided me the greatest source
of joy I have ever known. I love her dearly, and consider myself the most
blessed man ever.&lt;/p&gt;
&lt;p&gt;I have missed writing though, even though I've written quite a bit just for
myself, but each time I sat down to share something I got caught
fixing/tweaking my website rather than writing, and eventually got so far down
the rabbit hole that my site didn't even build anymore... so I tore it down to
the ground and rebuilt it. This is the result.&lt;/p&gt;
&lt;p&gt;I've got some code thoughts, some prayers, some random stories and rants
brewing in my brain, so hopefully this is a first step to sharing some Phil 4:8
style posts.&lt;/p&gt;
&lt;p&gt;I'll likely keep tweaking too... I've learned a lot and I want to try it out on
my website, but I figured I'd get the basics up first.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Engagement and wedding images by &lt;a href="http://www.astillbreath.com/"&gt;Meghan
Murphy&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description><author>trv.rs</author><pubDate>Sat, 28 Jan 2017 03:24:00 GMT</pubDate><guid isPermaLink="true">http://evantravers.com/articles/2017/01/28/new-year-new-site/</guid></item><item><title>Separate Your Email From Your Identity</title><link>https://www.craigpardey.com/post/2017-01-28-separate-email-identity/</link><description>&lt;p&gt;Your email address identifies you in this online world.  Companies use it to verify who you are, to communicate with you and for resetting passwords. You may also use the same email address to correspond with your friends and family, and it may even be linked to your calendar too.&lt;/p&gt;
&lt;p&gt;It makes sense to separate your personal email from your work email - you don&amp;rsquo;t send personal emails from your work address, nor do you send work emails from your personal address.  In all likelihood you use a free service like Gmail, Hotmail, AOL or Yahoo for your personal email.&lt;/p&gt;</description><author>Craig Pardey</author><pubDate>Sat, 28 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.craigpardey.com/post/2017-01-28-separate-email-identity/</guid></item><item><title>Social Analytics</title><link>https://macleodsawyer.com/blog/i-am-tired-of-analytics/</link><description>&lt;p&gt;For the last several years of my life I have subjected myself to a numbers game that everyone is taking part in.&lt;/p&gt;
&lt;p&gt;I love to write, but I have noticed a depressing result of publishing on existing platforms and there is a singular reason for why I left behind a million followers:&lt;/p&gt;
&lt;p&gt;Analytics.&lt;/p&gt;
&lt;p&gt;Every single platform, Medium, Tumblr, Wordpress, Facebook, and Twitter all have some form of analytical value that they append to writing. Likes, comments, reads, views, recommends, shares, and more are the epicenter of the content that is published.&lt;/p&gt;
&lt;p&gt;A small subset of people create the content, but the honest truth is that the epicenter of the products and platforms are the analytics that are created from that content. I want to write to be an individual for my own personal informational purposes. If other people learn and get an emotional response or attachment then that is great, but I don’t want to associate a number to the content. If I were to write a post, and I see that it doesn’t do as well as some of my other writings then I will naturally correct the rest of my writing to fit into the paradigm of my more popular posts. I don’t want to A/B test my writing to match the audience. I want to write to match my thoughts.&lt;/p&gt;
&lt;p&gt;I could write these all privately and never worry about them, but the issue with a private journal is that you can’t learn or grow from them. You can’t subject yourself to finding people who have similar thoughts. I write for myself, but to also help myself find like minded people or to help those that are struggling with similar thoughts and want to see into someone else’s mind and be affirmed.&lt;/p&gt;
&lt;p&gt;Having thoughts that you believe you are alone in is a punishment onto itself. It’s putting yourself into a cage of self deprivation that is constantly demoralizing and detrimental to your mental health. I don’t know if anyone will learn from my thoughts, but I am in hopes of it. If there is even a chance of helping someone feel more comfortable with themselves that is a success. I want my thoughts to be free and uncensored, but I also want others to be able to read them not for my own personal ego, but to help them realize who they are.&lt;/p&gt;
&lt;p&gt;I have some unconventional thoughts about myself and the world around us, I know I’m not alone in any of them — but some people do and I want to help. Posting my thoughts to larger platforms filters and censors my thoughts by forcing myself into an A/B test cage. I don’t want to do that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Appending analytical value to content is antithetical to the point of content.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Content is meant to be free, and meant to help others and ourselves.&lt;/p&gt;
&lt;p&gt;This won’t be the last time I write about this, I think about this a lot.&lt;/p&gt;</description><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Sat, 28 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/blog/i-am-tired-of-analytics/</guid></item><item><title>Monitoring Jupyter Notebooks with Munin</title><link>https://blog.tafkas.net/2017/01/28/monitoring-jupyter-notebooks-with-munin/</link><description>Recently, I set up Jupyter Notebooks on a server at work. The idea was to create an enviroment where every team member could run analyses using Python and share the results with the rest.
After reading the documentation, I found out that the Jupyter Notebook web application comes with a Contents API
I quickly put together a little Munin script that collects some statistics about the current notebooks.
The graph shows the total number of notebooks on the server as well as the currently open notebooks:</description><author>Tafkas Blog</author><pubDate>Sat, 28 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/2017/01/28/monitoring-jupyter-notebooks-with-munin/</guid></item><item><title>Sense8: Happy F... New Year</title><link>https://olshansky.info/tv/sense8_happy_f..._new_year/</link><description>Olshansky's review of Sense8: Happy F... New Year</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 27 Jan 2017 14:22:26 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/sense8_happy_f..._new_year/</guid></item><item><title>Level 1 Web Development</title><link>https://peterlyons.com/problog/2017/01/level-1-web-development/</link><description>&lt;p&gt;Recently I've been thinking about the scope of web development and the lack of clear boundaries. So much of being a "web developer" is a giant unbounded field of deep topics. JavaScript has become a very large language in terms of syntax, semantics, and features in addition to the 20 years of legacy quirks and inconsistencies we never remove. HTML again gets complex fast once you start building realistic applications and trying to balance semantics, accessibility, SEO, etc. CSS3 also has a tremendous scope including transforms, animations, etc.&lt;/p&gt;
&lt;p&gt;What I've been thinking about is would it be empowering to beginners to clearly define and name small subsets of these that can be realistically taught and learned in a fixed time frame (say 6 or 12 months just to throw out some numbers)?&lt;/p&gt;
&lt;p&gt;So just to flesh this out, let's say we took a subset of HTML elements and attributes that are the key building blocks and focused on those and clearly put all the more obscure tags, complex attributes and interactions off in a different set. We label this something like HTML5 Level 1. Forget about &lt;code&gt;object&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;audio&lt;/code&gt;, &lt;code&gt;dd&lt;/code&gt;, &lt;code&gt;cite&lt;/code&gt;, etc - for now.&lt;/p&gt;
&lt;p&gt;Same thing for CSS. Focus on the basics of simple layouts, colors, sizing. Enough to get some basic text and a few images on the page looking OK in all viewports. Basic class and nested selectors but no fancy attribute matching. No transforms or animations. No tweaking word wrapping or overflow, etc.&lt;/p&gt;
&lt;p&gt;For JavaScript it's trickier and I'd actually like to see an entirely new language (could compile to JS perhaps) but the main idea is that the scope is bounded. You can do basic programming but maybe not top-tier million-user webapp optimizations or complexity. You don't have to get explainations about how IE8 did something weird and then the spec adopted it. Forget metaprogramming, prototypes, generators, multiple syntaxes for similar concepts, regular expressions etc.&lt;/p&gt;
&lt;p&gt;I'd like to see self-taught folks and bootcamp grads be able to say "I'm proficient in Front End Web Development 2017.1" with confidence. I'd like them to know they can go on a job interview and have worked with everything in that defined scope. No surprises. No anxiety. No "I'll probably do OK as long as they don't ask me to build a complex table". I'd like to see companies be able to put these people to productive work and say "On day 1 we hope to see you submit a pull request using Front End Web Development 2017.1 tools. On day 180, we'll have trained you up to 2017.2".&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 26 Jan 2017 22:19:46 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2017/01/level-1-web-development/</guid></item><item><title>The Marathon obsession</title><link>https://honza.pokorny.ca/2017/01/the-marathon-obsession/</link><description>&lt;p&gt;This morning, I read a rather click-baity &lt;a href="http://runningmagazine.ca/11-questions-runners-hate-answering/"&gt;article&lt;/a&gt; about the kinds of
questions that runners hate answering.  Honestly, I don&amp;rsquo;t know why I clicked it
&amp;mdash; blame it on lack of coffee in my blood stream.  A common theme in the
article is the obsession with the marathon.  When are you running your first
marathon?  Are you training for Boston?  The writer then goes on to say that
she is perfectly happy with her 5ks and 10ks.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also tired of the marathon obsession,  but from the other end of the
spectrum.  The marathon distance isn&amp;rsquo;t the pinnacle of a runner&amp;rsquo;s career.  You
can run further.  Your legs don&amp;rsquo;t magically stop working after 42.2km.&lt;/p&gt;
&lt;p&gt;The following quote from Christopher McDougall&amp;rsquo;s &lt;em&gt;Born to run&lt;/em&gt; gives us a nice
glimpse into the mindset of an ultra runner.  This tiny section is one of my
favorite parts in the book.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;So why not marathons?&amp;rdquo; I asked Jenn when I called to interview her about
the Young Guns. &amp;ldquo;Do you think you could qualify for the Olympic Trials?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Dude, seriously,&amp;rdquo; she&amp;rsquo;d said. &amp;ldquo;The qualifying standard is 2:48. Anyone can
make it.&amp;rdquo; Jenn could run a sub-three-hour marathon while wearing a string
bikini and chugging a beer at mile 23-and she would, just five days after
running a 50-mile trail race in the Blue Ridge Mountains.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;But then what?&amp;rdquo; Jenn went on. &amp;ldquo;I hate all this hype about the marathon.
Where&amp;rsquo;s the mystery? I know a girl who&amp;rsquo;s training for the Trials, and she&amp;rsquo;s
got every single workout planned for the next three years! She&amp;rsquo;s doing
speedwork on the track like, every other day. I couldn&amp;rsquo;t take it, man. I
was supposed to run with her once at six in the morning, and I called her
up at two a.m. to tell her I was shitfaced on margaritas and puh-robably
not gonna make it.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Jenn didn&amp;rsquo;t have a coach or a training program; she didn&amp;rsquo;t even own a
watch. She just rolled out of bed every morning, downed a veggie burger,
and ran as far and as fast as she felt like, which usually turned out to be
about twenty miles. Then she hopped on the skateboard she&amp;rsquo;d bought instead
of a parking pass and kicked off to class at Old Dominion, where she&amp;rsquo;d
recently dropped back into school and was making straight As.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>Honza Pokorný</author><pubDate>Thu, 26 Jan 2017 14:35:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/01/the-marathon-obsession/</guid></item><item><title>ROS on arm64 with Ubuntu Core</title><link>https://kyrofa.com/posts/ros-on-arm64-with-ubuntu-core/</link><description>Previous Robot Operating System (ROS) releases only supported i386, amd64, and armhf. I even tried building ROS Indigo from source for arm64 about a year ago, but ran into dependency issues with a missing sbcl. Well, with surprisingly little fanfare, ROS Kinetic was released with support for arm64 in their prebuilt archive! I thought it might be time to take it for a spin with Ubuntu Core and its arm64 reference board, the DragonBoard 410c, and thought I&amp;rsquo;d take you along for the ride.</description><author>kyrofa's blog</author><pubDate>Thu, 26 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-on-arm64-with-ubuntu-core/</guid></item><item><title>Quick vIM Tips That Will Save Your Life</title><link>https://lucasfcosta.com/blog/Quick-vIM-Tips-That-Will-Save-Your-Life/</link><description>Hello, everyone! This week I'm a bit out of ideas for blog posts about programming, so I decided to write about vIM!

I have already written a blog post teaching people how to get started with it, bu...</description><author>Lucas F. Costa - Blog</author><pubDate>Mon, 23 Jan 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Quick-vIM-Tips-That-Will-Save-Your-Life/</guid></item><item><title>Wolfram's automata, a simple implementation with Python</title><link>https://faingezicht.com/articles/2017/01/23/wolfram/</link><description>Complexity science is one of my favorite topics, ever. Studying complexity is how I ended up in the computer science bandwagon in the first place, and I constantly find myself thinking about how individual agents' decisions affect the overall state of systems. Self-organization and emergence are fundamental aspects of how the pieces of the complexity puzzle fit together, and Wolfram's elementary cellular automata are a great way to understand them.

From Wikipedia[^1], these are "one-dimensional cellular automata where there are two possible states (labeled 0 and 1) and the rule to determine the state of a cell in the next generation depends only on the current state of the cell and its two immediate neighbors." This sounds complicated, but in reality it is just complex, and can be explained with quite simply.

For example, the animation above is a run of &lt;a href="http://mathworld.wolfram.com/Rule30.html"&gt;Rule 30&lt;/a&gt;[^2], which can be visualized easily:
&lt;img alt="rule-30" id="rule-30" src="https://cdn.faingezicht.com/30.png" /&gt;

Which represented by a Python `dict` looks like:

```python
rule = {"111": '0', "110": '0', "101": '0', "000": '0',
        "100": '1', "011": '1', "010": '1', "001": '1'}
```

In this dictionary, each triplet ("the current state of the cell and its two immediate neighbors") points to "the state of a cell in the next generation." Basic arithmetic can show us that there will always be 8 states to consider in one of these rules.

Generating a pattern is just a matter of breaking some initial state into triplets, and iterating over the groups. An initial state, or seed, might look like this:

```python
initial_state = '00000000000000000000100000000000000000000'
```

As we just saw, we calculate the next state for each cell by looking at groups of three cells at a time. This can be done with a windowing function:

```python
def window(iterable, stride=3):
    for index in range(len(iterable) - stride + 1):
        yield iterable[index:index + stride]
```

The behavior of this function is pretty simple, and is best shown by example:

```python
# notice that window is a generator
&gt;&gt;&gt; window('foobar')

&gt;&gt;&gt; list(window('foobar'))
['foo', 'oob', 'oba', 'bar']
```

If we apply this to our seed, we get what we'd expect, and computing the next state is quite straightforward: for every triplet, we look up the corresponding next state, and join it into a new string.

```python
# &gt;&gt;&gt; list(window(initial_state))
# ['000', '000', '000', '000', '000', '000', '000', '000',
#  '000', '000', '000', '000', '000', '000', '000', '000',
#  '000', '000', '001', '010', '100', '000', '000', '000',
#  '000', '000', '000', '000', '000', '000', '000', '000',
#  '000', '000', '000', '000', '000', '000', '000']

patterns = window(initial_state)
new_state = ''.join(rule[pat] for pat in patterns)

# &gt;&gt;&gt; print(new_state)
# 00000000000000000111000000000000000000
```

It isn't hard to see how repeating the same process again and again will give us the kind of behavior we see in the original animation. However, we need to add a bit of padding to accommodate for the special conditions of our (literal) edge cases, or we'll shrink by two cells when processing each row.

```python
# non-padded
state = initial_state
for _ in range(15):
    patterns = window(state)
    state = ''.join(rule[pat] for pat in patterns)
    print(state)

# 00000000000000000000100000000000000000000
# 000000000000000000111000000000000000000
# 0000000000000000110010000000000000000
# 00000000000000110111100000000000000
# 000000000000110010001000000000000
# 0000000000110111101110000000000
# 00000000110010000100100000000
# 000000110111100111111000000
# 0000110010001110000010000
# 00110111101100100011100
# 110010000101111011001
# 0111100110100001011
# 10001110011001101
# 101100111011100
# 0101110001001
# 10100101111

# padded
def generate_pattern(state, rule):
    for time in range(MAX_TIME):
        print(state)
        patterns = window(state)
        state = ''.join(rule[pat] for pat in patterns)
        state = '0{}0'.format(state)
    print(state)

# &gt;&gt;&gt; generate_pattern(initial_state, rule)
# 00000000000000000000100000000000000000000
# 00000000000000000001110000000000000000000
# 00000000000000000011001000000000000000000
# 00000000000000000110111100000000000000000
# 00000000000000001100100010000000000000000
# 00000000000000011011110111000000000000000
# 00000000000000110010000100100000000000000
# 00000000000001101111001111110000000000000
# 00000000000011001000111000001000000000000
# 00000000000110111101100100011100000000000
# 00000000001100100001011110110010000000000
# 00000000011011110011010000101111000000000
# 00000000110010001110011001101000100000000
# 00000001101111011001110111001101110000000
# 00000011001000010111000100111001001000000
# 00000110111100110100101111100111111100000
```

Clearly, different rules, and different seeds, will give you different patterns:

```python
RULES = {30: {"111": '0', "110": '0', "101": '0', "000": '0',
              "100": '1', "011": '1', "010": '1', "001": '1'},

         90: {"111": "0", "110": "1", "101": "0", "100": "1",
              "011": "1", "010": "0", "001": "1", "000": "0"},

         110: {"111": '0', "110": '1', "101": '1', "100": '0',
               "011": '1', "010": '1', "001": '1', "000": '0'},

         184: {"111": "1", "110": "0", "101": "1", "100": "1",
               "011": "1", "010": "0", "001": "0", "000": "0"}
         }

# generate_pattern(initial_state, RULES[110])
# 00000000000000000000100000000000000000000
# 00000000000000000001100000000000000000000
# 00000000000000000011100000000000000000000
# 00000000000000000110100000000000000000000
# 00000000000000001111100000000000000000000
# 00000000000000011000100000000000000000000
# 00000000000000111001100000000000000000000
# 00000000000001101011100000000000000000000
# 00000000000011111110100000000000000000000
# 00000000000110000011100000000000000000000
# 00000000001110000110100000000000000000000
# 00000000011010001111100000000000000000000
# 00000000111110011000100000000000000000000
# 00000001100010111001100000000000000000000
# 00000011100111101011100000000000000000000
# 00000110101100111110100000000000000000000
```

Surprisingly, these really simple mappings, which can be encoded in only 8 bits, can be used to model very complex behavior. Simple rules quickly give way to complexity, and it is &lt;a href="https://en.wikipedia.org/wiki/Cellular_automaton#Modeling_physical_reality"&gt;likely&lt;/a&gt; that much of our world behaves according to similar, although more complex mappings.

There are all sorts of interesting mathematic properties behind how these automata actually work, and what kind of patterns arise from them, which are beyond the scope of this post. The fact that Stanislaw Ulam and John von Neumann were studying automata back in the 40s[^3] with the first electronic computers shows how fundamental these concepts are. Wolfram's book on the topic is &lt;a href="http://www.wolframscience.com/nksonline/toc.html"&gt;freely available online&lt;/a&gt;, and while I have only read bits and pieces of it, I am sure it does a better job of explaining them than I could without overloading the basic mechanics.

To download a runnable version of this script, and give this a shot on your own, you can find my code &lt;a href="https://github.com/avyfain/automata"&gt;here&lt;/a&gt;.

&lt;a href="https://twitter.com/intent/tweet?text=Hey+%40avyfain%2C+just+read+your+post+faingezicht.com%2Farticles%2F2017%2F01%2F23%2Fwolfram%2F%20and..."&gt;Tweet at me&lt;/a&gt; and let me know what you think!

---
[^1]: Wikipedia Contributors. &lt;a href="https://en.wikipedia.org/w/index.php?title=Elementary_cellular_automaton&amp;amp;oldid=734235050"&gt;Elementary cellular automaton.&lt;/a&gt;, &lt;i&gt;Wikipedia, The Free Encyclopedia&lt;/i&gt;.
[^2]: &lt;a href="http://mathworld.wolfram.com/about/author.html"&gt;Weisstein, Eric W.&lt;/a&gt; &lt;a href="http://mathworld.wolfram.com/Rule30.html"&gt;"Rule 30."&lt;/a&gt; From &lt;i&gt;MathWorld, A Wolfram Web Resource&lt;/i&gt;.
[^3]: &lt;a href="http://embryo.asu.edu/handle/10776/2009"&gt;"John von Neumann's Cellular Automata"&lt;/a&gt;. &lt;i&gt;Embryo Project Encyclopedia&lt;/i&gt;.</description><author>Avy Faingezicht</author><pubDate>Mon, 23 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/01/23/wolfram/</guid></item><item><title>Surprise, you're in Costa Rica now!</title><link>https://faingezicht.com/photos/2017/01/23/costa-rica/</link><description>I had to arrange a last minute trip home to renew my visa in order to go to a different trip later this year. Now I am stuck here for a few days. Hopefully I won't have enough time to do another set of Costa Rica photos, but who knows.</description><author>Avy Faingezicht</author><pubDate>Mon, 23 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/01/23/costa-rica/</guid></item><item><title>The Accountant</title><link>https://olshansky.info/movie/the_accountant/</link><description>Olshansky's review of The Accountant</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 22 Jan 2017 13:01:50 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_accountant/</guid></item><item><title>Tel Aviv travel bookmarks</title><link>https://xenodium.com/tel-aviv-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;Breakfast club (dancing).&lt;/li&gt;
&lt;li&gt;Claro/Sarona Market.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Dizengoff_Square"&gt;Dizengoff Square - Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Drink Cafe hafuch at Rothschild 12.&lt;/li&gt;
&lt;li&gt;Jaffa's Flea market.&lt;/li&gt;
&lt;li&gt;Nightlife: Kuli Alma's hipster haven. Imperial craft cocktail bar (drink Gold fashioned).&lt;/li&gt;
&lt;li&gt;Park HaYarkon.&lt;/li&gt;
&lt;li&gt;Tel Aviv museum of art.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 22 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/tel-aviv-travel-bookmarks</guid></item><item><title>Jerusalem travel bookmarks</title><link>https://xenodium.com/jerusalem-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;Jerusalem: Rooftop Mamilla restarurant.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 22 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/jerusalem-travel-bookmarks</guid></item><item><title>Nepal travel bookmarks</title><link>https://xenodium.com/nepal-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.erikastravelventures.com/annapurna-circuit-itinerary/"&gt;Annapurna Circuit Itinerary - Erika's Travelventures&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.planetware.com/pictures/nepal-nep.htm"&gt;Nepal in Pictures: 19 Beautiful Places to Photograph&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Patan_Durbar_Square"&gt;Patan Durbar square&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vargiskhan.com/log/truth-behind-mysterious-magnetic-hill-of-ladakh/"&gt;The Truth Behind the Mysterious Magnetic Hill of Ladakh - Vargis Khan&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 22 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/nepal-travel-bookmarks</guid></item><item><title>Links - January 22, 2017</title><link>https://faingezicht.com/links/2017/01/22/links/</link><description>The new year has received me with a lot of reading, but of the dead tree variety. I'm halfway with books #3 and #4 of the year by now. I guess an unexpected trip, and an even more unexpected stay in Costa Rica helped too.</description><author>Avy Faingezicht</author><pubDate>Sun, 22 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/01/22/links/</guid></item><item><title>Migration of Site to Hugo!</title><link>https://rob.sh/post/hugo-site/</link><description>&lt;p&gt;&lt;strong&gt;Welcome&lt;/strong&gt; to a new rob.sh, apologies for the outage. I needed to migrate the site to something that was lower maintenance.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m working on migrating the old rob.sh content to this new site, but it may take a little time to do so. Please let me
know if there are specific articles from the old site that you&amp;rsquo;d like me to prioritise! The site now uses &lt;a href="http://gohugo.io"&gt;hugo&lt;/a&gt;
rather than django. This means that I can avoid running a bunch of backend infrastructure.&lt;/p&gt;</description><author>rob.sh</author><pubDate>Sat, 21 Jan 2017 19:13:13 GMT</pubDate><guid isPermaLink="true">https://rob.sh/post/hugo-site/</guid></item><item><title>Will Offering Discounts Keep Customers?</title><link>https://solomon.io/will-offering-discounts-keep-customers/</link><description>Here’s the scenario: You have a subscription business and you know a customer is leaving. Should you offer a discount to entice them to stay?</description><author>Sam Solomon</author><pubDate>Sat, 21 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/will-offering-discounts-keep-customers/</guid></item><item><title>Mobile Chrome vh units fix</title><link>https://muffinman.io/blog/mobile-chrome-vh-units-fix/</link><description>&lt;article class="article"&gt;&lt;h3 id="update-march-2019"&gt;Update March 2019 &lt;a class="anchor-link" href="#update-march-2019"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Check &lt;a href="https://css-tricks.com/the-trick-to-viewport-units-on-mobile/"&gt;this fix&lt;/a&gt; too. It works really well in most cases.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you ever used &lt;code&gt;vh&lt;/code&gt; units and tested your work on mobile Chrome (iOS and Android),
you probably were annoyed by page jumping when you scroll.&lt;/p&gt;
&lt;p&gt;As you probably know &lt;code&gt;vh&lt;/code&gt; units are based on the window height.
When you scroll, Chrome&amp;#x27;s address bar disappears and chrome actually changes window height.
Also triggers window resize event.
So when it does happen it changes the value of &lt;code&gt;vh&lt;/code&gt; unit, making your elements resize,
and page jump. On Android, keyboard toggle will do the same.&lt;/p&gt;
&lt;p&gt;Well I made a plain JavaScript library to solve this problem.&lt;/p&gt;
&lt;p&gt;Demo and documentation are available &lt;a href="https://muffinman.io/mobile-chrome-vh-fix/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="how-does-it-work"&gt;How does it work? &lt;a class="anchor-link" href="#how-does-it-work"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On load, it will get the element and set them fixed height in pixels,
using this formula:&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;window height / &lt;span class="token number"&gt;100&lt;/span&gt; * given vh value
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Library listens for the window &lt;code&gt;resize&lt;/code&gt; event, and only if both dimensions are changed
(which on mobile means orientation has changed)
it will recalculate and apply fixed height based on new window height. Please note that Android Chrome has a bug - when keyboard pops up, it triggers orientation change&lt;/p&gt;
&lt;p&gt;Library will only do this if it detects Chrome on Android or iOS.&lt;/p&gt;
&lt;h2 id="usage"&gt;Usage &lt;a class="anchor-link" href="#usage"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It accepts one parameter, which is an array of objects.
Every object should have CSS selector and height in &lt;code&gt;vh&lt;/code&gt; units.
All elements that match given selector will be fixed.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;var&lt;/span&gt; options &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    selector&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;.Bears&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token comment"&gt;// Mandatory, CSS selector&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    vh&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;150&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;  &lt;span class="token comment"&gt;// Mandatory, height in vh units&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    selector&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;.Foxes&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    vh&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;50&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    selector&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;.Horses&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    vh&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token number"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;]&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;var&lt;/span&gt; vhFix &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;new&lt;/span&gt; &lt;span class="token class-name"&gt;VHChromeFix&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;options&lt;span class="token punctuation"&gt;)&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="react-component-is-wip"&gt;React Component is WIP &lt;a class="anchor-link" href="#react-component-is-wip"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have a React component already done in a another project,
but I need to extract it, and pack it up as a separate &lt;code&gt;npm&lt;/code&gt; package for easier usage.&lt;/p&gt;
&lt;p&gt;Grab the code on &lt;a href="https://github.com/Stanko/mobile-chrome-vh-fix"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sat, 21 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/mobile-chrome-vh-units-fix/</guid></item><item><title>Growing Teams and Baking Bread</title><link>https://ntietz.com/blog/growing-teams-and-baking-bread/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;One of the keys in baking bread is getting the dough to rise well. As the yeast does its work, it ferments some of the sugars in the dough into alcohol and carbon dioxide, resulting in a growing, bubbly mass of dough.&lt;/p&gt;
&lt;p&gt;There are some tricks to making dough rise quickly, like using more yeast, using instant yeast, or even with a &lt;a href="http://www.thekitchn.com/proof-your-bread-dough-in-the-microwave-35685"&gt;microwave&lt;/a&gt;. These are methods of convenience, because they let you get the finished product out the door more quickly so you can eat your delicious bread.&lt;/p&gt;
&lt;p&gt;But how do you make truly great bread? One of the ways to make a great bread is to give it a much longer time to rise. With a quick rise, a lot of the flavors are underdeveloped. For a simple sandwich bread, that might be okay. But for an artisanal crusty loaf, these flavors lend complexity of flavor and depth of development which is key. Those flavors come from having a long, slow rise, where the yeast can take its time fermenting and the flavors can develop, lending subtleties and complexities. A long rise also helps with good gluten formation, where the yeast will develop it naturally instead of requiring a lot of kneading to force everything into line.&lt;/p&gt;
&lt;p&gt;The same is true with growing a team.&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; grow teams quickly, but by doing so, cohesion doesn't happen naturally and you have to force it, and the team culture that forms isn't as natural as the team culture if you grow a team slowly over time.&lt;/p&gt;
&lt;p&gt;In contrast, if you grow a team slowly and organically over a longer period, you reap a lot of benefits. The team works out a lot of problems with cohesion naturally over time (instead of in rapid, very painful periods) and they will all grow together, leading to a very strong shared culture with similar values and similar goals.&lt;/p&gt;
&lt;p&gt;There are definitely some situations where rapid growth is needed or beneficial, but it is worth thinking about whether or not it is necessary. A long, slow rise can make a unique team that has strong cohesion, and a more sustainable one at that.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Sat, 21 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/growing-teams-and-baking-bread/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Annual report number 11 + 12: My Success</title><link>https://www.jimwestergren.com/annual-report-number-11-12-my-success</link><description>Back in December of 2004 I started a new life from zero. I was 22 years old without any money, education or connections. I borrowed my mothers computer and started to learn HTML and internet marketing. Each year I publish an annual report. Earlier reports are linked from the history section in my about page. &amp;#91;...&amp;#93;</description><author>Jim Westergren</author><pubDate>Fri, 20 Jan 2017 09:50:00 GMT</pubDate><guid isPermaLink="true">https://www.jimwestergren.com/annual-report-number-11-12-my-success</guid></item><item><title>Three Mathematical Models for Building a More Valuable Company</title><link>https://www.codingvc.com/p/three-mathematical-models-for-building-a-more-valuable-company</link><description>&amp;#8220;All models are wrong, but some are useful.&amp;#8221;</description><author>Coding VC</author><pubDate>Fri, 20 Jan 2017 07:10:00 GMT</pubDate><guid isPermaLink="true">https://www.codingvc.com/p/three-mathematical-models-for-building-a-more-valuable-company</guid></item><item><title>Water consumption</title><link>https://honza.pokorny.ca/2017/01/water-consumption/</link><description>&lt;p&gt;During the 2016 edition of the Super Bowl, Colgate ran an ad highlighting our
overconsumption of water during tooth-brushing.  The ad is emotinally charged
with images of people from poverty-ridden countries.  You can watch it below.&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe width=&amp;ldquo;560&amp;rdquo; height=&amp;ldquo;315&amp;rdquo; src=&amp;quot;&lt;a href="https://www.youtube.com/embed/IS4lGnGfHTw"&gt;https://www.youtube.com/embed/IS4lGnGfHTw&lt;/a&gt;&amp;quot; frameborder=&amp;ldquo;0&amp;rdquo; allowfullscreen=&amp;ldquo;true&amp;rdquo;&amp;gt;&amp;lt;/iframe&amp;gt;Colgate claim that you waste up to 4 gallons (15L) of water if you leave the
fauset running.  They intend to guilt you into conserving water.&lt;/p&gt;
&lt;p&gt;On a global scale, turning the fauset off when you brush your teeth will have a
minimal effect.  And not because you are only a single person making a change.
Domestic consumption accounts for only about 5% of water use.  If we all made a
change leading to a reduction of water consumption by 50%, the overall domestic
use would drop to 2.5%.  And 50% is pretty dramatic.&lt;/p&gt;
&lt;p&gt;So, who is using all the water in the world?  According to the ground-breaking
research by the people behind the &lt;a href="http://www.cowspiracy.com/"&gt;Cowspiracy&lt;/a&gt; documentary, 55% of water
consumption in the United States goes towards animal agriculture.  An immense
amount of water is required to produce meat and dairy products.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/cowspiracy.png" /&gt;
&lt;/figure&gt;

&lt;p&gt;So instead of worrying about the running tap, we should stop eating meat and
dairy.  Doing so will have a much more significant impact on the world.  But of
course, that isn&amp;rsquo;t as feel-good as the tooth-brushing story.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Thu, 19 Jan 2017 18:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2017/01/water-consumption/</guid></item><item><title>Melting the Snow on Hester Street</title><link>https://apurva-shukla.me/bookshelf/melting-the-snow-on-hester-street/</link><description>⭐ ⭐ ⭐ A timid little book filled with the overflowing riches and glamour of the golden age of Hollywood. It contains the decadence of this…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Thu, 19 Jan 2017 02:32:16 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/melting-the-snow-on-hester-street/</guid></item><item><title>I'm Skipping the 2016 MacBook Pro</title><link>https://solomon.io/im-skipping-2016-macbook-pro/</link><description>I’ve been waiting for two years to see what Apple had in store for their new MacBook Pro. After much deliberation. I’ve decided to skip the 2016 MacBook Pro.</description><author>Sam Solomon</author><pubDate>Wed, 18 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/im-skipping-2016-macbook-pro/</guid></item><item><title>Deploying React (Router) app to the subfolder on server</title><link>https://muffinman.io/blog/react-router-subfolder-on-server/</link><description>&lt;article class="article"&gt;&lt;ul&gt;
&lt;li&gt;May 2018 - Updated to match React Router v4 API.&lt;/li&gt;
&lt;li&gt;September 2019 - Updated to match React Router v5 API, added React Create App part.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you ever had to deploy React Router app to the subfolder on the server, you know what the problem is.
Routes will get messed up once you upload it to the server.
Here are two solutions I use in these cases.&lt;/p&gt;
&lt;h2 id="easy-way-just-use-hashrouter"&gt;Easy way, just use &lt;code&gt;HashRouter&lt;/code&gt; &lt;a class="anchor-link" href="#easy-way-just-use-hashrouter"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The easiest way to achieve this is to use &lt;code&gt;HashRouter&lt;/code&gt; instead of &lt;code&gt;BrowserRouter&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;HashRouter&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Route&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-router-dom&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Then in render&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;HashRouter&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Route&lt;/span&gt; path&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;/&amp;#x27;&lt;/span&gt; component&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Home&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt; exact &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Route&lt;/span&gt; path&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;/about&amp;#x27;&lt;/span&gt; component&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;About&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt; exact &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;span class="token comment"&gt;/*...*/&lt;/span&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;HashRouter&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the best approach if your subfolder name changes
(for example, if folder name is a build version).
But you&amp;#x27;ll have &lt;code&gt;/#/&lt;/code&gt; included in the every URL.
If this bothers you, check the second solution.&lt;/p&gt;
&lt;p&gt;Example of the routes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://yourserver.com/path/to/subfolder/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://yourserver.com/path/to/subfolder/#/about&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://yourserver.com/path/to/subfolder/#/search&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="hard-way-setting-base-path-by-hand"&gt;Hard way, setting base path by hand &lt;a class="anchor-link" href="#hard-way-setting-base-path-by-hand"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to keep browser history implementation, you&amp;#x27;ll need to change few things.
First, we need to update our routes to include full absolute path to the subfolder.&lt;/p&gt;
&lt;h3 id="using-react-routers-basename"&gt;Using React Router&amp;#x27;s &lt;code&gt;basename&lt;/code&gt; &lt;a class="anchor-link" href="#using-react-routers-basename"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As Davis Cabral pointed out in the comments, instead of manually adding &lt;code&gt;publicPath&lt;/code&gt;
to all routes, it can be achieved by using React Router&amp;#x27;s &lt;a href="https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/BrowserRouter.md#basename-string"&gt;basename&lt;/a&gt; prop.&lt;/p&gt;
&lt;pre class="language-js"&gt;&lt;code class="language-js code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword module"&gt;import&lt;/span&gt; &lt;span class="token imports"&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;BrowserRouter&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Route&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;react-router-dom&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Then in render&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;BrowserRouter&lt;/span&gt; basename&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;/path/to/subfolder/&amp;#x27;&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Route&lt;/span&gt; path&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;/&amp;#x27;&lt;/span&gt; component&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;Home&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt; exact &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Route&lt;/span&gt; path&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;/about&amp;#x27;&lt;/span&gt; component&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token maybe-class-name"&gt;About&lt;/span&gt; &lt;span class="token punctuation"&gt;}&lt;/span&gt; exact &lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token punctuation"&gt;{&lt;/span&gt;&lt;span class="token comment"&gt;/*...*/&lt;/span&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token operator"&gt;/&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;BrowserRouter&lt;/span&gt;&lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="doing-it-by-the-hand"&gt;Doing it by the hand &lt;a class="anchor-link" href="#doing-it-by-the-hand"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I define my routes something like this:&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; publicPath &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;/path/to/subfolder/&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;export&lt;/span&gt; &lt;span class="token keyword"&gt;const&lt;/span&gt; routeCodes &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;HOME&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; publicPath&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;SEARCH&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token template-string"&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; publicPath &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;search&lt;/span&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token constant"&gt;ABOUT&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token template-string"&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; publicPath &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;about&lt;/span&gt;&lt;span class="token template-punctuation string"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Then you can use them like this&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// &amp;lt;Route exact path={ routeCodes.ABOUT } component={ About } /&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="setting-up-htaccess-file"&gt;Setting up &lt;code&gt;.htaccess&lt;/code&gt; file &lt;a class="anchor-link" href="#setting-up-htaccess-file"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once uplodaded to the server any route (but root &lt;code&gt;/&lt;/code&gt;) will return 404 error.
For example, if you try to open &lt;code&gt;http://yourserver.com/path/to/subfolder/about&lt;/code&gt;,
server will look for file (or folder) named &lt;code&gt;about&lt;/code&gt; in the app subfolder.
As it doesn&amp;#x27;t exist, it will fail with 404.&lt;/p&gt;
&lt;p&gt;You&amp;#x27;ll need to add a simple &lt;code&gt;.htaccess&lt;/code&gt; file,
in order to tell the server to fallback to our &lt;code&gt;index.html&lt;/code&gt; file.
This is the same configuration we would use if the application was on the server root,
just with a different absolute path to our index file.&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;RewriteEngine On
&lt;/span&gt;&lt;span class="code-line"&gt;RewriteCond %&lt;span class="token punctuation"&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class="token punctuation"&gt;}&lt;/span&gt;%&lt;span class="token punctuation"&gt;{&lt;/span&gt;REQUEST_URI&lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token parameter variable"&gt;-f&lt;/span&gt; &lt;span class="token punctuation"&gt;[&lt;/span&gt;OR&lt;span class="token punctuation"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;RewriteCond %&lt;span class="token punctuation"&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class="token punctuation"&gt;}&lt;/span&gt;%&lt;span class="token punctuation"&gt;{&lt;/span&gt;REQUEST_URI&lt;span class="token punctuation"&gt;}&lt;/span&gt; &lt;span class="token parameter variable"&gt;-d&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;RewriteRule ^ - &lt;span class="token punctuation"&gt;[&lt;/span&gt;L&lt;span class="token punctuation"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# Fallback all other routes to index.html&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;RewriteRule ^ /path/to/subfolder/index.html &lt;span class="token punctuation"&gt;[&lt;/span&gt;L&lt;span class="token punctuation"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now our example routes will look like this&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://yourserver.com/path/to/subfolder/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://yourserver.com/path/to/subfolder/about&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://yourserver.com/path/to/subfolder/search&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="notice-about-webpacks-output---publicpath-configuration"&gt;Notice about webpack&amp;#x27;s &lt;code&gt;output -&amp;gt; publicPath&lt;/code&gt; configuration &lt;a class="anchor-link" href="#notice-about-webpacks-output---publicpath-configuration"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you are using &lt;code&gt;publicPath&lt;/code&gt; in webpack&amp;#x27;s &lt;code&gt;output&lt;/code&gt; object,
make sure you either remove it or update to match your server build path.
Removing it  is easier, as it will create relative links,
which should work with your new configuration.&lt;/p&gt;
&lt;pre class="language-tsx"&gt;&lt;code class="language-tsx code-highlight"&gt;&lt;span class="code-line"&gt;output&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  publicPath&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;/&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token comment"&gt;// Remove, or update it&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  path&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;./build&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  filename&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;app-[hash].js&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token punctuation"&gt;}&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="create-react-app"&gt;Create React App &lt;a class="anchor-link" href="#create-react-app"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A lot of people are using Create React App. To deploy it in subfolder, you can set &lt;code&gt;homepage&lt;/code&gt; in your &lt;code&gt;package.json&lt;/code&gt;, for more details &lt;a href="https://create-react-app.dev/docs/deployment#building-for-relative-paths"&gt;check their documentation&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I&amp;#x27;m also interested if anyone has different/better ideas, cheers!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 18 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-router-subfolder-on-server/</guid></item><item><title>Making dynamic form inputs with React</title><link>https://goshacmd.com/array-form-inputs/</link><author>Gosha Spark</author><pubDate>Wed, 18 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/array-form-inputs/</guid></item><item><title>Updating Jekyll Formats</title><link>https://sal.dev/hack/mediator-jekyll-blog/</link><description>&lt;p&gt;&lt;em&gt;It’s 2017; my site needed to stop looking so 2013.&lt;/em&gt;&lt;/p&gt;

&lt;h1 id="thank-you-andrew"&gt;Thank you, Andrew&lt;/h1&gt;
&lt;p&gt;Three and a half years ago, my buddy who is into design, &lt;a href="https://capshaw.me/"&gt;Andrew&lt;/a&gt;, had a pretty swanky personal website. I thought it looked nice, so with his permission, I forked it, and pretty much took out his content and added my own.&lt;/p&gt;

&lt;p&gt;&lt;img alt="This is what swank looks like." src="/assets/article_images/2017-01-16-mediator-jekyll-blog/old-jekyll-setup-1920.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;At first I was proud of it, and tried to add content to it. I even wrote a post on &lt;a href="/hack/customizing-mac-input-source-icon/"&gt;how to change the keyboard icon&lt;/a&gt; which still gets most of the traffic to this site.&lt;/p&gt;

&lt;p&gt;&lt;img alt="I don't know what sharebutton.to is, but robots like it." src="/assets/article_images/2017-01-16-mediator-jekyll-blog/google-analytics.png" /&gt;&lt;/p&gt;

&lt;p&gt;Eventually, I lost interest and stopped paying attention to the site. Side projects that I had finished or abandoned were still featured front and center. Two and a half years after I graduated, &lt;a href="https://web.archive.org/web/20150525014515/http://saltesta.com/"&gt;it still said I was a Senior in college&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id="enter-mediator"&gt;Enter, Mediator&lt;/h1&gt;
&lt;p&gt;All the cool kids use the publishing platform, Medium, these days, or they were until Medium started getting a bit more flack for &lt;a href="https://www.bloomberg.com/view/articles/2017-01-05/why-medium-failed-to-disrupt-the-media"&gt;laying-off a third of their company&lt;/a&gt;. I don’t know if it’s still cool, but I’m hoping someone will tell me. Regardless, a few of my friends started exporting their work from the site and started looking for a new place to play ball. This made me wonder if it would be feasible to make something that looked as polished (cool) as Medium but hosted easily.&lt;/p&gt;

&lt;p&gt;&lt;img alt="This is what cool looks like." src="/assets/article_images/2017-01-16-mediator-jekyll-blog/medium-screenshot-1920.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I was already using &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; (site building) on &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt; (free hosting if you know how to use &lt;code class="language-plaintext highlighter-rouge"&gt;git&lt;/code&gt;) because that’s what Andrew used; I wanted my site to look more like Medium because that’s the new standard for what looks good; and I wanted to exert minimal effort because I’ve demonstrated to myself that I spend much time on this kind of thing (yet).&lt;/p&gt;

&lt;p&gt;&lt;img alt="It's the top two results!" src="/assets/article_images/2017-01-16-mediator-jekyll-blog/google-search-result.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;The top results were &lt;a href="https://github.com/dirkfabisch/mediator"&gt;Mediator&lt;/a&gt;, and &lt;a href="https://github.com/ageitgey/amplify"&gt;a copy of Mediator&lt;/a&gt; that used &lt;a href="https://www.ampproject.org/"&gt;Google’s fancy new caching thing-a-ma-bob&lt;/a&gt;. I could do almost no work and use the first option, so we had a winner!&lt;/p&gt;

&lt;p&gt;&lt;img alt="This is what winners look like." src="/assets/article_images/2017-01-16-mediator-jekyll-blog/df-screenshot.jpg" /&gt;&lt;/p&gt;

&lt;h1 id="mostly-seamless"&gt;Mostly Seamless&lt;/h1&gt;
&lt;p&gt;For the most part, moving between Jekyll projects went off without a hitch. There were a few minor problems: the URL structure was different and I didn’t want to make links to my site break (if they exist), and images in posts weren’t centered by default. Five minutes of work later, one scare with CNAMES on GitHub pages, and I was all setup.&lt;/p&gt;

&lt;p&gt;My knee-jerk reaction is that this is a pretty good configuration, and I hope it inspires me to write more posts this year.&lt;/p&gt;</description><author>Salvatore's Blog</author><pubDate>Mon, 16 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sal.dev/hack/mediator-jekyll-blog/</guid></item><item><title>Building efficient micro services in Go</title><link>https://www.umarniz.com/building-efficient-micro-services-in-go/</link><description>After dockerizing our existing infrastructure at Sense Health I have been working on building a suite of micro services for the backend. As…</description><author>Umar Nizamani | RSS Feed</author><pubDate>Sun, 15 Jan 2017 17:28:31 GMT</pubDate><guid isPermaLink="true">https://www.umarniz.com/building-efficient-micro-services-in-go/</guid></item><item><title>The more we record the less we understand</title><link>http://negfeedback.blogspot.com/2017/01/the-more-we-record-less-we-understand.html</link><description>Disclaimer: This post is unresearched and contains no links as I'm just working from an idea I had this morning. I'd love to hear if I got something wrong, but I'm going fast to stop myself from getting stuck on this.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
In the beginning was the word&lt;/h2&gt;
Language developed long before we wrote it down. But I think as soon as we started speaking to one another we had the problem that it is possible to say things that are different from the way things actually are. This is unlike in-person pointing and grunting, where we are restricted to the way things are in the world. We can't point at an object that doesn't exist, but we can speak of it.&lt;br /&gt;
&lt;br /&gt;
This is a wonderful advancement because it allows use to communicate things like plans for the future or relate stories about events which happened in the past. It's also the entry point to abstract thought and math. On the downside it allows for a whole set of possibilities in subterfuge. It allows us to promise things we have no intention of doing. It allows us to lie.&lt;br /&gt;
&lt;br /&gt;
I think to balance this in a positive direction, we have developed great social pressure not to be caught in a lie. But when all communication is oral, there is an out - you can deny what you said. It is understood that we have imperfect recall, and therefore a defence like "that's not what I said" is somewhat defensible.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Then we started writing things down&lt;/h2&gt;
&lt;div&gt;
As soon as we developed writing, the recall component of deniability was weakened. It's harder to argue that the writing was altered than to argue that someone is remembering wrong. But I think that social interaction &lt;i&gt;requires&lt;/i&gt;&amp;nbsp;a certain amount of wiggle room, so we started to focus on the nuance of context to retain deniability. When confronted with a written record of what we said, we can claim that it was quoted out of context, that something said before or after was left out, which changes the meaning. Or we can say that the written word doesn't capture the nuance of inflection and claim that we were using an ironic tone of voice.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Of course, it is also possible to write words which weren't ever spoken. In this case, we can claim that the reader lacks crucial information which changes the way the words should be interpreted. "Yes, I wrote that, but you misunderstand what I meant".&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;
Now we record everything&lt;/h2&gt;
&lt;div&gt;
The recent elections in America have shown that even our current recording technology, where we record the voice and the image of the person speaking, doesn't make things any more solid. It appears now that language itself is being called upon to allow the differences of interpretation which used to be restricted to arguments about what was said behind closed doors. Trump can say clearly and repeatedly in front of a camera that he intends to build a wall between America and Mexico, and people can interpret this as some kind of metaphor rather than a statement of intent.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I predict that the more exact and expansive we become in recording what people say, the less we will be able to point at those recordings themselves to understand the meaning, because the language will be called upon to allow for different interpretations. Perhaps a certain amount of wiggle room is a fact of communication, and we will find a way to introduce it.&lt;/div&gt;</description><author>Negative Feedback</author><pubDate>Sat, 14 Jan 2017 10:38:02 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2017/01/the-more-we-record-less-we-understand.html</guid></item><item><title>You don't need a tutorial for every-freaking-thing</title><link>https://goshacmd.com/no-tutorial-for-everything/</link><author>Gosha Spark</author><pubDate>Sat, 14 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/no-tutorial-for-everything/</guid></item><item><title>Don't quit that programming career yet because of AI</title><link>https://da-data.blogspot.com/2016/05/dont-quit-that-programming-career-yet.html</link><description>A recent Wired article breathlessly predicted&amp;nbsp;&lt;a href="http://www.wired.com/2016/05/the-end-of-code/"&gt;the end of code:&lt;/a&gt;&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
Soon We Won’t Program Computers.&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
We’ll Train Them Like Dogs&lt;/blockquote&gt;
Of course, this is the same magazine that declared in 2010 that &lt;a href="http://www.wired.com/2010/08/ff_webrip/"&gt;The Web is Dead&lt;/a&gt;. &amp;nbsp;So perhaps we should step back and think before throwing in the towel. &amp;nbsp;Have you &lt;i&gt;looked&lt;/i&gt;&amp;nbsp;at a self-driving car recently?&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp9BBaYl6LTRk97L7VfSi3HhDlDIFMDDkozX-4I668T0LCqFXGedIADhbbzDTRRd7sngrDVTp_fbsQZPT6fGMAj_e1-uy78qjh1xGuV_uaD7rgL_8J-gqnIW6lmGYQ8rvp-oaPwVZxDuM/s1600/Screenshot+2016-05-19+22.47.57.png" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp9BBaYl6LTRk97L7VfSi3HhDlDIFMDDkozX-4I668T0LCqFXGedIADhbbzDTRRd7sngrDVTp_fbsQZPT6fGMAj_e1-uy78qjh1xGuV_uaD7rgL_8J-gqnIW6lmGYQ8rvp-oaPwVZxDuM/s320/Screenshot+2016-05-19+22.47.57.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Self-driving car (image &lt;a href="https://www.google.com/selfdrivingcar/how/"&gt;from Google&lt;/a&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
In this simplified diagram blatantly stolen from Google, there's a laser scanner, a radar, a compass, speed sensors - missing are the cameras, the engine computer, the onboard computers, the cellular uplinks, the data recorders, the &lt;br /&gt;
onboard entertainment system (which will hopefully get even more use when the driver gets to play also). &amp;nbsp;And the backup systems, which are often redundantly engineered and even separately programmed to avoid coordinated failure. &amp;nbsp;Each of these devices has substantial embedded firmware controlling them, and per-device processing in order to control them and make sense of the data they generate.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="https://what-if.xkcd.com/imgs/a/63/google_punchcard.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="97" src="https://what-if.xkcd.com/imgs/a/63/google_punchcard.png" width="200" /&gt;&lt;/a&gt;Oh, and that car depends on Google's map infrastructure, which draws data from satellites, airplanes, streetview cars (and sometimes &lt;a href="https://googleblog.blogspot.com/2009/10/street-view-we-can-trike-wherever-you.html"&gt;tricycles&lt;/a&gt;), and huge databases. &amp;nbsp;The ability to train those machine learning models depends on an absolutely massive compute infrastructure with enough storage to &lt;a href="https://what-if.xkcd.com/63/"&gt;cover New England 4.5km deep in punch cards&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Advanced machine learning drastically increases the need for heavy-duty compute infrastructure and data management.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
If you want to get geeky about it, assume that a self-driving car has something like 4 HD camera-quality sensors attached to it. &amp;nbsp;I'm sure that's not accurate, but it's a conservative guess, if &lt;a href="http://abcnews.go.com/Technology/uber-takes-driving-car-spin-pittsburgh/story?id=39253886"&gt;the massive sensor array on top of Uber's new prototype&lt;/a&gt; is any indication. If it drives two hours per day (only two? &amp;nbsp;what a waste!), it's creating about 420GB of compressed h.264 60fps data per day. &amp;nbsp;8 hours, it's filling a hard drive every day. &amp;nbsp; YouTube currently is the most likely contender for most video uploaded (about 300 hours per minute). &amp;nbsp;Put a million self-driving cars on the road full time and you've got it beat by a factor of seventy. &amp;nbsp;If a million sounds like a lot, remember that it's a very small fraction of the &lt;a href="http://www.latimes.com/business/autos/la-fi-hy-ihs-automotive-average-age-car-20140609-story.html"&gt;253 million cars on the road today in the US.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Advanced machine learning techniques don't reduce the need for programming. &amp;nbsp;They make it possible to program systems that were formerly beyond the reach of automation.&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;


&lt;br /&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;There's a &lt;a href="https://www.youtube.com/watch?v=Rnm83GqgqPE"&gt;fun talk at Google I/O 2016 about machine learning&lt;/a&gt;, in which &lt;a href="http://twitter.com/aparnacd"&gt;Aparna Chennapragada&lt;/a&gt; notes:&lt;/span&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span class="s1"&gt;There are two ways in which machine learning changes the game.&amp;nbsp; One is that it can turbo-charge existing use cases [such as] speech recognition.&amp;nbsp; ... If the word error rate drops, we actually saw the usage go up. [...] The same thing with translation.&amp;nbsp; As translation gets better, Google Translate scales to 100+ languages.&amp;nbsp; [...] The second way, which is a lot more exciting to see, is where it can unlock new product use cases.&lt;/span&gt;&lt;/blockquote&gt;
When ML makes it possible to have high-quality translation in 100 languages, suddenly someone needs to build all the infrastructure to support them, from collecting and managing the training data, through disseminating the models to the billion+ users who're now able to take advantage of them.&amp;nbsp; When it unlocks new use cases, suddenly someone needs to write the code that adapts that use case to the ML that can solve it. &amp;nbsp;There's data to be stored, UIs to be designed, experimented with, and implemented.&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
Machine learning has been advancing at a tremendous rate, it's true. &amp;nbsp;I hope it keeps up. &amp;nbsp;But anyone who's dealt with ML in the real world &lt;a href="https://www.quora.com/Is-it-true-that-manipulating-data-with-SQL-and-NoSQL-is-90-of-data-scientist-job"&gt;can tell you that you're likely&lt;/a&gt; to spend more time cleaning and dealing with the data than the learning itself. &amp;nbsp;One Google paper termed Machine Learning "&lt;a href="http://research.google.com/pubs/pub43146.html"&gt;The High Interest Credit Card of Technical Debt&lt;/a&gt;", noting that:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
Machine learning packages have all the basic code
complexity issues as normal code, but also have a larger system-level complexity that can create
hidden debt.&lt;/blockquote&gt;
and&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
As a special case of glue code, pipeline jungles often appear in data preparation. These can evolve
organically, as new signals are identified and new information sources added. Without care, the
resulting system for preparing data in an ML-friendly format may become a jungle of scrapes, joins,
and sampling steps, often with intermediate files output.&lt;/blockquote&gt;
The view that you "just point" a machine learning algorithm at a pile of raw data ignores the very real system engineering challenges that arise any time you start hooking data sources together or using software to control things.&lt;br /&gt;
&lt;br /&gt;
By giving us tools to learn and control things formerly impossible, modern AI techniques are opening the way to applying computation even more pervasively, and in more sophisticated ways. &amp;nbsp;But the more we can use our computers to do, the more we spend our time programming the mechanisms to hook them up to data, to the real world, and to users, not less.&lt;br /&gt;
&lt;br /&gt;
Don't give up on that CS degree just yet. &amp;nbsp;&lt;a href="http://amzn.to/2jBI6Sv"&gt;Hit the books and learn about deep learning&lt;/a&gt;&amp;nbsp;instead!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;(As is hopefully obvious, while I'm using Google as an example a lot here, and they're paying my salary while I'm on sabbatical this year, the views in my blog are strictly my own.)&lt;/span&gt;</description><author>Dave's Data</author><pubDate>Fri, 13 Jan 2017 02:14:22 GMT</pubDate><guid isPermaLink="true">https://da-data.blogspot.com/2016/05/dont-quit-that-programming-career-yet.html</guid></item><item><title>Essential Tips for WordPress Admins and Editors</title><link>https://nitinnain.com/tips-for-wordpress-admins-and-editors/</link><description>(This post supposes that you have a working WordPress site already and now want to improve the content and design for the site.) You&amp;#8217;ll first need a login for your WordPress site. The login is most probably at example.com/wp-login. Most articles on &amp;#8220;Getting started with WordPress&amp;#8221; begin with setting up WordPress on a server, or [&amp;#8230;]</description><author>Nitin Nain</author><pubDate>Thu, 12 Jan 2017 20:49:00 GMT</pubDate><guid isPermaLink="true">https://nitinnain.com/tips-for-wordpress-admins-and-editors/</guid></item><item><title>The land after time</title><link>https://zrkrlc.com/notes/the-land-after-time/1484236680/</link><description>Note: I'm currently publishing pieces from my vault. This was supposed to be published on 2017 January 13.I had an enlightening talk once with The Giving Tree1 about his plan to start a VR-focused organisation in University X-1. In X-1, you have to do a couple of things before you can start your own club:</description><author>Junk Heap Homotopy</author><pubDate>Thu, 12 Jan 2017 17:58:00 GMT</pubDate><guid isPermaLink="true">https://zrkrlc.com/notes/the-land-after-time/1484236680/</guid></item><item><title>Diversity and unity</title><link>http://negfeedback.blogspot.com/2017/01/diversity-and-unity.html</link><description>I recently posted this tweet:&lt;br /&gt;
&lt;blockquote class="twitter-tweet"&gt;
&lt;div dir="ltr" lang="en"&gt;
The world would be better if we had one language in common, drove on the same side of the road and used the same units. &lt;a href="https://twitter.com/hashtag/standards?src=hash"&gt;#standards&lt;/a&gt;&lt;/div&gt;
— Carl Sandrock (@chthonicdaemon) &lt;a href="https://twitter.com/chthonicdaemon/status/818352319461003264"&gt;January 9, 2017&lt;/a&gt;&lt;/blockquote&gt;


&lt;br /&gt;
I was surprised by the number of people who protested on Facebook. Most of the problems were with the language rather than the other elements I mentioned. There were a couple of different arguments raised:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;People are attached to their language and wouldn't agree to stop talking their language.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Things would be boring if they were the same everywhere&lt;/li&gt;
&lt;li&gt;Less diversity means less creativity&lt;/li&gt;
&lt;li&gt;It is impossible to decouple language, culture and identity and people don't want to change them&lt;/li&gt;
&lt;/ol&gt;
Let me first say that when I was writing the original tweet I was careful to word it as "we had one language in common" rather than "everyone spoke the same language". The sense I was attempting to convey is not that I would like for everyone to give up their current language to speak only one language but that I would be happy if everyone spoke one common language (perhaps in addition to other languages). What is important to me is mutual intelligibility. In other words, I would like to be able to understand what another person is trying to tell me regardless of where in the world that person comes from. I realise that many people strongly identify with their language and see language as an integral part of their culture and identity. When I was thinking about the concerns raised by people I was thinking about differences which would be equivalent to me in terms of universal intelligibility but which would involve different sacrifices or advances in technology to implement.&lt;br /&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Everyone speaks only one language, the same all over the world.&lt;/li&gt;
&lt;li&gt;Everyone speaks one universal language, but many people speak multiple languages.&lt;/li&gt;
&lt;li&gt;Everyone speaks enough languages that the chance of meeting someone you don't understand is low.&lt;/li&gt;
&lt;li&gt;The same distribution of languages as there are now, but &lt;a href="https://en.wikipedia.org/wiki/Universal_translator"&gt;universal translator&lt;/a&gt; technology exists.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
It appears as though most of the objectors were picturing the first option. This option is probably impractical to implement completely as people would have to be forced to stop speaking the language they speak now if it differs from the universal language. I agree that this would be hard to do politically, but I am not convinced that we would be worse off if there were only one language. More on that later.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
What about the second option? I see two ways in which this could play out. On one hand, one existing natural language takes over. This actually appears to be happening slowly with English. There would be political resistance to this, partly based on the asymetric effort of some people having to learn a second language while some people by only an accident of birth already knowing the universal language. English is also quite &lt;a href="https://www.oxford-royale.co.uk/articles/learning-english-hard.html"&gt;hard to learn&lt;/a&gt;. These are the problems which &lt;a href="https://en.wikipedia.org/wiki/Esperanto"&gt;Esperanto&lt;/a&gt; was developed to solve. It is not the native language of any country and it is specifically easy to learn. The only problem is that few people are motivated enough to learn a made-up language just for this ideal of being able to talk to other idealists. The geek part of me wishes we could get some momentum behind &lt;a href="https://en.wikipedia.org/wiki/Lojban"&gt;Lojban&lt;/a&gt;, but I realise that is totally unrealistic. You can pick up the thread of the argument startin from the &lt;span id="goog_132388704"&gt;&lt;/span&gt;&lt;span id="goog_132388705"&gt;&lt;/span&gt;&lt;a href="https://en.wikipedia.org/wiki/Universal_language"&gt;Universal Language&lt;/a&gt; Wikipedia page&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
I think the third option is the least likely, but I have it in there to show that there is a logical "out" to the problem of cultural homogeneity, even if culture and language is tied. This option doesn't have everyone speaking the same language, but if there are a couple of languages in the mix, you have low odds of meeting someone who doesn't speak one language you understand. If you speak the top 5 languages in &lt;a href="https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers"&gt;this list&lt;/a&gt;&amp;nbsp;(Mandarin Chinese, English, Spanish, Arabic and Hindi) you can be understood by about half of the people on Earth.&lt;br /&gt;
&lt;br /&gt;
The most interesting option here from a cultural point of view is the universal translator. I can attest to the fact that learning extra languages is hard. I've been trying to teach myself French for many years and have had only very limited success. A universal translator promises to remove language barriers with no effort from the user. One of the protestors on Facebook found even this problematic in that they said mutual unintelligibility was important for creativity.&lt;br /&gt;
&lt;br /&gt;
I can understand this idea, but let's think about how we ended up speaking different languages in the first place. I think that groups of humans which don't interact will eventually diverge in the ways which are not very functional. In other words, since there is no strong force requiring the mapping of one sound to an object above another, you would expect different sounds to correspond to the same object in different geographical regions just because of chance. I think the same forces go for things like the way people wear their hair or clothing styles and so on. All these things could easily be different but are unlikely to be the same without some concerted coordination. So it seems to me that these isolated groups would develop different languages at the same time as they were developing different cultures. However, I can easily see how groups with a language in common could remain mutually intelligible while developing divergent culture.&lt;br /&gt;
&lt;br /&gt;
So culture can change even when language stays the same and probably, but much less likely, language can change while culture stays the same. I'm saying we observe that different cultures have different languages not because they are coupled but because they only change when the same kind of isolation is in place.&lt;br /&gt;
&lt;br /&gt;
One very interesting argument about the application of language is known as the &lt;a href="https://en.wikipedia.org/wiki/Linguistic_relativity"&gt;Sapir-Whorf hypothesis&lt;/a&gt;, which loosely states that language forms the way you think. I've seen this used often as an argument against using indiginous African languages for scientific teaching because these languages don't have the ability to express the required concepts. What I've read on this topic appears to show that this is a flawed idea. I'm not convinced that any popular human language is inherently less suited for particular kinds of thought that humans have. I would however not be completely surprised as I subscribe to something similar for programming languages (see &lt;a href="https://en.wikipedia.org/wiki/Paul_Graham_(computer_programmer)#The_Blub_paradox"&gt;the blub paradox&lt;/a&gt; for more information). It seems that a universal language would not be bad whether linguistic relativity is true or false, as long as we choose a "good" universal language.&lt;br /&gt;
&lt;br /&gt;
Now, I count a language to be substantially similar if it is mutually intelligible. I could sense some pushback which implied that something like American English and South African English are different languages from British English due to their different idioms and/or pronunciation. I'm not sure what the linguistic view is, but I'm pragmatic and I draw the line at intelligibility (perhaps in written form, to reduce the effect of accent).&lt;br /&gt;
&lt;br /&gt;
An interesting question to those who feel that unintelligibility is useful in driving creativity is what the "best" number of mutually unintelligible languages would be. This question follows from the idea that if one language is bad, and one could assume it would be bad if everyone spoke their own personal language which was not understood by anyone else, there would appear to be an optimum number. My personal feeling is that the optimum number is one, but I'm hoping for someone to show me a different point of view.&lt;br /&gt;
&lt;br /&gt;
To address the issue of identity and language: I am not a fan of nationalism. I find it is nice for me to think about national boundaries dissolving and no restriction of movement. This is not based on a deep understanding of socio-political theory, but it is my personal inclination. As such, the idea of people being "loyal" to "their kind" is viscerally repulsive to me. This may be why I have little understanding of people who are proud of their culture. This, in turn, may be why I find arguments based on language and identity hard to follow. We do know that the idea of &lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2775052/"&gt;national character is quite flawed&lt;/a&gt;, and that in-group out-group morality probably violates most people's personal description of their moral principles. So overall, my sense is that this kind of identity does more harm than good. But I will repeat again this is not a strong argument but rather my personal preference.&lt;br /&gt;
&lt;br /&gt;
Lastly, when I mentioned this discussion to a colleague of mine they asked a counter-question: "Would you rather that there be only one computer language"? This is an interesting question because there is a different question about why we have multiple computer languages. The reason is not the same as for human languages, because we didn't see computer languages emerge in non-communicating groups, but rather they were designed with different goals and constraints in place. Given that these constraints remain different, one could imagine different solutions which satisfy the constraints and the goals. I do believe there could easily be less computer languages, but here I agree that the optimal number is probably more than one.&lt;br /&gt;
&lt;br /&gt;
My final view is that I remain attracted to the idea of mutual inteligibility, and that I am still not convinced of the utility of multiple human languages in and of themselves. There's some stuff I want to unpack about the responses here which has to do with the idea of diversity as a virtue, but I think that will have to wait for another post.&lt;/div&gt;</description><author>Negative Feedback</author><pubDate>Thu, 12 Jan 2017 09:54:36 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2017/01/diversity-and-unity.html</guid></item><item><title>Winter Tech Meetup Vol 5</title><link>https://muffinman.io/blog/winter-tech-meetup-vol-5/</link><description>&lt;article class="article"&gt;&lt;p&gt;We prepared another tech meetup, this time with four presentations.
There will be a break after the second one.
This should be the biggest one so far, with two guest speakers.&lt;/p&gt;
&lt;p&gt;It will happen on February the 4th, at Belgrade Youth Centre.
Hope to see you there!&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Winter Tech Meetup Vol 5" height="2048" src="./poster.jpg" width="1448" /&gt;&lt;/figure&gt;
&lt;p&gt;Visit &lt;a href="https://www.facebook.com/events/171047483377472/"&gt;Facebook event&lt;/a&gt;
or &lt;a href="https://www.meetup.com/Tech-Meetup-Vol-5/"&gt;meetup.com page&lt;/a&gt;.
And apply
&lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSc_HFx5M6rhQYqmXkV5V1dPhkw0-M8L4R-1L7LoN6p2zgfnOA/viewform"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks to everyone who participated!&lt;/p&gt;
&lt;h3 id="slides"&gt;Slides &lt;a class="anchor-link" href="#slides"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/pdf/Nikola Pantovic - Pet cula u poslovnom nastupu.pdf"&gt;Five senses in a business performance&lt;/a&gt; - Nikola Pantović&lt;/li&gt;
&lt;li&gt;&lt;a href="/pdf/Ivan Nikitovic - Go fast with web workers.pdf"&gt;Go fast with Web Workers&lt;/a&gt; - Ivan Nikitović&lt;/li&gt;
&lt;li&gt;&lt;a href="/pdf/Sasa Ranisavljevic - How to become more professional developer.pdf"&gt;Become more professional developer&lt;/a&gt; - Saša Ranisavljević&lt;/li&gt;
&lt;li&gt;&lt;a href="/pdf/Stanko Tadic - State of modern JS development.pdf"&gt;State of a modern JavaScript development&lt;/a&gt; - Stanko Tadić (myself)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="photos"&gt;Photos &lt;a class="anchor-link" href="#photos"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="grid wide"&gt;&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="Nikola Pantović" height="800" src="./1.jpg" width="1200" /&gt;&lt;/figure&gt;&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="Tech meetup audience" height="800" src="./2.jpg" width="1200" /&gt;&lt;/figure&gt;&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="Stanko Tadić talking about JavaScript" height="800" src="./3.jpg" width="1200" /&gt;&lt;/figure&gt;&lt;figure class="image__figure wide image__figure--wide"&gt;&lt;img alt="Saša Ranisavljević" height="800" src="./4.jpg" width="1200" /&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Thu, 12 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/winter-tech-meetup-vol-5/</guid></item><item><title>Avoiding false cause</title><link>https://sebinsua.com/avoiding-false-cause</link><description>&lt;p&gt;Tech teams often cargo-cult the practices and patterns that are established earlier on by their creators.&lt;/p&gt;
&lt;p&gt;This can lead to useless boilerplate proliferating and sometimes to the creators eventually deciding that they have no choice but to disavow their earlier approaches.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Many don’t realize I wrote all that stuff when React was relatively new and people shared what they learned, not instilled ‘rules’.”&lt;/p&gt;
&lt;p&gt;— Dan Abramov, &lt;a href="https://twitter.com/dan_abramov/status/802571906385932288"&gt;November 2016&lt;/a&gt; (deleted)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Dogma is bad but noticing things is hard&lt;/h3&gt;
&lt;p&gt;Dogma is bad because it leads to poorly-fit solutions.&lt;/p&gt;
&lt;p&gt;However, in the absence of dogma, a greater problem can reveal itself: &lt;em&gt;it’s hard to correctly notice the causes of problems&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Dogma might not be the right solution, but it does serve a purpose. Without frameworks to act as guard rails, patterns and best-practices are needed to help less experienced engineers find their feet and avoid wasting time.&lt;/p&gt;
&lt;h3&gt;Problem solving&lt;/h3&gt;
&lt;p&gt;The central instruments of problem-solving are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Carefully &lt;em&gt;noticing&lt;/em&gt; things.&lt;/li&gt;
&lt;li&gt;Correctly &lt;em&gt;establishing&lt;/em&gt; cause-and-effect.&lt;/li&gt;
&lt;li&gt;Effectively &lt;em&gt;implementing&lt;/em&gt; solutions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As engineers we often focus our energy on the final item, however here we will concentrate on ‘noticing things’ and avoiding &lt;a href="https://en.wikipedia.org/wiki/Questionable_cause"&gt;false causes&lt;/a&gt; and the bad solutions that arise from these and which result in wasted developer productivity.&lt;/p&gt;
&lt;p&gt;In writing this essay my hope to to inform those that create libraries or tools on how to best increase accessibility for both beginners and experts and to provide a high-level framework for thinking about some of the problems that we encounter.&lt;/p&gt;
&lt;h2&gt;Noticing things&lt;/h2&gt;
&lt;p&gt;Over the last few years, I’ve spent quite a bit of time as a consultant technical lead, often advising teams made up of very junior software engineers. This has given me a lot of exposure to the problems that they face.&lt;/p&gt;
&lt;p&gt;Some of the problems that I noticed are already in the process of being fixed (e.g. complex build processes should no longer be the default as better tools attempt to provide good default choices), however I also encountered a number of problems that surprised me. This lead me to believe that (1) there are still many ways in which we are too permissive even as we reject past dogma, and (2) there are useful patterns and heuristics that are either unwritten or overlooked.&lt;/p&gt;
&lt;p&gt;Here are some of the issues I encountered:&lt;/p&gt;
&lt;h3&gt;Mismanagement of salience&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;salience&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ˈseɪlɪəns/
&lt;em&gt;noun&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;noun: &lt;strong&gt;salience&lt;/strong&gt;; noun: &lt;strong&gt;saliency&lt;/strong&gt;; plural noun: &lt;strong&gt;saliencies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;the quality of being particularly noticeable or important; prominence.&lt;/p&gt;
&lt;p&gt;“the political salience of religion has a considerable impact”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Great developer experience (DX) is largely about control over salience. Software and its outputs should be understood by all engineers that contribute to them.&lt;/p&gt;
&lt;p&gt;Here are a few examples of how problems of saliency can occur:&lt;/p&gt;
&lt;h4&gt;Silent failures or overly noisy output&lt;/h4&gt;
&lt;p&gt;&lt;u&gt;Silence&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;I once worked on a codebase which was very heavily tooled, and on which one of the more junior engineers often complained about having difficulties getting his code to work. From time to time I would come over to provide direction and help them to fix logical issues, often relying on my ability to quickly understand what was being coded rather than reaching for any particular debugging technique. Since this generally helped, I incorrectly assumed that their complaint was due to the occasional mistakes I spotted within their code.&lt;/p&gt;
&lt;p&gt;A few weeks later, I made a linting error in my own code, started the app and got a white screen of death. I checked the Developer Console and to my surprise saw a &lt;code&gt;404 Not Found&lt;/code&gt; error against the HTTP request for JavaScript.&lt;/p&gt;
&lt;p&gt;It turned out that the build process had been misconfigured and it would exit without outputting code if it found any linting error. To make matters worse it emitted no errors when it did this. Failure was silent.&lt;/p&gt;
&lt;p&gt;This behaviour primarily affected junior engineers on the team, since many senior engineers program within the linters rules by default and hence rarely see its errors. Ironically, a process that had originally been setup to help engineers write consistent code was hindering their understanding by making their logic fail for irrelevant reasons. And, since those that wrote the build process were less exposed to linting errors the problem was effectively invisible to them.&lt;/p&gt;
&lt;p&gt;This class of problem is likely more common than you’d expect. Build processes are quite often cobbled together at the start of projects by lead/senior engineers, who often hit different edge-cases than beginners.&lt;/p&gt;
&lt;p&gt;Lessons learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A build process should have invariants for its expected outputs and should error loudly when it fails any of these.&lt;/li&gt;
&lt;li&gt;Junior engineers are important customers of build processes and developer tools. They are more reliant on these tools and therefore we should seek their feedback and centre it creating or combining these tools.&lt;/li&gt;
&lt;li&gt;It’s a good idea to use an off-the-shelf build process and to avoid hacking together a new one for every project you create.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;u&gt;Noise&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;On the other end of the spectrum is the &lt;a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons"&gt;Tragedy of the Commons&lt;/a&gt; that occurs when combining lots of disparate tools into a single process.&lt;/p&gt;
&lt;p&gt;A popular software principle is the &lt;a href="https://en.wikipedia.org/wiki/Unix_philosophy"&gt;Unix Philosophy&lt;/a&gt;’s &lt;a href="http://www.linfo.org/rule_of_silence.html"&gt;Rule of Silence&lt;/a&gt;. This states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Developers should design programs so that they do not print unnecessary output. This rule aims to allow other programs and developers to pick out the information they need from a program’s output without having to parse verbosity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Often individual tools will follow this principle, or at least provide options to help reduce the default verbosity (e.g. &lt;code&gt;npm run -s&lt;/code&gt;). However, as engineers begin to combine them the total output will tend to become noisy and difficult to parse, reducing its usability.&lt;/p&gt;
&lt;h4&gt;Defactoring to understand code and hence leaving a larger surface area for errors&lt;/h4&gt;
&lt;p&gt;Beginners tend to understand and debug problems through tinkering and excavation instead of through contextual readings of the code or situation.&lt;/p&gt;
&lt;p&gt;This will sometimes lead them to &lt;a href="http://raganwald.com/2013/10/08/defactoring.html"&gt;defactor&lt;/a&gt; logic towards units of meaning that are easier for them to granularly understand and observe. This can lead to a loss of salience for more experienced engineers that have learnt to work at a higher-level of abstraction due to its greater expressivity, and reduced surface area for errors.&lt;/p&gt;
&lt;p&gt;Unless we retreat back up the ladder of abstraction after gaining understanding this can aggravate future problems.&lt;/p&gt;
&lt;h4&gt;Unamenabilility to laddering&lt;/h4&gt;
&lt;p&gt;&lt;u&gt;A preference for trees or forests&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;A suspicion I have is that in order to gain understanding and debug problems different engineers require different things to be salient. Senior engineers might prefer for the overall approach and context to be expressive and concise so that it can be checked against their &lt;a href="https://en.wikipedia.org/wiki/Indexicality"&gt;previous experiences&lt;/a&gt;, while junior engineers might need the individual details of the problem to be most salient so they can build understanding from scratch.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Laddering&lt;/u&gt;&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;I believe that the deepest understandings will come from a new form of &amp;quot;reading&amp;quot; which is actively moving up and down such a ladder. 4/&lt;/p&gt;&amp;mdash; Bret Victor (@worrydream) &lt;a href="https://twitter.com/worrydream/status/812369681075965952?ref_src=twsrc%5Etfw"&gt;December 23, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;Maybe a useful way of looking at the developer experience of a codebase is to try to judge it by the quality of the abstraction ladder that has been embedded within it? How easy is it for engineers with differing preferences towards granularities of abstraction to move up-and-down this ladder? Can they do so non-destructively?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Abstraction Ladder" src="http://i.imgur.com/tRf29Nx.gif" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Language in Thought and Action” by S.I. Hayakawa&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I have recently seen valuable work being done &lt;a href="http://elm-lang.org/blog/compilers-as-assistants"&gt;improving error messages&lt;/a&gt; by expressing them as a granular detail (including a diff of expected to actual) alongside context and beginner hints. This is analogous to Bret Victor’s tweet on stories and stats:&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Stories &amp;amp; stats are two extremes, both myopic: one too specific, one too general. Neither can represent the truth of a complex situation. 2/&lt;/p&gt;&amp;mdash; Bret Victor (@worrydream) &lt;a href="https://twitter.com/worrydream/status/812369540386459648?ref_src=twsrc%5Etfw"&gt;December 23, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;h3&gt;Deep-nesting and nullability&lt;/h3&gt;
&lt;p&gt;When programming in JavaScript, it’s not unusual to run into errors like &lt;code&gt;TypeError: props.service.manufacturingService is undefined&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In general, in the absence of &lt;a href="https://en.wikipedia.org/wiki/Type_system#Static_type_checking"&gt;static typing&lt;/a&gt; deeply-nested object properties signal that some code is likely to be fragile.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre class="shiki shiki-themes vitesse-dark vitesse-dark" tabindex="0"&gt;&lt;code class="language-javascript"&gt;&lt;span class="line"&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; React&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; '&lt;/span&gt;&lt;span&gt;react&lt;/span&gt;&lt;span&gt;'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; roleNames&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    CHAIRMAN&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; '&lt;/span&gt;&lt;span&gt;Chairman&lt;/span&gt;&lt;span&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    CEO&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; '&lt;/span&gt;&lt;span&gt;Chief Executive Officer&lt;/span&gt;&lt;span&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    MD&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; '&lt;/span&gt;&lt;span&gt;Managing Director&lt;/span&gt;&lt;span&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; SomeComponentDeepWithinHierarchy&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        &amp;#x3c;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;service-box&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            &amp;#x3c;&lt;/span&gt;&lt;span&gt;h2&lt;/span&gt;&lt;span&gt;&gt;{&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}&amp;#x3c;&lt;/span&gt;&lt;span&gt;h2&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            &amp;#x3c;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;service-box__info&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                &amp;#x3c;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&gt;{&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;}&amp;#x3c;/&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                {&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;manufacturingService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;factories&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                    ?&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                        &amp;#x3c;&lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                            &amp;#x3c;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;Primary Factory: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;manufacturingService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;factories&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}&amp;#x3c;/&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                            &amp;#x3c;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;Owner Role: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;roleNames&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;manufacturingService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;factories&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;owners&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;roleType&lt;/span&gt;&lt;span&gt;]}&amp;#x3c;/&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                        &amp;#x3c;/&lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                    :&lt;/span&gt;&lt;span&gt; ''&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            &amp;#x3c;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        &amp;#x3c;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The logic shown above has many opportunities to throw &lt;code&gt;TypeError&lt;/code&gt;s:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;props.service&lt;/code&gt; could be null.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;props.service.manufacturingService&lt;/code&gt; could be null.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;props.service.manufacturingService.factories[0]&lt;/code&gt; could be null or empty.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;props.service.manufacturingService.factories[0].owners[0]&lt;/code&gt; could be null or empty.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;roleNames&lt;/code&gt; could be missing a key-value mapping for &lt;code&gt;props.service.manufacturingService.factories[0].owners[0].role&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;This won’t even throw an error, but instead will silently evaluate to &lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every time &lt;code&gt;service&lt;/code&gt; is passed down the component hierarchy into a component that will read from it, it endows a stealth requirement to either trust that the data is there or to manually check before each property access.&lt;/p&gt;
&lt;p&gt;Often back-end engineers that work in languages with static typing produce deeply-nested objects like these without thinking twice. And, if the shape of the object hasn’t yet been stabilised on the back-end, uncertainty on the front-end can quickly cause a proliferation of defensive programming throughout the component hierarchy (e.g. if-else checks on &lt;code&gt;props.service &amp;amp;&amp;amp; props.service.manufacturingService &amp;amp;&amp;amp; props.service.manufacturingService.factories.length &amp;amp;&amp;amp; ...&lt;/code&gt;). Over time these checks become FUD that clouds other team member’s understanding of data contracts.&lt;/p&gt;
&lt;p&gt;Engineers with less experience working with JavaScript won’t realise that they have a problem until it’s too late. And, they will sometimes &lt;a href="https://en.wikipedia.org/wiki/Law_of_Demeter"&gt;exasperate the problem&lt;/a&gt; often attempting to resolve the problem while also trying to reduce key strokes: for example, by choosing to pass through kitchen-and-sink objects so function signatures look simpler.&lt;/p&gt;
&lt;p&gt;Of course, there are best practices. For example: objects can be flattened, nullability reduced at the source, defaults can be provided, &lt;a href="https://www.typescriptlang.org"&gt;TypeScript&lt;/a&gt; definitions setup, &lt;a href="https://github.com/yury-dymov/json-api-normalizer"&gt;transforms&lt;/a&gt; moved to the edges, &lt;a href="https://github.com/reduxjs/reselect"&gt;selectors&lt;/a&gt; configured, and finally when there is no other choice careful use of &lt;a href="http://ramdajs.com/docs/#prop"&gt;deep property selector functions&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Too many potential output shapes&lt;/h3&gt;
&lt;p&gt;The best way I can explain this one is to intentionally write bad code:&lt;/p&gt;
&lt;pre class="shiki shiki-themes vitesse-dark vitesse-dark" tabindex="0"&gt;&lt;code class="language-javascript"&gt;&lt;span class="line"&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; initialState&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  priceToggle&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  userConfig&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {},&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; reducer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;state&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; initialState&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; newState&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; cloneDeep&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;state&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  switch&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;SET_CONFIG_DATA&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        userConfig&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;userConfig&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      };&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;FETCH_USER_SUCCESS&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;currentUser&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;FETCH_PRODUCTS_SUCCESS&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;MARK_AS_EDITING_PRODUCT&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt; productIndex&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;editingProductIndex&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; productIndex&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;originalData&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;editing&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;UPDATE_PRODUCT_KEY&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt; productIndex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; propertyName&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; propertyValue&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;propertyName&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; !==&lt;/span&gt;&lt;span&gt; propertyValue&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;changed&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;propertyName&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; propertyValue&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;MARK_AS_NO_LONGER_EDITING_PRODUCT&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt; productIndex&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;originalData&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;CREATE_PRODUCT_SUCCESS&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt; productIndex&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;editing&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      delete&lt;/span&gt;&lt;span&gt; newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;productIndex&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;originalData&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;FETCH_SUPERSTORES_SUCCESS&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;superstores&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;currentSuperstoreId&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;currentSuperstoreId&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;superstores&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;SELECT_SUPERSTORE&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;currentSuperstoreId&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; action&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;payload&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;TOGGLE_PRICE&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;priceToggle&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;newState&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;priceToggle&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; newState&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, various problems arise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Difficulty determining the reducer’s output shape&lt;/strong&gt;: By default it will contain a boolean for &lt;code&gt;priceToggle&lt;/code&gt; and an empty object for &lt;code&gt;userConfig&lt;/code&gt;, but almost every other property might be &lt;code&gt;null&lt;/code&gt;, and in fact &lt;code&gt;products&lt;/code&gt; can have dynamic properties.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Difficulty reading the state mutations within branches&lt;/strong&gt;: It’s also hard to read since step-by-step mutations are applied to &lt;code&gt;newState&lt;/code&gt; in order to generate the correct object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reducer’s output shape is dependent on the order of the actions received&lt;/strong&gt;: Depending on the collection of and order of the actions that are received, the reducer will output a different shaped object. In fact, in this example, if &lt;code&gt;SET_CONFIG_DATA&lt;/code&gt; is called after the other actions it will destroy the state they’d setup.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This problem is considerably worse when a function has over 20 branches or is over 1000 lines long. In one project I consulted on, a decision had been made to store all of the state required for each page in a respective &lt;code&gt;reducer&lt;/code&gt; function, and this combined with a lack of experience handling data made it very difficult to reason when there were bugs. As more features were added to pages, the number of branches increased and the number of possible output shapes increased combinatorially.&lt;/p&gt;
&lt;p&gt;Nowadays I recommend using static typing in your app. But, the underlying theory is to reduce the number of possible shapes that your data can take, as this affords you the ability to reason about your application’s state more easily while also requiring less complication in your logic.&lt;/p&gt;
&lt;h3&gt;Issues with use of mutable global state&lt;/h3&gt;
&lt;p&gt;Within the earlier &lt;code&gt;reducer&lt;/code&gt; code example, there are also a few other issues:&lt;/p&gt;
&lt;h4&gt;Switching into ‘editing’ mode, and then resetting state on cancellation&lt;/h4&gt;
&lt;p&gt;Mutating the data that is currently displayed on the screen, and then resetting it if the edit is cancelled is a bad pattern. It’s preferable to mimic &lt;a href="https://en.wikipedia.org/wiki/Database_transaction"&gt;transactions&lt;/a&gt; by copying the data that is going to be edited into a separate property where it can be mutated, and then only choosing to mutate the original data if the operation is successful. This is better since it is less destructive by default, and side-effects only when it needs to.&lt;/p&gt;
&lt;h4&gt;Making multiple, dynamic key-value changes&lt;/h4&gt;
&lt;p&gt;Functions of the form &lt;code&gt;setProductProperty(propertyName: string, propertyValue: any | undefined)&lt;/code&gt; allow you to write any value into an object. This is problematic since it is so general that it is descriptive of almost any mutation. There are a few cases in which it might be the right solution, however in most cases we should constrain signatures in a way that they are descriptive of more specific intentions and name these so that they describe the &lt;em&gt;action that should occur&lt;/em&gt; instead of the &lt;em&gt;state that should be set&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;Mutating cached API responses&lt;/h4&gt;
&lt;p&gt;Pages that receive data from an API, display it, update it and then send it back to the server should not mutate the cache of the original data that was received from the server. The reason for this is that it’s confusing for the client and the server to be out-of-sync and buggy if other pages or components rely on this data being correct. Instead it’s better to treat the server data as if it is immutable, and to store it separately from the data that the client is preparing for the server. A benefit of this is that it makes it much more explicit whether the data that is being sent back was provided by the server or whether it has been created or modified client-side.&lt;/p&gt;</description><author>@sebinsua</author><pubDate>Thu, 12 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sebinsua.com/avoiding-false-cause</guid></item><item><title>Finding Bugs in TensorFlow with LibFuzzer</title><link>https://da-data.blogspot.com/2017/01/finding-bugs-in-tensorflow-with.html</link><description>&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvOtmvkaQPB2fLRQRrIjtuW9WBpZRZZGI0wBe9nR11UvDJ97p1_EXZRpYU7WrE0RLA34QQIMgFvOECQ_lvTrp2bascZP6iO7vNuqA_bF4BrV53XZPzte-zq5_BmebDiNCma16Canh_N-I/s1600/xkcd_fuzzing_1137.png" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvOtmvkaQPB2fLRQRrIjtuW9WBpZRZZGI0wBe9nR11UvDJ97p1_EXZRpYU7WrE0RLA34QQIMgFvOECQ_lvTrp2bascZP6iO7vNuqA_bF4BrV53XZPzte-zq5_BmebDiNCma16Canh_N-I/s320/xkcd_fuzzing_1137.png" width="209" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://xkcd.com/1137/"&gt;xkcd 1137&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Over the past year, I've spent some time working on improving the robustness of TensorFlow. &amp;nbsp;As I mentioned earlier, one of my &lt;a href="https://da-data.blogspot.com/2016/04/stealing-googles-coding-practices-for.html"&gt;goals for my time at Google was to dive into industry best-practices for writing good code&lt;/a&gt;. &amp;nbsp;At Google, writing good code starts with careful programmers, requires good tests that get run on a &lt;a href="https://testing.googleblog.com/2016/11/what-test-engineers-do-at-google.html"&gt;fantastic internal testing infrastructure&lt;/a&gt;, is improved through &lt;a href="https://blog.fullstory.com/what-we-learned-from-google-code-reviews-arent-just-for-catching-bugs-b125a13aa292#.j8b66n6ap"&gt;code review&lt;/a&gt;, and makes use of several code quality tools and linters.&lt;br /&gt;
&lt;br /&gt;
One part of that testing that's been gaining more visibility recently is fuzzing - throwing random inputs at programs or libraries to try to cause them to crash. &amp;nbsp;&lt;a href="http://blog.regehr.org/archives/1039"&gt;John Regehr has been fuzzing compilers&lt;/a&gt; for a while now - very effectively. &amp;nbsp;(That link has a nice taxonomy of the types of fuzzers.) &amp;nbsp;Google's Project Zero has been &lt;a href="https://googleprojectzero.blogspot.in/2016/06/a-year-of-windows-kernel-font-fuzzing-1_27.html"&gt;fuzzing the FreeType library for the last 4 years&lt;/a&gt;, and has found a &lt;a href="https://bugs.chromium.org/p/project-zero/issues/list?can=1&amp;amp;redir=1"&gt;tremendous number of security vulnerabilities&lt;/a&gt;&amp;nbsp;in all sorts of programs. &amp;nbsp;&amp;nbsp;(This isn't to suggest fuzzing is new - it's been used for years by security researchers, and was invented in 1988 by &lt;a href="http://pages.cs.wisc.edu/~bart/fuzz/"&gt;Barton Miller&lt;/a&gt;. &amp;nbsp;Back in 1997, amusingly, before I knew what the term fuzzing was, a much younger me used a random input generator to find a &lt;a href="https://www.angio.net/consult/secadv/AA-1997-09-03.livingston-telnet.final"&gt;bug in the terminal servers I was deploying at my ISP.&lt;/a&gt;&amp;nbsp; I remember being very pleased with myself at the time -- probably excessively so.)&lt;br /&gt;
&lt;br /&gt;
Modern, production fuzzers such as &lt;a href="http://lcamtuf.coredump.cx/afl/"&gt;AFL&lt;/a&gt; and &lt;a href="http://llvm.org/docs/LibFuzzer.html"&gt;libFuzzer&lt;/a&gt; aren't purely random, they can be guided: &amp;nbsp;They start with an input "corpus" of examples, and then mutate them. &amp;nbsp;They use compiler and binary rewriting support to guide the exploration of mutations to maximize code coverage. &amp;nbsp;The combination of a good starting corpus and coverage-guided mutation makes for impressive results.&lt;br /&gt;
&lt;br /&gt;
Midway through my year at Google, &lt;a href="http://colah.github.io/"&gt;Chris Olah&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/dario-amodei-3934934"&gt;Dario Amodei&lt;/a&gt;, and &lt;a href="https://twitter.com/danmane?lang=en"&gt;Dan Mané&lt;/a&gt; started writing their &lt;a href="https://arxiv.org/pdf/1606.06565.pdf"&gt;Concrete Problems in AI Safety paper&lt;/a&gt;. &amp;nbsp;While many of the problems and solutions they discuss are in the realm of machine learning, I was interested in the question of the systems side, provoked in part by their example of a machine intelligence-based system exploiting a buffer overflow in its reward function (by accident, but producing undesirable results). &amp;nbsp;A malfunctioning reward function isn't the kind of thing that traditional isolation approaches such as sandboxing can prevent - it manifests as a logic bug, not an escape-into-the-rest-of-the-system. &amp;nbsp;Not that it's a complete solution, but it made me curious whether there was value in trying to fuzz TensorFlow. &amp;nbsp;And so, encouraged by&amp;nbsp;Kostya Serebryany, I decided to write some adapters from libFuzzer to some of the TensorFlow kernels.&lt;br /&gt;
&lt;br /&gt;
(For those who note that some of these bugs wouldn't have existed in more strongly-typed or safe languages, you're probably right. &amp;nbsp;But high-performance machine learning software has very strong demands on it from both a performance, correctness, and flexibility perspective, and I'm very sympathetic to the challenge of achieving all three of these goals simultaneously. &amp;nbsp;I'm hopeful that the new XLA compiler framework might make it easier to achieve them, but since it's still a work-in-progress, that remains to be seen!)&lt;br /&gt;
&lt;h4&gt;
How to Fuzz&lt;/h4&gt;
All libFuzzer tests start by writing a single function that tests a library call or calls, &lt;a href="http://llvm.org/docs/LibFuzzer.html#id24"&gt;like this&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;span class="c1" style="color: #60a0b0; font-style: italic;"&gt;// fuzz_target.cc&lt;/span&gt;
&lt;span class="k" style="color: #007020; font-weight: bold;"&gt;extern&lt;/span&gt; &lt;span class="s" style="color: #4070a0;"&gt;"C"&lt;/span&gt; &lt;span class="kt" style="color: #902000;"&gt;int&lt;/span&gt; &lt;span class="n"&gt;LLVMFuzzerTestOneInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k" style="color: #007020; font-weight: bold;"&gt;const&lt;/span&gt; &lt;span class="kt" style="color: #902000;"&gt;uint8_t&lt;/span&gt; &lt;span class="o" style="color: #666666;"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt" style="color: #902000;"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;DoSomethingInterestingWithMyAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k" style="color: #007020; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span class="mi" style="color: #40a070;"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1" style="color: #60a0b0; font-style: italic;"&gt;// Non-zero return values are reserved for future use.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
When the compiled fuzzing binary is executed, it repeatedly invokes this function with "random" (mutated) data supplied in &lt;span&gt;Data&lt;/span&gt;. &amp;nbsp;It's your job as the fuzzing adapter writer to figure out how to map that blob of random data to calls to your application.&lt;br /&gt;
&lt;br /&gt;
When fuzzing, the binary is typically compiled with &lt;a href="http://clang.llvm.org/docs/AddressSanitizer.html"&gt;LLVM's address sanitizer&lt;/a&gt;, which detects several common memory errors, such as out-of-bounds array accesses, and turns them into a crash. &amp;nbsp;The libFuzzer driver detects that crash and saves the example that caused it. &amp;nbsp;An output might look something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;dga@instance-1:~/fuzz$ ./fuzz&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;INFO: Seed: 44456222&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;INFO: Loaded 0 modules (0 guards):&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;INFO: -max_len is not provided, using 64&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;INFO: A corpus is not provided, starting from an empty corpus&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;#0&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;READ units: 1&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;#1&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;INITED cov: 8 units: 1 exec/s: 0&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;#2&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;NEW&amp;nbsp; &amp;nbsp; cov: 9 units: 2 exec/s: 0 L: 64 MS: 0&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;=================================================================&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;==1310==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff56ccc6e8 at pc 0x0000004f69e1 bp 0x7fff56ccc690 sp 0x7fff56ccc688&lt;/span&gt;&lt;/div&gt;













&lt;br /&gt;
&lt;div class="p3"&gt;
&lt;span class="s1" style="background-color: #f3f3f3;"&gt;WRITE of size 4 at 0x7fff56ccc6e8 thread T0&lt;/span&gt;&lt;/div&gt;
&lt;span style="background-color: #f3f3f3;"&gt;&lt;br /&gt;&lt;/span&gt;
Leaving behind a file that can be used to reproduce the crash. &amp;nbsp;After you fix the bug, you would typically add this file to the fuzz seed set to prevent regressions.&lt;br /&gt;
&lt;h4&gt;
What to Fuzz in TensorFlow?&lt;/h4&gt;
Much of what TensorFlow does is numeric, and finding bugs in those operations is important - it prevents massive headaches when trying to debug why a model isn't working, for example. &amp;nbsp;But testing the numerical results requires a reference or spec that's (believed to be) correct. &amp;nbsp;Some of the tests for the XLA compiler for TensorFlow do this, for example, &lt;a href="https://github.com/tensorflow/tensorflow/blob/f94e20f2c704f037a113d350fd7c431e3fd75df8/tensorflow/compiler/tests/randomized_tests.cc"&gt;by using the CPU version as a reference and ensuring that the XLA version produces the same answer.&lt;/a&gt;&amp;nbsp; This is an important set of tests for ensuring the correctness of XLA, but when I started writing my version, I didn't have a reference, and didn't want to try to write a spec for every operation.&lt;br /&gt;
&lt;br /&gt;
Instead, I focused on the thing Fuzzing tends to do best, which is finding crashes. &amp;nbsp;I started with the lowest-hanging fruit, and the place I thought bugs were most likely to linger: &amp;nbsp;Complex input parsers. &amp;nbsp;TensorFlow includes functions to encode and decode several image formats, such as &lt;span&gt;&lt;a href="https://www.tensorflow.org/api_docs/python/image/encoding_and_decoding#decode_png"&gt;tf.image.decode_png&lt;/a&gt;&lt;/span&gt;. &lt;br /&gt;
&lt;br /&gt;
Starting with the image decoders made things easy - you can find existing corpora of example inputs to start with, and the functions effectively take only a single input, the string to decode into a Tensor.&lt;br /&gt;
&lt;h4&gt;
Many bugs found and fixed.&lt;/h4&gt;
This approach found bugs in the &lt;a href="https://github.com/tensorflow/tensorflow/commit/293c0900d5511e63162a5bd71fc7a578519751d4"&gt;PNG decoder&lt;/a&gt; and the &lt;a href="https://github.com/tensorflow/tensorflow/commit/dfe46341cc73c98a111a6610e0d3daa77fe549e9"&gt;JPEG decoder&lt;/a&gt;. &amp;nbsp;Extra fuzzing done using&amp;nbsp;&lt;a href="https://testing.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html"&gt;automatic fuzzing infrastructure&lt;/a&gt;&amp;nbsp;then turned up more, which Brennan Saeta &lt;a href="https://github.com/tensorflow/tensorflow/commit/5e0c9fff657498f9a74da38b2ce1b4721698a388"&gt;kindly fixed&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
After bashing against the image decoders, I turned to some of the string parsing functions, again finding a &lt;a href="https://github.com/tensorflow/tensorflow/commit/7231d01fcb2cd9ef9ffbfea03b724892c8a4026e"&gt;subtle bug in the strtonum function&lt;/a&gt;. &amp;nbsp;And then &lt;a href="https://github.com/tensorflow/tensorflow/commit/a1f2e1ebe0b371714e164addd79e651b1786c5cd"&gt;again in the TensorProto parser&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Interestingly, Fuzzing didn't just find the expected buffer overflows or other failures -- it also pointed out places where the code was unnecessarily fragile in their error handling.&lt;br /&gt;
&lt;br /&gt;
A general design principle in TensorFlow is that errors in a kernel should be returned to the caller in a friendly way, so that they can deal with it appropriately. &amp;nbsp;A common pattern for handling this is to write code &lt;a href="https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/kernels/as_string_op.cc#L40"&gt;like this&lt;/a&gt;, in which immediately after entering the kernel, the programmer writes checks for as many error conditions as can be caught up-front:&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class="pl-k"&gt;explicit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="pl-en"&gt;AsStringOp&lt;/span&gt;&lt;span&gt;(OpKernelConstruction* ctx) : OpKernel(ctx) {&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;...&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class="pl-c1"&gt;OP_REQUIRES_OK&lt;/span&gt;&lt;span&gt;(ctx, ctx-&amp;gt;&lt;/span&gt;&lt;span class="pl-c1"&gt;GetAttr&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;T&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &amp;amp;dtype));&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&lt;span style="background-color: white; font-size: 12px; white-space: pre;"&gt;&amp;nbsp;   &lt;/span&gt;&lt;/span&gt;&lt;span class="pl-c1"&gt;OP_REQUIRES_OK&lt;/span&gt;&lt;span&gt;(ctx, ctx-&amp;gt;&lt;/span&gt;&lt;span class="pl-c1"&gt;GetAttr&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;precision&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &amp;amp;precision));&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&lt;span style="background-color: white; font-size: 12px; white-space: pre;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&lt;span style="background-color: white; font-size: 12px; white-space: pre;"&gt;    ... do the work here after making sure the above worked ...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This is good design for any library, since it doesn't impose your idea of failure handling on your users. &amp;nbsp;By throwing the fuzzer at TensorFlow, I was able to find a few places where &lt;a href="https://github.com/tensorflow/tensorflow/commit/f19b35458929908c1f6d8590f97615d976dafaa6"&gt;errors resulted in program termination&lt;/a&gt;&amp;nbsp;instead of having a friendly return.&lt;br /&gt;
&lt;h4&gt;
I've Become a Fan of Fuzzing&lt;/h4&gt;
Before this, I'd primarily thought of fuzzing as something you did to find security holes in other people's code. &amp;nbsp; Now I've changed my tune, and I'm convinced that using a modern fuzzer is a great part of normal software development and testing. &amp;nbsp;They won't find all of your bugs, and you have to write the adapters to let them get inside your functions, but they'll teach you new things about your code and help you find problems before they manifest in the real world. &amp;nbsp;I'm sold.&lt;br /&gt;
&lt;br /&gt;
If you're interested in trying it out on your own code, a good next step would be the &lt;a href="https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md"&gt;libFuzzer tutorial&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Happy bug squishing!&lt;br /&gt;
&lt;br /&gt;
(For more of my posts, see &lt;a href="https://da-data.blogspot.com/p/blog-page.html"&gt;the archive&lt;/a&gt;.)</description><author>Dave's Data</author><pubDate>Wed, 11 Jan 2017 22:48:27 GMT</pubDate><guid isPermaLink="true">https://da-data.blogspot.com/2017/01/finding-bugs-in-tensorflow-with.html</guid></item><item><title>Stealing Google's Coding Practices for Academia</title><link>https://da-data.blogspot.com/2016/04/stealing-googles-coding-practices-for.html</link><description>I'm spending the year in &lt;a href="http://research.google.com/research-outreach.html#/research-outreach/faculty-engagement"&gt;Google's Visiting Faculty&lt;/a&gt; program. &amp;nbsp;I had a few goals for my experience here:&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9mZO_e2h2FHp14TlKw9sYgZs3UUTUos5SQXyAlsaIHuVQWl0yWq_6zfZpGVP3AN4oAHGQJlYuqJEXTxeDU3lt5ttMlOjYm2D4yPpP1xtQIRVK3JD78nG7Iy5yljqvXrMiq3J4By9T3uM/s1600/Screenshot+2017-01-11+11.31.07.png" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9mZO_e2h2FHp14TlKw9sYgZs3UUTUos5SQXyAlsaIHuVQWl0yWq_6zfZpGVP3AN4oAHGQJlYuqJEXTxeDU3lt5ttMlOjYm2D4yPpP1xtQIRVK3JD78nG7Iy5yljqvXrMiq3J4By9T3uM/s200/Screenshot+2017-01-11+11.31.07.png" width="163" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;From &lt;a href="http://xkcd.com/378/"&gt;xkcd 378&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Learn learn learn&lt;/b&gt;! &amp;nbsp;I hoped to get a different perspective from the inside of the largest collection of computing &amp;amp; distributed systems that the world has ever seen, and to learn enough about machine learning to think better about providing systems support for it. &amp;nbsp;I haven't been disappointed.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Do some real engineering&lt;/b&gt;. &amp;nbsp;I spend most of my time as a faculty member teaching &amp;amp; mentoring my Ph.D. students in research. &amp;nbsp;I love this - it's terribly fun and working with fantastic students is an incredibly rewarding experience. &amp;nbsp;But I also get a lot of creative satisfaction from coding, and I can only carve out a bit of my faculty time to dedicate to it. &amp;nbsp;I haven't written large amounts of production code since I was 21 - and the world has changed a lot since then. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Contribute something useful &lt;/b&gt;to Google while I was here. &amp;nbsp;They're paying my salary for the time I'm here, so I figure I shouldn't be a completely useless sponge that just spends all the time playing with their toys.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
It's been a blast. &amp;nbsp;I &lt;i&gt;have&lt;/i&gt;&amp;nbsp;learned a ton, and I've gotten to write quite a bit of code. &amp;nbsp;As it turns out, I've been working on two relatively orthogonal programming-heavy projects: &amp;nbsp;One with a research flavor aimed at scaling training deep neural networks better across more workers, and one with an engineering flavor aimed at cleaning up the &lt;a href="https://www.tensorflow.org/"&gt;TensorFlow&lt;/a&gt; code to better support really big tensors. &amp;nbsp;(As Gates may or may not have famously noted, "Surely 2 billion entries in a Tensor is enough for anybody").&lt;br /&gt;
&lt;br /&gt;
This latter engineering effort has focused on both handling big tensors and returning more semantically helpful error messages when programmers try to push too much stuff through ops that have been optimized by using, e.g., 32 bit pointers. &amp;nbsp;(Particularly without Google's&amp;nbsp;&lt;a href="http://research.google.com/pubs/pub45226.html"&gt;GPUCC compiler, used internally,&lt;/a&gt; using 64 bit indices for accessing tensors is quite slow in CUDA). &amp;nbsp;I picked the cleanup job for a few reasons. &amp;nbsp;First, I wanted to get a very hands-on feel for what was involved in making the TensorFlow (or mxnet, or any modern deep learning framework) code be "correct" -- I have an itch here that I hope to explore post-sabbatical that TensorFlow and the related systems are absolutely ripe for a more formal specification and code generation approach, and I wanted to get my hands dirty across a variety of the kernels to better understand the gross reality of lots of high-performance C++ code. &amp;nbsp;And it scratches my itch of getting my feet dirty with real-world software engineering that's useful to people inside &amp;amp; outside of Google: &amp;nbsp;You break TensorFlow, you break &lt;a href="https://www.tensorflow.org/versions/r0.8/resources/uses.html"&gt;RankBrain and SmartReply&lt;/a&gt;. &amp;nbsp;Fix bugs, everyone gets epsilon happier.&lt;/div&gt;
&lt;h3&gt;
Stealing Ideas Back To Academia&lt;/h3&gt;
&lt;div&gt;
One of my explicit goals was to steal ideas from Google that I could feed back into teaching and mentoring. &amp;nbsp;There's a long-running discussion about academic code vs production code, and Google is widely viewed as having &lt;a href="https://www.quora.com/What-is-Googles-internal-code-review-policy-process"&gt;a well-orchestrated code review&lt;/a&gt; and &lt;a href="https://google.github.io/styleguide/cppguide.html"&gt;style guide&lt;/a&gt; process, combined with &lt;a href="http://google-engtools.blogspot.com/2011/05/c-at-google-here-be-dragons.html"&gt;very helpful tooling&lt;/a&gt;, that produces &lt;a href="https://www.quora.com/What-is-the-code-quality-at-Google-like"&gt;quite high quality code&lt;/a&gt;. &amp;nbsp;My experience thus far agrees with this general perception -- I've gotten great and actionable feedback on the code I've written, which has turned up bugs that were missed by tests, observed cleaner ways to write it, and noted problems that it might create in the future. &amp;nbsp;I'm sold, at least as the way code review is handled in the &lt;a href="https://research.google.com/teams/brain/"&gt;Brain group&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This leads immediately to the question:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;i&gt;What of this industrial approach can be profitably used in developing research code?&lt;/i&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/div&gt;
&lt;div&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div&gt;
Research &amp;amp; production code differ, and rightly so. &amp;nbsp;In many, though not all, cases, research code quickly becomes abandonware. &amp;nbsp;Fewer people work on it. &amp;nbsp;These combine to make it less worthwhile to support the kind of extensive testing that most industry code uses. &amp;nbsp;Testing, of course, serves a dual purpose of making sure the system works, and also of making it easier for someone to come along and make changes to it without wrecking everything.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://imgs.xkcd.com/comics/academia_vs_business.png" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="165" src="//imgs.xkcd.com/comics/academia_vs_business.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Not the goal of learning from industry programming.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
I encourage my students at CMU quite strongly to &lt;a href="https://github.com/efficient"&gt;release all of the code they develop&lt;/a&gt;, and to put a modest effort into making sure that someone else can run it later. &amp;nbsp; But with the exception of &lt;a href="https://github.com/efficient/libcuckoo"&gt;libcuckoo&lt;/a&gt;, we rarely support them on an ongoing basis. &amp;nbsp;So, &lt;i&gt;without slowing down our ability to do research&lt;/i&gt;, or even &lt;i&gt;speeding it up&lt;/i&gt;, what can we learn from our industrial friends?&lt;/div&gt;
&lt;h4&gt;
1. &amp;nbsp;Arbitrary and capricious style adherence.&lt;/h4&gt;
&lt;div&gt;
Something I've seen both externally through the Go project, and internally at Google, is that mindlessly adhering to common formatting rules when the choices are approximately arbitrary, is a wonderful thing. &amp;nbsp;When possible, mechanize it - as go does through &lt;i&gt;gofmt&lt;/i&gt;. &amp;nbsp;Other students and external people can come in and pick up your code with less cognitive load to get into the spirit of it, and it's easier to edit other people's stuff.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Suggestion: &amp;nbsp;Just follow the &lt;a href="https://github.com/google/styleguide"&gt;Google Style Guides&lt;/a&gt;, since they're nice enough to publish them. &amp;nbsp;(For Python, PEP8 is probably the best choice if they ever differ, for compatibility with the rest of the world. &amp;nbsp;The Google style guide is mostly a superset of PEP8).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
As part of your onboarding process, get students set up with the appropriate dotfiles that just Do The Right Thing out of the box. &amp;nbsp;I've put a list in the next section. &amp;nbsp;What? &amp;nbsp;You're an academic research group that doesn't have a formal &lt;a href="https://en.wikipedia.org/wiki/Onboarding"&gt;onboarding process&lt;/a&gt;? &amp;nbsp;Yeah, neither does my group at CMU, and my time here has made me realize how important and useful it would be. &amp;nbsp;That's going to be the subject of a later blog post.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://imgs.xkcd.com/comics/code_quality.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="138" src="//imgs.xkcd.com/comics/code_quality.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
2 &amp;nbsp;Tooling, Tooling, Tooling.&lt;/h4&gt;
&lt;div&gt;
&lt;b&gt;Revision control: &amp;nbsp;&lt;/b&gt;Standardize on a revision control framework and a code review framework for your group. &amp;nbsp;GitHub is a natural choice if &lt;a href="https://education.github.com/"&gt;the educational discounts and free private repositories&lt;/a&gt; are sufficient for your needs. &amp;nbsp;If you do a lot of data management, you may find that GH isn't sufficient, but we've moved all of our group's stuff to it to good effect. &amp;nbsp;Key, though, is getting as much buy-in as possible from your students and other research groups around you. &amp;nbsp;There's a network effect involved in this that's useful to exploit. &amp;nbsp;It's also handy for students going on the industrial job market, since many employers like to see their GitHub profile. &amp;nbsp;Free resume! &amp;nbsp;Wahoo!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Auto-formatters&lt;/b&gt;: &amp;nbsp;Make it thought-free to follow the silly style guide. &amp;nbsp;Add the appropriate save hooks to your editors. This shouldn't take any of your brainpower, just automate it all.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Go: &amp;nbsp;&lt;a href="https://golang.org/cmd/gofmt/"&gt;gofmt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python: &amp;nbsp;pyformat&lt;/li&gt;
&lt;li&gt;C/C++: &amp;nbsp;&lt;a href="http://clang.llvm.org/docs/ClangFormat.html"&gt;clang-format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Java: &amp;nbsp;&lt;a href="https://github.com/google/google-java-format"&gt;google-java-format&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Compiler warnings, clang-tidy, pylint, etc.: &amp;nbsp;&lt;/b&gt;They're a bit nitpicky, but I'm pretty sold on mandating a clean pass when submitting code. Use all of the C/C++ warnings, both&amp;nbsp;&lt;span&gt;-Wall&lt;/span&gt;&amp;nbsp;and&amp;nbsp;&lt;span&gt;-Wextra&lt;b&gt;. &lt;/b&gt;&lt;/span&gt;&amp;nbsp;There's a bit of pain involved using them with rapidly-developing code, but it's offset by the extra bugs they catch.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Go: &amp;nbsp;&amp;nbsp;&lt;a href="https://golang.org/cmd/vet/"&gt;go vet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python: &amp;nbsp;&lt;a href="https://www.pylint.org/"&gt;pylint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;C/C++: &amp;nbsp;&lt;a href="http://clang.llvm.org/extra/clang-tidy/"&gt;clang-tidy&lt;/a&gt;&amp;nbsp; (plus -Wall -Wextra, and on clang, -Weverything)&lt;/li&gt;
&lt;li&gt;Java: &amp;nbsp;&lt;a href="http://errorprone.info/"&gt;errorprone.info&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
I'm particularly fond of pylint these days, because it catches quite a few errors that would normally be caught by the type system in other languages, letting you find more bugs before you even run your python program.&lt;br /&gt;
&lt;br /&gt;
Don't just tell people to use these tools: &amp;nbsp;Integrate them as a mandatory part of the build and code management system.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Be forgiving when people want to temporarily disable the warnings. &amp;nbsp;I'd be just fine with seeing a lot of &lt;span&gt;#pylint disable&lt;/span&gt;s in research code as long as it wasn't being abused.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Automate tests and experiments early on&lt;/b&gt;: &amp;nbsp;One thing I tell my students is that they should aim, when possible, to be able to run their experiments with a single command, regenerate the data files and graphs with at most one more, and rebuild the paper. &amp;nbsp;The same applies to tests, and it's probably low-overhead to get both automated from the very beginning.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I don't think that fully test-driven development is particularly necessary in academic code, but the right set of unit tests are &lt;i&gt;great&lt;/i&gt;&amp;nbsp;for rapidly iterating on your code, because they tell you when you broke something stupid. &amp;nbsp;I have a hypothesis that better testing might make it substantially easier to have summer interns or short-term undergrads work in your group.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://www.cs.cmu.edu/~hl/"&gt;Hyeontaek Lim &lt;/a&gt;notes,&amp;nbsp;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;Automatic tests and experiments are very useful in accelerating rapid&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;integration.&amp;nbsp; It can produce the final evaluation results with a high&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;level of robustness and reproducibility.&amp;nbsp; The practice of using&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;automatic test and experiments hinders bad habits of leaving uncommitted&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;changes and manual configuration of systems that many people fall into&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;while trying to get quick and dirty evaluation results.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;
I think this trap is particularly easy for people who've just come from undergrad, where lack of revision control and rapid hacking without a coherent development practice is the norm.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Bug tracking&lt;/b&gt;: &amp;nbsp;Sounds odd for an academic project, but I suspect that a bug tracker might be a nicely transparent way of managing the big todo list that's always associated with a project in a shared way.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;i&gt;But&lt;/i&gt;: &amp;nbsp;Your goal isn't to kill all the bugs. &amp;nbsp;It's to do research. &amp;nbsp;Be aggressive about pruning the bugs - use it as a GTD list that you can share with your colleagues more than a must-do list.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I don't feel as strongly about the importance of this for academic code, but if you think I'm wrong, comment below and let me know why!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;[Priority 2]: &amp;nbsp;Make it easy to use asan and tsan where applicable:&lt;/b&gt;&amp;nbsp; If you introduce your {students, advisor, colleagues} to &lt;a href="http://clang.llvm.org/docs/ThreadSanitizer.html"&gt;tsan&lt;/a&gt; and &lt;a href="http://clang.llvm.org/docs/AddressSanitizer.html"&gt;asan&lt;/a&gt;&amp;nbsp;and they get it integrated into their tests at the time a project starts, it's a great source of extra information that doesn't come at a high cost. &amp;nbsp;Me, I'd drop it like a hot potato if it started becoming a huge burden to maintain or was producing a lot of false positives, unless I was trying something very specific and tricky with concurrency. &amp;nbsp;This starts to become a pain with multi-language projects, but the cost is low if you're purely in C/C++.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;[Priority TBD] Continuous Integration systems are pretty awesome, but their utility may be higher for supported code&lt;/b&gt;: &amp;nbsp;At Google and almost all code-quality-focused companies, a CI system is one of the backbone elements of development. &amp;nbsp;&lt;a href="https://jenkins.io/"&gt;Jenkins&lt;/a&gt;, which seems to be the standard open source answer,&amp;nbsp;annoys me, but I do love finding bugs early. &amp;nbsp;If it were lower-overhead, I'd do it as a matter of course, but I'm not convinced that the tooling available &lt;i&gt;today&lt;/i&gt;&amp;nbsp;provides as much benefit in the academic environment except for those projects that you decide to really transition via a supported OSS release. &amp;nbsp;(Our libcuckoo work, or at the extreme end, projects like Spark.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I should have something intelligent here to say about balancing local language expertise with using a language best suited for the job, but I don't. &amp;nbsp;I'll leave this minefield for others to explore. :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Having access to the compute resources necessary to run this stuff reliably and consistently can be a challenge in the often very ad-hoc academic environment. &amp;nbsp;GitHub is a start, but as a community, we should put our heads together and identify ways to manage it better. &amp;nbsp;Cloud options are probably the answer, but it can be difficult to overcome the academic illusion that it's cheaper to do it by ourselves. &amp;nbsp;(It's not - we underprice our own and our students time!)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The same applies to writing papers. &amp;nbsp;For example, our group has a common &lt;a href="https://github.com/efficient/paper_skel"&gt;LaTeX paper skeleton framework&lt;/a&gt;&amp;nbsp;(it's on GitHub, anyone's welcome to use it and contribute), primarily developed by &lt;a href="http://www.cs.cmu.edu/~kaminsky/"&gt;Michael Kaminsky&lt;/a&gt;, that captures the essence of the ACM and Usenix templates but without the horrible legacy gloop. &amp;nbsp;People may have their favorite tricks, but it's awesome as an advisor to be able to intuitively navigate all of my students' papers source.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
(I'd love it if we made more progress as a community on standardizing our biblio handling. &amp;nbsp;&lt;a href="https://www.cs.cornell.edu/people/egs/"&gt;G&lt;span style="background-color: white;"&gt;ün&lt;/span&gt;&lt;/a&gt;&amp;nbsp;probably had it right with &lt;a href="https://www.cs.cornell.edu/people/egs/crosstex/"&gt;CrossTeX&lt;/a&gt; -- perhaps we should all join in the fray?)&lt;br /&gt;
&lt;h4&gt;
3. &amp;nbsp;Support Code Reviews, but thoughtfully.&lt;/h4&gt;
&lt;div&gt;
&lt;i&gt;Code review is shockingly awesome when done well. &amp;nbsp;&lt;/i&gt;My personal experience with it thus far is that I had &lt;i&gt;no clue how many bugs I introduced when writing code solo&lt;/i&gt;&amp;nbsp;that I'd later have to spend more effort filtering out with testing &amp;amp; debugging. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;A great code review mechanism in academic projects is pair programming. &amp;nbsp;&lt;/b&gt;The last major coding I did in an academic project was the &lt;a href="https://www.cs.cmu.edu/~dot-project/"&gt;Data-Oriented Transfer (DOT) project&lt;/a&gt;, where Michael Kaminsky and I mostly pair-programmed our parts of it. &amp;nbsp;It was a stellar experience - we wrote thousands of lines of often-intricate async code together that actually worked. &amp;nbsp;(Yes, it's nasty 2005-era async network code; &amp;nbsp;it would look drastically better if written using today's frameworks. &amp;nbsp;But it &lt;i&gt;was&lt;/i&gt;&amp;nbsp;2005, and it worked. :)&lt;br /&gt;
&lt;br /&gt;
Unbeknownst to me, two of my students also pair programmed large parts of the first &lt;a href="http://www.cs.cmu.edu/~fawnproj/"&gt;FAWN project&lt;/a&gt; prototypes, which is likely our group's most impactful overall research project to date. &amp;nbsp;(I hadn't known this until I asked for feedback on this article!) &amp;nbsp;&lt;a href="http://vijay.vasu.org/"&gt;Vijay&lt;/a&gt; noted:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="background-color: white; color: #212121; line-height: 19.5px;"&gt;&lt;span style="font-family: inherit;"&gt;I really enjoyed peer coding with &lt;a href="http://research.microsoft.com/en-us/um/people/amar/"&gt;Amar&lt;/a&gt; -- we only got FAWN stuff done so quickly because we were working on it together (both design, algorithms, and implementation).&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
But, of course, effective pair programming requires a lot of soft skills and compatible pairs. &amp;nbsp;I'm not going to pretend that this solution works everywhere.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Tool-based code review is easier in some ways, but adds challenges for academia. &amp;nbsp;&lt;/b&gt;I've&amp;nbsp;&lt;a href="https://github.com/tensorflow/tensorflow/commits/master?author=dave-andersen"&gt;committed a bunch of changes to TensorFlow&lt;/a&gt;&amp;nbsp;since it was open sourced (and since the machinery properly attributed commits to my GitHub handle). &amp;nbsp;Each of those commits had to be "LGTM" (looks good to me) by someone within Google,&amp;nbsp;&lt;i&gt;before&lt;/i&gt;&amp;nbsp;it could be submitted. &amp;nbsp;I term this "gating" code review. &amp;nbsp;Google's code review process is&amp;nbsp;&lt;a href="http://www.drdobbs.com/architecture-and-design/crash-course-in-lightweight-code-review/215800147"&gt;"lightweight", review tool-based&lt;/a&gt;&amp;nbsp;code review - much like you'd do using a tool like&amp;nbsp;&lt;a href="https://www.gerritcodereview.com/"&gt;Gerrit&lt;/a&gt;&amp;nbsp;(the link has some explanation of the review workflow for those unfamiliar).&lt;br /&gt;
&lt;br /&gt;
Lightweight tool-based code review is designed to provide benefits similar to pair programming in terms of extra eyes on the code, but without needing quite as close coupling. &amp;nbsp;When writing code without someone else's eyes on it, it turns out that I introduce errors&amp;nbsp;&lt;i&gt;all the time&lt;/i&gt;&amp;nbsp;that are subtle enough that they often get through tests. &amp;nbsp;(Of course, that's biased - if they break the tests, I catch them before I try to submit them. :)&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
A great recent example: &amp;nbsp;In &lt;a href="https://github.com/tensorflow/tensorflow/commit/227e7db4b0d3d9ff8325b1f0f3a2ee1f91c8eb0c#diff-2b59fd6036e9dc013fcba52270604687R255"&gt;this commit to TensorFlow&lt;/a&gt;, I changed the &lt;span&gt;sample_distorted_bounding_box.cc&lt;/span&gt; op&amp;nbsp;to return a polite error if you tried to resize an image with dimensions larger than could be stored in a 32 bit signed integer. &amp;nbsp;But in the first version of the code that I submitted for review, I didn't use the FastBoundsCheck function that I've tried to use throughout my changes for consistency. &amp;nbsp;(It also checks non-negative to catch any overflow-related weirdness.) &amp;nbsp;My reviewer noticed this and asked about it. &amp;nbsp;When I'd written the code initially, it hadn't compiled using that, because the kernel could be instantiated with float types for the size argument, and the boundscheck function was integer-only. &amp;nbsp;I'd simply written a quick inline test instead that could handle floats. &amp;nbsp;When I was asked in code review why I hadn't used the usual pattern, I realized that there was actually an underlying error: &amp;nbsp;The function was spec'd to handle only integral types (and, indeed, that's what the docs said) but the kernel had been registered for all numeric types. &amp;nbsp;Great find - the solution both kept the code the same as all other bounds check cases, and getting rid of the incorrect registrations (&lt;a href="https://github.com/tensorflow/tensorflow/commit/227e7db4b0d3d9ff8325b1f0f3a2ee1f91c8eb0c#diff-2b59fd6036e9dc013fcba52270604687R408"&gt;this line&lt;/a&gt;) saved compile time generating the unused floating point &amp;amp; double versions and reduced the code size of any generated TensorFlow program that used those ops. &amp;nbsp;&lt;i&gt;Code review can keep you honest&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
(And in one of my recent commits, my reviewer spotted that I'd unintentionally shadowed a variable, which had caused a test failure that was only caught by the later run of the CI system, because it occurred only in GPU code and I'd forgotten to run the GPU tests locally. &amp;nbsp;His sharp eyes saved me from having to debug the test failure -- he spotted exactly the problem, just by looking carefully for 10 minutes.)&lt;br /&gt;
&lt;br /&gt;
But code review can also slow things down &lt;i&gt;in the short term&lt;/i&gt;. &amp;nbsp;(Like, 10 minutes short term. :). &amp;nbsp;The truth is that most of the time "spent" is actually earned back -- perhaps with a multiplier -- in reduced debugging time. &amp;nbsp;But there can be problems when reviewers take too long, and as I note below, with managing very rapidly changing research code where you want to get some stuff committed quickly and keep moving. &amp;nbsp;While it's clear to me that there's huge value in code review, I might do it differently in academia.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Concrete suggestion: &amp;nbsp;&lt;/b&gt;When there are multiple students working on a project, provide the infrastructure for them to do code reviews, but consider not making them "gatekeeping" reviews -- just advisory. &amp;nbsp;(See, e.g., some &lt;a href="http://blog.smartbear.com/code-review/avoiding-the-politics-of-code-review/"&gt;organizational pitfalls of code reviews&lt;/a&gt;). &amp;nbsp;In general, "lightweight" code review &lt;a href="https://www.atlassian.com/agile/code-reviews"&gt;serves a few functions&lt;/a&gt;, and we should be careful to explicitly choose those functions we want in research:&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Maintaining stylistic / cultural coherence ("&lt;a href="https://www.quora.com/What-is-Googles-internal-code-review-policy-process"&gt;readability&lt;/a&gt;").&lt;/li&gt;
&lt;li&gt;Improving code quality.&lt;/li&gt;
&lt;li&gt;Giving programmers feedback for learning.&lt;/li&gt;
&lt;li&gt;Preventing bugs from reaching production.&lt;/li&gt;
&lt;li&gt;Keeping a team in sync with ongoing changes.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
From an academic perspective, on most projects, I argue the focus should be on speed, education, and communication, and early detection of flaws that would fundamentally invalidate the research. &amp;nbsp;From that perspective, supporting a form of &lt;b&gt;non-gating code review&lt;/b&gt;&amp;nbsp;may be an excellent way to balance things. &amp;nbsp;I'm going to try this when I get back to academia, but I'd love to hear from others who've tried it. &amp;nbsp;By non-gating, I mean post-commit review that provides feedback to the author, without being a stepping stone to getting additional code written.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
(In many code review environments, the process of building upon an outstanding CL (change list) adds extra work: &amp;nbsp;One usually patches in the pending CL into a new checkout of the repository and goes forward from there. &amp;nbsp;It adds some amount of mental and layout juggling that's a distraction. &amp;nbsp;I'm not convinced this cost is a good idea for standard research code.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The focus of academic code reviews should probably be more narrow than, e.g., Google's fairly widely-scoped "make the code excellent" approach. &amp;nbsp;Obviously, finding critical bugs is always important, but I think an approach that focuses on correcting one or two style issues, and/or showing the author one improved way to do things, is likely to be more appropriate for the academic environment. &amp;nbsp;I would &lt;i&gt;not&lt;/i&gt;&amp;nbsp;like my students spending an hour commenting about &lt;a href="https://github.com/golang/go/wiki/CodeReviewComments#comment-sentences"&gt;missing periods at the end of documentation comments&lt;/a&gt;&amp;nbsp;-- even though, for Go and in Google, I think it's a great policy that pays dividends for the 1000 other people who might have to read the docs generated from it. &lt;i&gt;Rationale:&lt;/i&gt; &amp;nbsp;Most academic code &amp;amp; code docs will be read by far fewer people and over a shorter period of time than industrial code, so biasing towards the write side is reasonable. &amp;nbsp;I &lt;i&gt;would&lt;/i&gt;&amp;nbsp;like my students identifying that someone had used an n^2 algorithm on a dataset large enough to benefit from an n log n algorithm, or noting that 20 lines of handling different cases would be &lt;a href="https://github.com/efficient/libcuckoo/commit/126af279621d43ec26068cf3c0ffaa996cf25230"&gt;more simply expressed by a quick-and-dirty sort of three items.&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Code reviews are only reasonable with good tooling &lt;i&gt;and&lt;/i&gt;&amp;nbsp;a culture that supports and welcomes them. &amp;nbsp;As a cultural note, don't view code review purely as knowledge flowing from the experienced to the uninitiated: &amp;nbsp; likely the biggest benefit is that it's just a different person taking a fresh look at the code. &amp;nbsp;It's the exact same benefit we get from asking colleagues to review our papers before we submit them -- we eventually become blind to what we've written. &amp;nbsp;Keep an open mind to the fruits of code review; &amp;nbsp;we're all in the academic game to keep learning, and it's a great tool.&lt;br /&gt;
&lt;br /&gt;
I suspect that GitHub's comments are a reasonable way to start for post-hoc commit review. &amp;nbsp;It's not nearly as effective or intuitive as using &lt;a href="https://www.gerritcodereview.com/"&gt;Gerrit&lt;/a&gt;, but sometimes keeping it simple is better. &amp;nbsp;Our group has tried a few of these approaches, and we're just on GitHub these days. &amp;nbsp;YMMV - and I'd love to hear how others successfully manage this.&lt;/div&gt;
&lt;h4&gt;
4. &amp;nbsp;Don't forget that you're not a company: &amp;nbsp;Release your junk!&lt;/h4&gt;
&lt;div&gt;
In the midst of all this industrial-styled verbiage, don't forget that you're a researcher, not a production engineer. &amp;nbsp;Release your code, even if it's crappy. &amp;nbsp;You never know when someone might need it for their own research, and the world is strictly better when your research products are available for others to build on, even if you're a little embarrassed about the quality of the code. &amp;nbsp;As a researcher, it's not your job to have the best thing ever: &amp;nbsp;It's your job to &lt;i&gt;be beaten later.&lt;/i&gt;&amp;nbsp; Make it easy for people to beat you by using your work as a stepping stone. &amp;nbsp;(They'll both cite you &lt;i&gt;and&lt;/i&gt;&amp;nbsp;thank you.)&lt;br /&gt;
&lt;h3&gt;
Footnotes&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: x-small;"&gt;1. &amp;nbsp;By research code, I mean the kind of code produced as part of a longer-term, larger research project leading to one or more published papers, implemented by one or more Ph.D. or M.S. students. &amp;nbsp;It's a separate and important question how to try to use some of these techniques in undergraduate education, but that's for another time.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-size: x-small;"&gt;Many thanks to Hyeontaek Lim, Vijay Vasudevan, and Matt Welsh for comments on draft versions of this document. &amp;nbsp;Thanks to Jeremy Manson for pointing out google-java-format and errorpone, and Bryan Mills for noting -Weverything for clang. All errors, opinions, and saying-of-stupid-things are purely my own fault. &amp;nbsp;And I assume that it's clear that while I'm spending the year at Google, this is all my personal opinion and take-away from the experience, not some official statement of any of the organizations I'm fortunate to be affiliated with.&lt;/span&gt;&lt;/div&gt;</description><author>Dave's Data</author><pubDate>Wed, 11 Jan 2017 18:32:02 GMT</pubDate><guid isPermaLink="true">https://da-data.blogspot.com/2016/04/stealing-googles-coding-practices-for.html</guid></item><item><title>Getting Started With Testing in Go</title><link>https://lucasfcosta.com/blog/Getting-Started-With-Testing-in-Go/</link><description>Hello, everyone! Today I'm gonna do something a little bit different from what I usually do. I'm not going to write about JavaScript, I'm going to write about Go!

Recently I have been writing Go ...</description><author>Lucas F. Costa - Blog</author><pubDate>Wed, 11 Jan 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Getting-Started-With-Testing-in-Go/</guid></item><item><title>2016 - Biggest Lesson, Most Dangerous Books</title><link>https://josh.works/2016-most-dangerous-books</link><description>&lt;p&gt;I don’t do New Years resolutions, but I like to think back on the last year.&lt;/p&gt;

&lt;p&gt;I’ll touch on two things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The most important thing I’ve learned this year: Tactical Silence&lt;/li&gt;
  &lt;li&gt;Most dangerous books of 2016&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id="tactical-silence"&gt;Tactical Silence&lt;/h1&gt;

&lt;p&gt;I suspect that a year from now, I’m going to look back and say “Man, I really dropped the ball on a lot of conversations and relationships up through 2016”.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Old Josh&lt;/em&gt; thought discussions went somewhere, and that I could change minds with words, in conversations directly about the thing I wanted to change.&lt;/p&gt;

&lt;p&gt;Hah. A helpful-but-reluctant read through &lt;a href="https://www.goodreads.com/book/show/1303.The_48_Laws_of_Power?ac=1&amp;amp;from_search=true"&gt;48 Laws of Power&lt;/a&gt;, couples with reading through &lt;em&gt;Life Together&lt;/em&gt;, and a few other sources, convinced me that direct discussion about most things where I’m trying to convince someone of something is more “entertaining-though-possibly-damaging pastime” than “productive effort”. This holds true in the work and private domains.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;em&gt;New Josh&lt;/em&gt; is cynical, and in most situations much less inflammatory. I don’t stand to gain anything from debates, and neither does the person I’m debating with.&lt;/p&gt;

&lt;p&gt;What DOES matter is action. No one really cares what I &lt;em&gt;think&lt;/em&gt; about anything, but as soon as I take &lt;em&gt;action&lt;/em&gt; on something, any potential conversation is dramatically shifted.&lt;/p&gt;

&lt;p&gt;Conversations go from hypothetical:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What if x happens&lt;/p&gt;

  &lt;p&gt;If that thing is true, than it might mean this other thing is false!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to historical:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Well, you did X, and it seems like Y and Z happened, so I guess going forward we’ll do…&lt;/p&gt;

  &lt;p&gt;I know I said X in the past, but it looks like we’re seeing Y results, and IMPORTANT_PERSON suggests Z response.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, now, when someone says something that is (to me) catastrophically untrue, about either myself or anything else, I just smile and nod. Even if I need to do something about it, it’s rare that addressing it right then will drive any useful change.&lt;/p&gt;

&lt;p&gt;“Tactical Silence” is still new to me, so I imagine in another month I’ll have much more coherent and consistent thoughts on it, but by then I’ll probably not want to talk about it.&lt;/p&gt;

&lt;p&gt;(I don’t even know where the term came from. I feel better keeping my mouth shut when it’s a &lt;em&gt;tactical&lt;/em&gt; decision, instead of &lt;em&gt;backing down from conflict&lt;/em&gt;)&lt;/p&gt;

&lt;h1 id="dangerous-books"&gt;Dangerous books&lt;/h1&gt;

&lt;p&gt;I read a lot last year. More than I plan on reading for a while, and along the way, I read many books that I wouldn’t really recommend to others, and a few that I would.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;dangerous&lt;/em&gt; book is one that did one of two two things, against my will:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Forced behavioral change in my daily or weekly routine&lt;/li&gt;
  &lt;li&gt;Forced my thinking to change on a specific topic or domain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These books are dangerous because they’re driving changes in how I behave and/or how I think. I am able to exert precious little control over both of these things, and am therefore exceedingly wary in letting outside influences in. So, when something &lt;em&gt;forces&lt;/em&gt; me to behave or think differently, I must admit temporary defeat, even though I’m inevitably improved in the process.&lt;/p&gt;

&lt;p&gt;I don’t &lt;em&gt;endorse&lt;/em&gt; any of these, though there’s lots of potential value in all of them.&lt;/p&gt;

&lt;p&gt;Here’s the books that I label as &lt;em&gt;dangerous&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/10266902-selfish-reasons-to-have-more-kids"&gt;Selfish Reasons to Have More Kids&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/998062.The_Market_for_Liberty"&gt;The Market for Liberty&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25744928-deep-work"&gt;Deep Work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/174845.Life_Together"&gt;Life Together&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/33229792-80-000-hours"&gt;80,000 Hours&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;If your curiosity is even remotely piqued on any of these books, check out reviews on Amazon or GoodReads.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id="selfish-reasons-to-have-more-kids"&gt;Selfish Reasons to Have More Kids&lt;/h3&gt;

&lt;p&gt;This easily pushed me over the edge from “I don’t look forward at all to the burdens of parenthood” to “it’ll be hard, but I think the reward will fairly quickly outpace the effort, and the long-term gains certainly outweigh the short-term sacrifice.”&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Josh, that’s a terrible reason to have kids. You think the long-term gains outweigh the short-term sacrifice? What about love, and your own flesh-and-blood? Doesn’t that matter?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not to me, right now. I imagine it will eventually. Also, this is a small picture into my decision-making about many things. Imagine what it’s like for Kristi, putting up with this all day long…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/dp/B004OA64Q6/ref=dp-kindle-redirect?_encoding=UTF8&amp;amp;btkr=1"&gt;Amazon: Selfish Reasons to Have More Kids&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="the-market-for-liberty"&gt;The Market for Liberty&lt;/h3&gt;

&lt;p&gt;Sigh. Here marks my transition “Libertarian” to “certified tin-foil-hat-wearing anarchist”. I didn’t even like the book, but there was one key point in the book that I couldn’t shake.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A laissez-faire society is not a Utopia in which the initiation of violence is impossible. Rather, it is a society which does not &lt;em&gt;institutionalize&lt;/em&gt; the initiation of force and in which there are means for dealing with aggression justly when it does occur.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, what system has a monopoly on the lawful initiation of force, and which also institutionalizes bad actors inside that system?&lt;/p&gt;

&lt;p&gt;The government.&lt;/p&gt;

&lt;p&gt;This ties into some other themes that have been growing in my head for a few years. Tinkering around the edges of a system that institutionalizes the initiation of force, and is able to coerce it’s own survival on the backs of those who serve it… is a luxury, since it’s steamrolling over the lives of many others.&lt;/p&gt;

&lt;p&gt;Related: the last book that made me cry while reading it: &lt;a href="https://www.goodreads.com/book/show/17834926-negroes-and-the-gun?ac=1&amp;amp;from_search=true"&gt;Negroes and the Gun: The Black Tradition of Arms&lt;/a&gt;. Spoiler: The government simultaneously claimed to act in the interests of it’s citizens as it hunted down and destroyed innocent-but-marginalized people.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Market-Liberty-Morris-Tannehill-ebook/dp/B007N7JDLA/ref=sr_1_1?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1484174882&amp;amp;sr=1-1&amp;amp;keywords=the+market+for+liberty"&gt;Amazon: The Market for Liberty&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="deep-work"&gt;Deep Work&lt;/h3&gt;

&lt;p&gt;I wrote &lt;a href="https://josh.works/i-quit"&gt;I quit&lt;/a&gt; after reading &lt;em&gt;Deep Work&lt;/em&gt;. I started wearing a wrist-watch, and I now work in &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique"&gt;Pomodoros&lt;/a&gt;. As I track how much work I do, I mostly just track how many Pomororo’s I’ve accomplished in a given day.&lt;/p&gt;

&lt;p&gt;I’m still slowly remaking how I work and my daily routine in response to &lt;em&gt;Deep Work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No other book that I’ve read this year has impacted my day to day as &lt;em&gt;Deep Work&lt;/em&gt; by Cal Newport.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Deep-Work-Focused-Success-Distracted-ebook/dp/B00X47ZVXM/ref=sr_1_1?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1484174924&amp;amp;sr=1-1&amp;amp;keywords=deep+work"&gt;Deep Work on Amazon&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="life-together"&gt;Life Together&lt;/h3&gt;

&lt;p&gt;Life Together is about Christians living in community. This exact topic has been plaguing me for the better part of two years, and &lt;em&gt;Life Together&lt;/em&gt; brought a lot of hope and clarity to me.&lt;/p&gt;

&lt;p&gt;I’ve struggled with the notion of “Christian community” because I get so frustrated by much of what happens in churches, or is done on my behalf by “the church” (as defined by old white conservatives from America).&lt;/p&gt;

&lt;p&gt;I struggle to sit under the biblical authority of people who’s politics seem decidedly anti-christ-like. The temptation is to just walk away and try to carve out some little “church of Thompson”, and pretend like that is sufficient and Christ-honoring, but it isn’t.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Life Together&lt;/em&gt; was convicting, and is driving change in my daily routines. I’m going to re-read it soon and make another “wave” of changes, but the most encouraging thing was how much Bohhoeffer celebrates the virtue of keeping one’s mouth shut:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bonhoeffer’s Decisive Rule of Christian Fellowship: Every individual is prohibited from saying much of what occurs to him.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, I can celebrate the minor victories of keeping my mouth shut, most of the time.&lt;/p&gt;

&lt;p&gt;More on this topic another time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Life-Together-Dietrich-Bonhoeffer-ebook/dp/B005MJ2RPK/ref=sr_1_1?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1484175478&amp;amp;sr=1-1&amp;amp;keywords=life+together"&gt;Amazon: Life Together&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="80000-hours"&gt;80,000 Hours&lt;/h3&gt;

&lt;p&gt;40 hours a week, 50 weeks a year, 40 years. That’s about 80,000 hours of work. How are you going to spend it?&lt;/p&gt;

&lt;p&gt;This book &lt;em&gt;isn’t&lt;/em&gt; driving change in my life right now, but it meshes perfectly with my already-heretical notions about what it means to “do good work for others”.&lt;/p&gt;

&lt;p&gt;I.E. Do you want to have a big impact on the world? Don’t become a doctor, at least if you plan on working in America. The marginal societal return of an additional doctor is tiny compared to that same doctor in a poor country, or compared to plenty of other career paths available to someone today.&lt;/p&gt;

&lt;p&gt;Don’t go work for a non-profit, either.&lt;/p&gt;

&lt;p&gt;The theme is “effective altruism”, and they handle job/career advice better than most. FWIW, they’re big fans of Cal Newport’s &lt;em&gt;Deep Work&lt;/em&gt; philosophy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/80-000-Hours-fulfilling-career-ebook/dp/B01M70QISP/ref=sr_1_1?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1484175534&amp;amp;sr=1-1&amp;amp;keywords=80000+hours"&gt;Amazon: 80,000 Hours&lt;/a&gt;&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Wed, 11 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/2016-most-dangerous-books</guid></item><item><title>2016 Year in Review</title><link>https://solomon.io/2016-year-in-review/</link><description>Taking time at the end of the year to reflect is a great exercise. It allows me to think through things that went both well and poorly.</description><author>Sam Solomon</author><pubDate>Wed, 11 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/2016-year-in-review/</guid></item><item><title>Open Financial Exchange (OFX)</title><link>https://denvaar.dev/posts/open_financial_exchange.html</link><description>Some information about using OFX for obtaining financial data.</description><author>denvaar's website</author><pubDate>Tue, 10 Jan 2017 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/open_financial_exchange.html</guid></item><item><title>All Quiet on the Western Front</title><link>https://apurva-shukla.me/bookshelf/all-quiet-on-the-western-front/</link><description>⭐ ⭐ ⭐ ⭐ ⭐ Spellbound, I was drawn in.

There’s honestly not much else to say than this novel is  greatest anti-war novel of all time; and…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Mon, 09 Jan 2017 14:02:40 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/all-quiet-on-the-western-front/</guid></item><item><title>How to build and deploy a private NuGet server on IIS or Azure</title><link>https://nicolaiarocci.com/how-to-build-and-deploy-a-private-nuget-server-on-iis-or-azure/</link><description>&lt;p&gt;Recently I had to build and deploy a private NuGet server. The
official &lt;a href="https://docs.nuget.org/ndocs/hosting-packages/overview"&gt;documentation&lt;/a&gt; is quite good, but I did hit some
(admittedly small) hitches along the way, so I thought I might as well share
the whole process. Hopefully this post will be helpful to the next guy or gal
adventuring down the same path.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If I don&amp;rsquo;t need to convince you on the usefulness and importance of packages
in modern software development, then you can safely jump to &lt;a href="#the-case-for-private-nuget-feeds"&gt;The case for
private NuGet feeds&lt;/a&gt;, and spare yourself
some of my ramblings.&lt;/em&gt;&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Mon, 09 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/how-to-build-and-deploy-a-private-nuget-server-on-iis-or-azure/</guid></item><item><title>Links - January 09, 2017</title><link>https://faingezicht.com/links/2017/01/09/links/</link><description/><author>Avy Faingezicht</author><pubDate>Mon, 09 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/01/09/links/</guid></item><item><title>Lineage of CBA CAD tools</title><link>https://mattkeeter.com/blog/2017-01-09-lineage</link><description/><author>Matt Keeter</author><pubDate>Mon, 09 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2017-01-09-lineage</guid></item><item><title>Simple but handy Postgres features</title><link>/2017/01/08/simple-but-handy-postgresql-features/</link><description>&lt;p&gt;It seems each week when I&amp;rsquo;m reviewing data with someone a feature comes up that they had no idea existed within Postgres. In an effort to continue documenting many of the features and functionality that are useful, here&amp;rsquo;s a list of just a few that you may find handy the next time your working with your data.&lt;/p&gt;
&lt;h3 id="psql-and-e"&gt;
&lt;div&gt;
Psql, and \e
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;This one I&amp;rsquo;ve &lt;a href="http://www.craigkerstiens.com/2013/02/13/How-I-Work-With-Postgres/"&gt;covered before&lt;/a&gt;, but it&amp;rsquo;s worth restating. Psql is a great editor that already comes with Postgres. If you&amp;rsquo;re comfortable on the CLI you should consider giving it a try. You can even setup you&amp;rsquo;re own &lt;code&gt;.psqlrc&lt;/code&gt; for it so that it&amp;rsquo;s well customized to your liking. In particular turning &lt;code&gt;\timing&lt;/code&gt; on is especially useful. But even with all sorts of customization if you&amp;rsquo;re not aware that you can use your preferred editor by using &lt;code&gt;\e&lt;/code&gt; then you&amp;rsquo;re missing out. This will allow you to open up the last run query, edit it, save–and then it&amp;rsquo;ll run for you. Vim, Emacs, even Sublime text works just take your pick by setting your &lt;code&gt;$EDITOR&lt;/code&gt; variable.&lt;/p&gt;
&lt;h3 id="watch"&gt;
&lt;div&gt;
Watch
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Ever sit at a terminal running a query over and over to see if something on your system changed? If you&amp;rsquo;re debugging something whether locally or even live in production, watching data change can be key to figuring out. Instead of re-running your query you could simply use the &lt;code&gt;\watch&lt;/code&gt; command in Postgres, this will re-run your query automatically every few seconds.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; now() &lt;span style="color: #f92672;"&gt;-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; query_start,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #66d9ef;"&gt;state&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; query
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; pg_stat_activity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #960050; background-color: #1e0010;"&gt;\&lt;/span&gt;watch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="jsonb-pretty-print"&gt;
&lt;div&gt;
JSONB pretty print
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I love &lt;a href="https://www.citusdata.com/blog/2016/07/14/choosing-nosql-hstore-json-jsonb/"&gt;JSONB&lt;/a&gt; as a datatype. Yes, in cases it won&amp;rsquo;t be the &lt;a href="http://blog.heapanalytics.com/when-to-avoid-jsonb-in-a-postgresql-schema/"&gt;optimal&lt;/a&gt; for performance (though at times it can be perfectly fine). If I&amp;rsquo;m hitting some API that returns a ton of data, I&amp;rsquo;m usually not using all of it right away. But, you never know when you&amp;rsquo;ll want to use the rest of it. I use &lt;a href="https://www.clearbit.com"&gt;Clearbit&lt;/a&gt; this way today, and for safety sake I save all the JSON result instead of de-normalizing it. Unfortunately, when you query this in Postgres you get one giant compressed text of JSON. Yes, you could pipe out to something like jq, or you could simply use Postgres built in function to make it legible:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-sql"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;SELECT&lt;/span&gt; jsonb_pretty(clearbit_response)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;FROM&lt;/span&gt; lookup_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; jsonb_pretty
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #75715e;"&gt;&lt;/span&gt; &lt;span style="color: #960050; background-color: #1e0010;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"person"&lt;/span&gt;: &lt;span style="color: #960050; background-color: #1e0010;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"id"&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;"063f6192-935b-4f31-af6b-b24f63287a60"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"bio"&lt;/span&gt;: &lt;span style="color: #66d9ef;"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"geo"&lt;/span&gt;: &lt;span style="color: #960050; background-color: #1e0010;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"lat"&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;37&lt;/span&gt;.&lt;span style="color: #ae81ff;"&gt;7749295&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"lng"&lt;/span&gt;: &lt;span style="color: #f92672;"&gt;-&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;122&lt;/span&gt;.&lt;span style="color: #ae81ff;"&gt;4194155&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"city"&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;"San Francisco"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"state"&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;"California"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"country"&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;"United States"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"stateCode"&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;"CA"&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"countryCode"&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;"US"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #960050; background-color: #1e0010;"&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; &lt;span style="color: #e6db74;"&gt;"name"&lt;/span&gt;: &lt;span style="color: #960050; background-color: #1e0010;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="importing-my-data-into-google"&gt;
&lt;div&gt;
Importing my data into Google
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;This one isn&amp;rsquo;t Postgres specific, but I use it on a weekly basis and it&amp;rsquo;s key for us at &lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt;. If you use something like Heroku Postgres, dataclips is an extremely handy feature that lets you have a real-time view of a query and the results of it, including an anonymous URL you can it for it. At Citus much like we did at Heroku Postgres we have a dashboard in google sheets which pulls in this data in real-time. To do this simple select a cell then put in: &lt;code&gt;=importdata(&amp;quot;pathtoyourdataclip.csv&amp;quot;)&lt;/code&gt;. Google will import any data using this as long as it&amp;rsquo;s in CSV form. It&amp;rsquo;s a great lightweight way to build out a dashboard for your business without rolling your own complicated dashboarding or building out a complex ETL pipeline.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m sure I&amp;rsquo;m missing a ton of the smaller features that you use on a daily basis. Let me know &lt;a href="https://www.twitter.com/craigkerstiens"&gt;@craigkerstiens&lt;/a&gt; the ones I forgot that you feel should be listed.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 08 Jan 2017 22:55:56 GMT</pubDate><guid isPermaLink="true">/2017/01/08/simple-but-handy-postgresql-features/</guid></item><item><title>Sherlock: Season 4</title><link>https://olshansky.info/tv/sherlock_season_4/</link><description>Olshansky's review of Sherlock: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 08 Jan 2017 14:00:49 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/sherlock_season_4/</guid></item><item><title>Lion</title><link>https://olshansky.info/movie/lion/</link><description>Olshansky's review of Lion</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 08 Jan 2017 11:55:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/lion/</guid></item><item><title>Docker in development</title><link>https://www.umarniz.com/docker-in-development/</link><description>Having used Docker on and off for lots of small dev environments in the past couple of years, containers have become by goto solution for…</description><author>Umar Nizamani | RSS Feed</author><pubDate>Sat, 07 Jan 2017 17:29:47 GMT</pubDate><guid isPermaLink="true">https://www.umarniz.com/docker-in-development/</guid></item><item><title>A metaphor</title><link>https://rjp.is/blogging/posts/a-metaphor-2/</link><description>In which we dip our toe into politics.</description><author>infrequent oscillations</author><pubDate>Sat, 07 Jan 2017 17:21:55 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/a-metaphor-2/</guid></item><item><title>Comparing MicroBus and MediatR</title><link>https://daniellittle.dev/comparing-microbus-and-mediatr</link><description>Mediators are an excellent addition to the developer toolbox. Allowing you to define a pipeline that is decoupled from any particular…</description><author>Daniel Little Dev</author><pubDate>Sat, 07 Jan 2017 04:09:43 GMT</pubDate><guid isPermaLink="true">https://daniellittle.dev/comparing-microbus-and-mediatr</guid></item><item><title>Ocean</title><link>https://june.kim/ocean/</link><author>june.kim</author><pubDate>Sat, 07 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/ocean/</guid></item><item><title>Links - January 7, 2017</title><link>https://faingezicht.com/links/2017/01/07/links/</link><description>2017 is off to a busy start. After posting on &lt;a href="/articles/2017/01/06/books/"&gt;books I read last year&lt;/a&gt;, gathering &lt;a href="/links/2016/12/30/101-things-from-2015/"&gt;links from the year before that&lt;/a&gt;, and sharing &lt;a href="/photos/2017/01/05/chicago/"&gt;photos of my last trip&lt;/a&gt; it is about time I curate some fresh links. Enjoy:</description><author>Avy Faingezicht</author><pubDate>Sat, 07 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2017/01/07/links/</guid></item><item><title>Ten minute hacks: Process pause &amp;amp; resume</title><link>https://purpleidea.com/blog/2017/01/06/ten-minute-hacks-process-pause-resume/</link><description>&lt;p&gt;I&amp;rsquo;m old school and still rocking an old X220 laptop &lt;a href="https://purpleidea.com/blog/2014/02/02/scathing-review-of-the-lenovo-x240/"&gt;because I didn&amp;rsquo;t like the new ones&lt;/a&gt;. My battery life isn&amp;rsquo;t as great as I&amp;rsquo;d like it to be, but it gets worse when some &amp;ldquo;webapp&amp;rdquo; (which I&amp;rsquo;d much rather have as a native &lt;a href="https://en.wikipedia.org/wiki/GTK%2B"&gt;GTK+&lt;/a&gt; app) causes Firefox to rev my CPU with their websocket (hi gmail!) poller.&lt;/p&gt;
&lt;p&gt;This seems to happen most often on planes or when I&amp;rsquo;m disconnected from the internet. Since it&amp;rsquo;s difficult to know which tab is the offending one, and since I might want to keep that tabs state anyway, I decided to write a little shell script to pause and resume misbehaving processes.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Fri, 06 Jan 2017 07:57:08 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2017/01/06/ten-minute-hacks-process-pause-resume/</guid></item><item><title>Books read in 2016</title><link>https://faingezicht.com/articles/2017/01/06/books/</link><description>One of my goals for this past year was to read at least one book a month, purely for leisure. At the current rate, it'll take me roughly 30 years to read all the books in &lt;a href="https://docs.google.com/spreadsheets/d/1VkbAVV86-HRxxl0PlCTVl_beF2GjvofUYeVyuNAAQTg/"&gt;my list&lt;/a&gt;. That's a scary thought. While not a super ambitious goal, 12 was a step in the right direction.

All 12 titles were worthwhile, and I would definitely recommend each one. Here's what I read in 2016:

&lt;div class="book-review"&gt;
  &lt;h4&gt;Cool Gray City of Love - Gary Kamiya&lt;/h4&gt;
  &lt;p&gt;A book about San Francisco's nooks and crannies, by a former cab driver/journalist who knows the city by heart. Traveling through time and space, Kamiya tells the history of the city through its booms and busts. At some point, I want to compile a list of all the locations mentioned in the book, and go experience them, one by one. In the meantime, I'd like to try out this audio tour narrated by the author.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;A Primate's Memoir - Robert M. Sapolsky&lt;/h4&gt;
  &lt;p&gt;Probably my favorite book this year. Sapolsky is a biology professor at Stanford, where all students know him for his Human Behavioral Biology course (available on YouTube). The book is non fiction, but reads as a novel, as the author tells us of his time in Kenya, following a troop of baboons. The primates show all sorts of human like behaviors, and Sapolsky shows us that they are not so different from us after all. Hilariously, he gives every animal a biblical name, which adds to the humorous and novelesque feel of the narration.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Why Information Grows - César Hidalgo&lt;/h4&gt;
  &lt;p&gt;I have known Hidalgo's work since I first saw the Atlas of Economic Complexity several years ago. His book extends on his research, tying up a bunch of concepts I am deeply interested in, such as computation, complex networks, international trade, incentives, growth, etc. The main point of the book is that while physics pushes us towards disorder, humanity has been able to build systems to accumulate knowledge and knowhow, effectively defying that trend. The only thing that sets our world apart from that of cavemen, is that we've figured out how to organize matter differently. The atoms are roughly the same.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Books V. Cigarettes - George Orwell&lt;/h4&gt;
  &lt;p&gt;This one I never planned to read, but on a bookless day at Hannah's I picked it up on a whim. It is an odd window into early XX century Britain. As the book says, \"Literature is an attempt to influence the viewpoint of one's contemporaries by recording experience,\" and this viewpoint would be completely unavailable to me if it weren't for Orwell writing it down. From childhood memories and the intricacies of education, to why people don't read, and the complexities of freedom, this collection of essays seems very relevant today. Overall, a good surprise.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;In The Beginning... Was The Command Line - Neal Stephenson&lt;/h4&gt;
  &lt;p&gt;I enjoyed reading the essay online so much that I ended up buying the book. It was that good. A good mix of history, tech culture and economics, told by a futurist science fiction author almost 20 years ago. Threading narratives and arguments around the business of open source software, and operating systems, Stephenson's essay kept me thinking about today's tech ecosystem. There are echoes of Microsoft's market power at the time on today's conversations about Facebook, Google, Apple, and even Amazon. Reading about the future as seen from the past is always a lot of fun.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Turing's Cathedral - George Dyson&lt;/h4&gt;
  &lt;p&gt;After putting it on my to do list years ago, I finally read it. I knew little about the history of early computers beyond \"John Von Neumann built a team of engineers at IAS and translated Turing's theory to practice.\" The many levels of abstraction that separate us from the physical problems these guys were solving never stopped perplexing me, and as I've kept repeating, it still amazes me that anything works. There is a lot to learn here about path dependence, team building, and leadership.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Between the World and Me - Ta-Nehisi Coates&lt;/h4&gt;
  &lt;p&gt;My life in this country has been inside two bubbles: four years at a private elite university on Chicago's North Shore followed by two years in San Francisco, the most expensive city in the US. My life experience, like most people's, is extremely narrow. This letter from a father to a son exposed me to a wide range of ideas, places, and feelings that few in my circles have lived. Listening to the audiobook, narrated by the author, gave it a whole other level of depth. At a time like this, when identity politics are so prevalent, I can't recommend this book enough. Sadly, the people that need to read it the most would not even consider it.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Surely You're Joking, Mr. Feynman! - Richard P. Feynman&lt;/h4&gt;
  &lt;p&gt;Another audiobook, this one about the life of a nobel winning phycisist. If you're unfamiliar with Feynman, I'd recommend you watch his explanation of how magnets work, followed by his commencement address on Cargo Cult Science (which is actually part of the book, too). The guy was a character.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;The Name of the Rose - Umberto Eco&lt;/h4&gt;
  &lt;p&gt;When Umberto Eco died at the beginning of the year, in February, I grabbed this book off a bookshelf and the first ~150 pages flew by in a day. Somehow, I got distracted for 8(!) months, but eventually got back to it. And I am glad I did. The historical novel is layered with studies of science, humanity, religion, and self awareness. Putting yourself in the mindset of a XIV century monk is interesting by itself, but the murder mysteries are wonderfully executed, which paired with the intricate symbolism make for a fantastic read.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;The Great Crash of 1929 - John Kenneth Galbraith&lt;/h4&gt;
  &lt;p&gt;While dry, this retelling of the great depression, and its context, was worth it. During my undergrad, when I took classes on international trade and monetary policy, the professor always made a point of explaining the history of large recessions, bubbles, and rallies. Economics is a science, and its macro subset is one with very few data points, making the deep analysis of every event quite important. The biggest takeaway I had was that while policy decisions and market structures can be influential, in the end it is people who, in aggregate, make the decisions that bring us booms and busts.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Do Androids Dream Of Electric Sheep - Phillip K. Dick&lt;/h4&gt;
  &lt;p&gt;In high school I read a bunch of dystopian books, and the title of Dick's novel called my attention back then, but I did not get around to reading it until this year. A tale of us vs. them where, as usual, the boundaries get fuzzy and in group and the out group blend into each other. I am convinced we're all machines, which is what makes the premise of this book interesting: trying to answer "What makes us human?" As a side note, it is way better than the movie.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Zealot - Reza Aslan&lt;/h4&gt;
  &lt;p&gt;Having grown up in an insular Jewish community within a strongly Catholic country, I unsurprisingly know very little about Christianity. I read this book to change that. The author's objective is to make clear distinctions between the historical Jesus and the religious Jesus, spending most of the book explaining the context in which Christianity came about as a branch of Judaism, and eventually graduated into its own religion. Reading about the Jewish history from a different angle, where heroes and champions are framed as failed messiahs was fascinating. Gotta love revisionist history.&lt;/p&gt;
&lt;/div&gt;

&lt;hr /&gt;

Additionally, I should mention there were a few technical/reference books that took up some of my time, but which I'll skip, plus these, which I started but stopped halfway:

* Atlas Shrugged
* The Circle
* Guns, Germs, and Steel
* Zen and the Art of Motorcycle Maintenance

The first two I have already dropped twice over the years, for no good reason. GGS I had on audiobook via &lt;a href="https://www.overdrive.com/"&gt;Overdrive&lt;/a&gt; and the loan expired before I could finish the book, so now I am in line again. Lastly, Zen and the Art of Motorcycle Maintenance was another "bookless at Hannah's" choice, but this one I have not worked through yet. These four might show up on next year's list.

This year, the goal is to bring the number up to 18, which should shave off 10 years of reading time, or so. I'll report back on these next year, but if you have a book recommendation, &lt;a href="/contact"&gt;let me know&lt;/a&gt; and I might add it to my stack!

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: self-portrait by me, previously posted on &lt;a href="/photos/2016/09/06/redwoods/"&gt;Up in the Redwoods&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Fri, 06 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2017/01/06/books/</guid></item><item><title>December Review, January Goals</title><link>https://josh.works/december-review-january-goals</link><description>&lt;p&gt;This is a follow-up from &lt;a href="/monthly%20evaluation/2016/12/20/december-2016-goals/"&gt;last month’s goals&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="1-deepen-knowledge-of-back-end-development"&gt;1. Deepen Knowledge of Back-end Development&lt;/h2&gt;

&lt;p&gt;I finished OverTheWire’s Bandit series, except &lt;a href="http://overthewire.org/wargames/bandit/bandit26.html"&gt;the last lesson&lt;/a&gt;, which didn’t make sense. (It does now! Turns out login shells and “regular” shells are different. I’ll take another spin at it some day.) A few benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Way more comfortable in my terminal&lt;/li&gt;
  &lt;li&gt;Way better with Less/Vim/Man pages&lt;/li&gt;
  &lt;li&gt;Basic understanding of Linux boxes, SSHing, looking around an unfamiliar system for things of note.&lt;/li&gt;
  &lt;li&gt;Better understanding of how terminal programs and scripts work (.vimrc, .bashrc), how things relate to each other in the $PATH, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;!--more--&gt;

&lt;p&gt;For example, before this, the following message wouldn’t have meant much to me:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;The test files may have the execution bit set so you may also be able to run it like this:
    ./hello_world_test.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;now, without any hesitation, I know that &lt;code class="language-plaintext highlighter-rouge"&gt;$ chmod u+x hamming_test.rb&lt;/code&gt; fixes the problem, and I’m off to the races.&lt;/p&gt;

&lt;p&gt;I worked through the &lt;a href="https://launchschool.com/books/oo_ruby/read/the_object_model"&gt;LaunchSchool Ruby “book”&lt;/a&gt;, and did lots of Anki memorization. I’m trying to absorb the basics of object oriented programing.&lt;/p&gt;

&lt;p&gt;Now I’m on &lt;a href="http://exercism.io/profiles/josh-works/6d8e0f83a1f048aeb99e46e6baf07ddf"&gt;Exercism&lt;/a&gt;. I’m not sure how far through I’m going to go, but it’s really useful on many levels. Interpreting error messages, getting tests to pass, test-driven development, etc. Reinforces what I’ve learned in the LaunchSchool material.&lt;/p&gt;

&lt;h2 id="2-rehab-my-wrist"&gt;2. Rehab my Wrist&lt;/h2&gt;

&lt;p&gt;I climbed hard three times last week, for the first time in almost two months. My wrist is still certainly weak, but as long as I avoid certain grip positions, I feel good. So, I can start easing back into projects, as long as I listen to it.&lt;/p&gt;

&lt;p&gt;I need to be better at climbing in a “defensive” manner anyway, if I plan on climbing in conjunction with difficult strength training, so this is fruitful experience, even though it’s sometimes a bit frustrating.&lt;/p&gt;

&lt;h2 id="3-finish-seven-more-books"&gt;3. Finish seven more books&lt;/h2&gt;

&lt;p&gt;Turns out I’d not counted my books that I’ve read this year correctly. I was aiming to get to 80 books (from 74 at the time) and once I updated my &lt;a href="https://www.goodreads.com/user_challenges/5318638"&gt;GoodReads profile&lt;/a&gt;, I was at 81 or so. I’ve now read 84 books this year, and don’t think I’ll finish any of my current books today. (Dec. 31)&lt;/p&gt;

&lt;h1 id="january-goals"&gt;January Goals&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Keep improving w/programming&lt;/li&gt;
  &lt;li&gt;Climb 5.13&lt;/li&gt;
  &lt;li&gt;Get a purchase page up, functioning for Climber’s Guide&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="1-programming-improvement"&gt;1. Programming improvement&lt;/h2&gt;

&lt;p&gt;Turing School starts Jan 23rd. I’m trying to pack in as much prep as I can before it starts. I’m working through some Exercism exercises, and trying to wrap my head around ruby basics, like manipulating/combining arrays and hashes, and understanding Enumerators.&lt;/p&gt;

&lt;p&gt;I’ve been using &lt;a href="https://ankiweb.net/about"&gt;Anki SRS&lt;/a&gt; for a long time now, in a variety of ways in my life. Mostly &lt;a href="/2-things-spanish"&gt;vocabulary memorization&lt;/a&gt;, but lots of other things too. Derek Sivers &lt;a href="https://sivers.org/srs"&gt;uses it to improve as a programmer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If it’s good enough for him, it’s good enough for me!&lt;/p&gt;

&lt;p&gt;Here’s the thing, though - I don’t yet have a good system for making cards. I can stick lots of information in the flashcards, but I’m not yet convinced that I’ve got the right method of quizzing myself with well-made cards.&lt;/p&gt;

&lt;p&gt;Fortunately, my Anki deck is easy to experiment with and modify!&lt;/p&gt;

&lt;p&gt;I plan on digging deeper in making programming-specific Anki flashcards later, but for now, the most useful Anki add-on is the &lt;a href="https://ankiweb.net/shared/info/162313389"&gt;Power Format Pack&lt;/a&gt;. It lets you apply markdown, including syntax-specific markdown, to your cards.&lt;/p&gt;

&lt;h2 id="2-climb-513"&gt;2. Climb 5.13&lt;/h2&gt;

&lt;p&gt;I hopped on a project yesterday in Earth Treks Golden, and could do all of the hard moves without much wrist discomfort. It’s certainly still weak, but it feels good to cause minor stress to it. I’m considering myself 90% healed.&lt;/p&gt;

&lt;p&gt;The two themes of the next few months for me, as far as climbing progression, will be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;remember my beta on routes&lt;/li&gt;
  &lt;li&gt;train max-weight hangs on an 18mm edge 2x/week.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="3-get-a-purchase-page-up-on-climbers-guide"&gt;3. Get a purchase page up on Climber’s Guide&lt;/h2&gt;

&lt;p&gt;I’ve got tons of copy written, tons of ideas around this, I’ve worked out pricing, but some stupid fear keeps me from actually asking for money. I’ve been working regularly with a few folks in the gym that I’ve bumped into, and they’ve all seen massive improvement in their climbing.&lt;/p&gt;

&lt;p&gt;The URL will probably be something like &lt;a href="http://www.climbersguide.co/conquer-fear-course/"&gt;http://www.climbersguide.co/conquer-fear-course/&lt;/a&gt; or something. We shall see!&lt;/p&gt;

&lt;p&gt;I’ll also record and post lots of video, talking through some of the finer points. Scary!&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Thu, 05 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/december-review-january-goals</guid></item><item><title>New Years in Chicago</title><link>https://faingezicht.com/photos/2017/01/05/chicago/</link><description>For the first time in several years, I did not go home to Costa Rica to celebrate the new year. Instead, we went to Chicago, and while we had packed expecting the polar vortex, the city welcomed us with warmth. So did our friends.

Oddly, this time around my photographs show way more of the city's character than on &lt;a href="/photos/2016/05/27/chicago/"&gt;my previous trip&lt;/a&gt;. Perhaps I've started to appreciate Chicago more, being away.</description><author>Avy Faingezicht</author><pubDate>Thu, 05 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2017/01/05/chicago/</guid></item><item><title>Daily Memory Drawings</title><link>https://johnj.com/posts/daily-memory-drawing/</link><description>&lt;figure&gt;





&lt;a href="https://johnj.com/dc-12-20-2016-wide.png"&gt;&lt;img class="resize" src="https://johnj.com/dc-12-20-2016-wide_hu_c28d731e7f694d0.png" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Riverside Plaza Memory Sketch
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Every day for the past three months I have drawn some
scene or event that I saw that day, purely from memory.&lt;/p&gt;
&lt;p&gt;
Usually this is something I saw on the way to work, or, if I'm home
that day, something I saw when out for a run or a walk somewhere in
the neighborhood.&lt;/p&gt;
&lt;p&gt;
Since I usually make the drawing at the end of the day, several hours
will have passed by the time I get around to recording what I saw. To
keep this purely about memory (with bits of invention as needed), I
don't allow myself any notes or photo references.  As a result, while
going about my day, I need to work extra hard to have a chance to
remember the things I see. Sometimes I'll stop on the street and spend
extra time looking at something, perhaps making little drawing
gestures in the air to build a little muscle memory about the shapes, and
no doubt drawing a stare or two from passersby. Other times if I've
seen something transitory while walking I'll look down at the sidewalk
and go over the scene in my mind with minimal distraction from new
visual inputs.&lt;/p&gt;
&lt;p&gt;
Throughout the day, if I think of it, I'll try to recall one or two
things I've seen to increase the chance of recall later.&lt;/p&gt;
&lt;p&gt;
When I sit down to draw, I first make a list of all the things I can
remember seeing, sometimes accompanied by small thumbnail
sketches.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20161224_0012_copy.png"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20161224_0012_copy_hu_782455d2b032b556.png" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Details remembered from Walk in Hyde Park
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Then I choose one thing as the subject of a larger, 15- to 20-minute drawing, usually 6"x8".&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/barber-9-26-2016sm.png"&gt;&lt;img class="resize" src="https://johnj.com/barber-9-26-2016sm_hu_16764434e5d42496.png" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Van Buren Barber Shop
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20161224_0013_copy.png"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20161224_0013_copy_hu_9b9c9f76eba2f33a.png" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
A Capella Band at Metra Entrance
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
While the drawings are usually not particularly good (and definitely
not "finished" by my usual standards), doing this exercise religiously
for awhile has had a few noticeable effects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The exercise forces me to get out of the house at least once per
day, no matter my schedule or the weather.&lt;/li&gt;
&lt;li&gt;The drawings seem to be getting a little better, and a little more
complex, on average.&lt;/li&gt;
&lt;li&gt;I can remember more at the end of the day, often enough to fill two
pages of notes and drawings.&lt;/li&gt;
&lt;li&gt;Things I see throughout the day are more vivid and can pack more
emotional punch.  I feel a stronger connection to my surroundings,
the city of Chicago in particular.&lt;/li&gt;
&lt;li&gt;Imagining or inventing things, coming up with ideas for drawings or
compositions, seems easier.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I have been appreciating the last two items especially.&lt;/p&gt;
&lt;p&gt;
I don't have a great memory, so this exercise sometimes feels
impossible, and involves a fair amount of staring off into space.
Like writing down dreams, however, once I get going, I tend to
remember more than I thought I would.&lt;/p&gt;
&lt;p&gt;
This activity is, with a minor variation or two, the "Daily
Composition" exercise proposed by Kimon Nicolaïdes in &lt;em&gt;The Natural Way
to Draw&lt;/em&gt;.  Without giving much explanation, he asserts,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No other exercise in the book is more important than this one. These
compositions do not have to be right. They can be &lt;em&gt;all wrong&lt;/em&gt;. The
important thing is to do them — three hundred and sixty-five of them
between today and this date next year. It will be helpful if you keep
this up for a year, and it will be twice as helpful if you keep it up
for two years. The really serious student will make a quick
composition every day for the rest of his life despite everything else
he has to do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
I first read about this exercise in the 1980s. How I wish I had
followed that advice consistently since then! Nevertheless, when I go
back and look at old sketchbooks and discover my occasional Daily
Compositions, no matter how bad the drawings, I do feel the strings of
memory vibrating strongly.&lt;/p&gt;
&lt;p&gt;
I think this exercise is hard to do consistently because, at first,
there isn't much to work with… nothing to &lt;em&gt;copy from&lt;/em&gt;.  A newcomer
to the exercise will struggle when all he or she has to work with is a
few wispy clouds of memory and spotty knowledge of lighting, anatomy,
weather, architecture, costume, etc. But working on one's weak spots
is a great way to improve.  In particular, when I go back to a spot
I've tried to draw, I notice many things I missed the first time. It's
fun to re-draw those things, armed with the extra knowledge.&lt;/p&gt;
&lt;p&gt;
It's also nice to have a fairly clear idea of &lt;em&gt;what to draw&lt;/em&gt; at least
once per day, without worrying about making it anything complicated or
clever. (Generally one of the day's memories stands out clearly as the
best subject for a drawing.)&lt;/p&gt;
&lt;p&gt;
All art considerations aside, this exercises exposes the vast extent
of my ignorance of the simplest things I encounter every day. The
process of learning to notice my environment more feels like a healthy
(albeit upstream) direction to take in a world where constant
distraction by one's smartphone has become the norm.&lt;/p&gt;
&lt;p&gt;
Since starting this exercise I've looked around for other references
to working from memory. It seems that the practice was more common in
the 19th Century.  Degas, in particular, and Whistler used memory
extensively in their work. More on this, perhaps, in later posts. In
any case, it seems to me that the practice is not given its due in
contemporary teaching and discourse (I don't remember any discussion
of it in art school).&lt;/p&gt;
&lt;p&gt;
What things that you see every day are worthy of your repeated
attention and study… or even memorization?&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_20161224_0008_copy.png"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20161224_0008_copy_hu_351571036dadd194.png" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Van Buren Memory Sketch
&lt;/figcaption&gt;
&lt;/figure&gt;</description><author>John Jacobsen</author><pubDate>Tue, 03 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/daily-memory-drawing/</guid></item><item><title>Instant form field validation with React's controlled inputs</title><link>https://goshacmd.com/instant-form-fields-validation-react/</link><author>Gosha Spark</author><pubDate>Tue, 03 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/instant-form-fields-validation-react/</guid></item><item><title>On-Prem Development Kubernetes Cluster Options</title><link>https://justingarrison.com/blog/2017-01-03-on-prem-development-kubernetes-cluster-options/</link><description>Kubernetes has a lot of options for running in cloud environments.</description><author>Justin Garrison's Homepage</author><pubDate>Tue, 03 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2017-01-03-on-prem-development-kubernetes-cluster-options/</guid></item><item><title>How to Write Assertions Right</title><link>https://lucasfcosta.com/blog/How-to-Write-Assertions-Right/</link><description>Hi, friends! Today I'm going to write about assertions.

I won't be talking about JavaScript, I'll be talking about assertions in general and this knowledge can be applied doesn't matter what lang...</description><author>Lucas F. Costa - Blog</author><pubDate>Mon, 02 Jan 2017 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/How-to-Write-Assertions-Right/</guid></item><item><title>Goa. 9 years later.</title><link>https://walkabout165.blogspot.com/2017/01/goa-8-years-later.html</link><description>My first Goa post I wrote most of a decade ago.&lt;br /&gt;
&lt;br /&gt;
A lot's changed - for example, the "King of Good Times" Vijay Malia's Kingfisher Villa in Candolim is in lien. &amp;nbsp;Many, many more local Indians (who the vast majority are male) have arrived for the 2017 New Years' celebration, and relatively few foreigners. &lt;br /&gt;
&lt;br /&gt;
I've also changed. &amp;nbsp; For example, this time, I haven't arrived alone. &amp;nbsp;You see, last year, my wife and I married, and this is the beginning of our honeymoon. &amp;nbsp;So I write as a honeymooner instead of a backpacker. &amp;nbsp;We've technically been calling this the "pre-honeymoon", as we're intending to arrive in Bhutan for the main deal. &lt;br /&gt;
&lt;br /&gt;
Finally, I couldn't help but see each of the two Goa trips as bookend moments in the expansion of my awareness of the world and my place in it as a person. &amp;nbsp;So I've also been drawn to thinking about how the world has changed in the past ten years. &lt;br /&gt;
&lt;br /&gt;
World: &amp;nbsp;China's ascendant. &amp;nbsp;The BRIC concept would have been more accurately captured with b-r-i-&lt;span style="font-size: x-large;"&gt;C&lt;/span&gt; &amp;nbsp;. &amp;nbsp;It's old news by now that the world's nations are turning inward on themselves currently in reaction to globalization. &amp;nbsp;(I don't need to mention who we elected president). &amp;nbsp;Canada stands out as having the only recently elected head of state with an outward-looking perspective. &amp;nbsp;Eyes will slowly turn to France and Germany to see if the conservative wave takes hold there too. &lt;br /&gt;
&lt;br /&gt;
The US notionally has a national healthcare system now. &amp;nbsp;It's under fire right now, and has built in flaws from the start like lack of single-payer and lack of national uniformity (and the resources / bargaining clout that would go with that). &amp;nbsp;I pay more for healthcare than I did before but I see it as at least an interim sacrifice if the country's most desperate can get adequate health care now. &lt;br /&gt;
&lt;br /&gt;
The developing world's middle class have swelled, even as the ranks of the developed world's middle class have contracted somewhat. &amp;nbsp;(Hint: they didn't head toward the rich end of things)&lt;br /&gt;
&lt;br /&gt;
India's working hard to fight corruption. As I write the country is in the midst of "demonetization" which is basically outlawing the largest denominations of currency and requiring them to be replaced with new currency, with the dual intent of flushing out black money, and getting India into a more trackable, more liquid cashless electronic payments society. &lt;br /&gt;
&lt;br /&gt;
Self: &amp;nbsp;First, I received a diagnosis and got treatment for sleep apnea. &amp;nbsp;(For anyone in the world who snores, including people I come across hearing you loudly dozing away on airplanes, I have enormous empathy for you). &amp;nbsp;Second, after a lot of ups and downs, highs and scars, I have a career that faces the world especially it's less fortunate (primarily in Africa) that leverages my technical experience. &amp;nbsp;Finally, as mentioned, I'm married now, to a woman I met in business school who is sincerely amazing. For all of these I feel truly blessed. &lt;br /&gt;
&lt;br /&gt;
One MBA (and a lot more independent reading) later, I understand economics better than I did before, but there is still so much to learn that is simply not taught in formal curriculae. &amp;nbsp;The closest I find is "input/output economics", and I am hopeful for what still-nascent economic simulations can teach us about the world we live in.&lt;br /&gt;
&lt;br /&gt;
During these couple days in Goa, my wife complains that I'm being too wistful / nostalgic, which she perceives as depressed, and not being present enough to her. &amp;nbsp;I try in vain to convince her otherwise, that I'm just a massive introvert. &amp;nbsp; (My writing this post isn't helping in the immediate term, but I think will help after I'm done and have got the feelings out of my head and onto paper). &lt;br /&gt;
&lt;br /&gt;
I think the key thing is that I need to "put the backpack down", even if my own self-image is the only remaining manifestation of that. &amp;nbsp;Although she loves travel, this kind of it is definitely not her thing: 4+-star hotels, not guesthouses. &amp;nbsp;Anyway our near term life plans are incompatible with anything resembling the backpacker lifestyle. &amp;nbsp;Again I hope this post helps with that. &lt;br /&gt;
&lt;br /&gt;
Our next stop is Bhutan, the "land of happiness". &amp;nbsp;I sincerely hope it lives up to its intent of being the world's happiest nation, or at least successfully striving to be. &amp;nbsp;I may or may not write a blog post about it. &amp;nbsp;For the sake of my honeymoon's happiness, I hope I am not motivated to :) .&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWsH5ubDyGpJzPQt5A7vhpLbfsBsIrEVOhhJlpH8xL9z8vWzFYuntkRQmWxtCyUVh3DMQk9o_5cTSv2YM69qy2swZXvSAzSvp9fj-sl_mmIabWDTXcdXb1U1ySQFHTCVi85_lt8J3HtCCy/s1600/IMG_9223.JPG" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWsH5ubDyGpJzPQt5A7vhpLbfsBsIrEVOhhJlpH8xL9z8vWzFYuntkRQmWxtCyUVh3DMQk9o_5cTSv2YM69qy2swZXvSAzSvp9fj-sl_mmIabWDTXcdXb1U1ySQFHTCVi85_lt8J3HtCCy/s1600/IMG_9223.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</description><author>The Walkabout Blog</author><pubDate>Mon, 02 Jan 2017 11:10:50 GMT</pubDate><guid isPermaLink="true">https://walkabout165.blogspot.com/2017/01/goa-8-years-later.html</guid></item><item><title>Accelerating cryptocurrency Mining with Intel ISPC</title><link>https://da-data.blogspot.com/2016/12/accelerating-cryptocurrency-mining-with.html</link><description>&lt;a href="http://lemire.me/blog/2016/12/30/can-your-c-compiler-vectorize-a-scalar-product/"&gt;Daniel Lemire&lt;/a&gt;&amp;nbsp;and &lt;a href="https://twitter.com/Love2Code"&gt;Maxime Chevalier&lt;/a&gt;&amp;nbsp;just had a &lt;a href="https://twitter.com/love2code/status/811980789659234304"&gt;great exchange on Twitter&lt;/a&gt;&amp;nbsp;about the state of compilers and being able to automatically vectorize code, such as a scalar product. &amp;nbsp;Of course, hoping the compiler can correctly vectorize your code can be a bit fragile, and as Maxime points out, writing raw intrinsics results in an unreadable pain in the editor, and a GPU-style implementation in CUDA or OpenCL might be more scalable and maintainable.&lt;br /&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A few years ago, some folks at Intel wrote a compiler called ISPC, the &lt;a href="https://ispc.github.io/"&gt;Intel SPMD Program Compiler&lt;/a&gt;. &amp;nbsp;A possibly unfairly simple way to describe ISPC is that it's OpenCL-style programming for x86 vector units. &amp;nbsp;You can write code that looks like this:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;export uniform float scalar_product(uniform float a[],&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uniform float b[],&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uniform int count) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; float a_times_b = 0.0;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; foreach (i = 0 ... count) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; a_times_b +&lt;/span&gt;&lt;span&gt;= a[i] * b[i];&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; &amp;nbsp; return reduce_add(a_times_b);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
After compiling this appropriately with ISPC and linking it in, you'd have an appropriately-vectorized implementation of scalar product for the architecture(s) you specified. &amp;nbsp;Pretty neat!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
(If you can't tell, I'm a fan of ISPC, and I don't know for the life of me why it hasn't received more attention.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
At the end of 2013, sick in bed with bronchitis, I got interested in playing around with proof-of-work functions for cryptocurrencies. &amp;nbsp;One was &lt;a href="http://www.hashcash.org/papers/momentum.pdf"&gt;Momentum&lt;/a&gt;, for which I &lt;a href="https://da-data.blogspot.com/2014/01/gaining-momentum-duplicate-detection-in.html"&gt;wrote and released the first publicly-available GPU miner&lt;/a&gt;. &amp;nbsp;As a part of playing with Momentum, I decided to also write an optimized CPU miner. &amp;nbsp;At the time, the fastest available one was from&amp;nbsp;&lt;a href="https://twitter.com/yvg1900"&gt;yvg1900&lt;/a&gt;, a (I believe) Ukraine-based developer who writes some of the most astoundingly optimized code I've seen. &amp;nbsp;The momentum miner was the fastest available, but didn't seem as fast as it could be on Intel Haswell series processors, which support AVX-2 (256 bit integer vector support), so I decided to try to improve upon it. &amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The Momentum proof of work relies upon finding partial collisions in a large (2^26) set of hashes. &amp;nbsp;To improve upon the miner, I used the same fast duplicate detection mechanism I'd devised for the GPU version. &amp;nbsp;After implementing that, it turned out that the vast majority of time was then spent running the SHA-512 hash function, even after linking against Intel's highly tuned version of it. &amp;nbsp;The Intel optimized SHA-512 didn't scale too well to AVX2: &amp;nbsp;Going to SSE-optimization (128 bit vectors) gave it a big speedup, but doubling the vector width to 256 bits didn't come close to doubling the speed.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Fortunately, there was a solution at hand. &amp;nbsp;In most cryptocurrencies, the hash function can be trivially parallelized, as the input is of the form: &amp;nbsp;Hash(block stuff, nonce), where the nonce is usually an integer that's incremented for each turn. &amp;nbsp;So you can compute &lt;i&gt;many&lt;/i&gt;&amp;nbsp;hashes in parallel -- this is one of the reasons GPUs and ASICs work so well for cryptocurrency mining.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I turned to ISPC to write an 8-way parallel SHA-512 implementation. &amp;nbsp;It turns out to have been approximately trivial. &amp;nbsp;I started with some GPU-style unrolled, very-inlined code that implemented SHA-512 on a restricted sized input, and then wrapped that for ISPC:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;



&lt;br /&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;export void sha512_ispc(uniform unsigned int64 data[5],&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span class="s1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uniform unsigned int64 * uniform buf,&lt;/span&gt;&lt;br /&gt;
&lt;span class="s1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uniform int base) {&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;nbsp; for (uniform int i = 0; i &amp;lt; 8; i+= programCount) {&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;nbsp; &amp;nbsp; sha512_block(&amp;amp;buf[i*8], i+programIndex, data, base);&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In this code, the &lt;span&gt;sha512_block&lt;/span&gt; code is &lt;i&gt;not&lt;/i&gt;&amp;nbsp;parallelized -- it just implements a single hash at a time. &amp;nbsp;I've lost some of my original source code for this, but the results were fast:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;



&lt;br /&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="font-family: Courier New, Courier, monospace;"&gt;dga-sha512_ispc: &amp;nbsp; 1.239s&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1" style="font-family: Courier New, Courier, monospace;"&gt;intel-avx2: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2.853&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The output of using ispc like this is probably not as fast as expert-optimized code. &amp;nbsp;I've looked at some of the &lt;a href="https://searchcode.com/file/93512443/src/intel/sha512_avx2.S"&gt;Intel hand-optimized cryptographic functions&lt;/a&gt;, and they're the work of wizards -- they expertly juggle between both the vector units and the scalar units to get maximum throughput out of both. &amp;nbsp;But for the game I was playing a few years ago, I didn't have to -- I just had to write a fast miner sooner than anyone else did. &amp;nbsp;ISPC was a great tool for doing so.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
(For the record and for fairness, of course, I should note that yvg1900 later released a version of their AVX2 Momentum miner that was faster than mine, also using ISPC for some of the code generation, and also that there are many things that make software good -- the yvg1900 miners are robust and well written, and mine was a quick hack.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I've put the &lt;a href="https://github.com/dave-andersen/dga-blog-code/tree/master/cryptocurrency"&gt;source code for the AVX2-optimized ISPC SHA512 code on my Github&lt;/a&gt; -- but be warned, I didn't extract from the original framework the makerules to build the Intel parts of the code.&lt;br /&gt;
&lt;br /&gt;
(Like what you're reading? &amp;nbsp;See &lt;a href="https://da-data.blogspot.com/p/blog-page.html"&gt;more in the Archive&lt;/a&gt;...)&lt;/div&gt;</description><author>Dave's Data</author><pubDate>Mon, 02 Jan 2017 06:11:48 GMT</pubDate><guid isPermaLink="true">https://da-data.blogspot.com/2016/12/accelerating-cryptocurrency-mining-with.html</guid></item><item><title>Introducing Skate or Bike</title><link>https://huphtur.nl/introducing-skate-or-bike/</link><description>&lt;p&gt;Super stoked to officially launch a little side project. It’s called &lt;a href="https://skateorbike.com/"&gt;Skate or Bike&lt;/a&gt; and will feature people who sometimes ride 4, and sometimes ride 2 wheels.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://skateorbike.com/"&gt;&lt;img alt="Skate or Bikes web site displayed on an iPad with an big photo of Sal Barbier skateboarding and a frame in the same room." src="https://huphtur.nl/images/introducing-skateorbike.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://skateorbike.com/miki-vuckovich/"&gt;first interview&lt;/a&gt; on the site is with Miki Vuckovich. I emailed him a huge list of questions and the next day, while on a airplane flight, he answered them all &lt;strong&gt;on his iPhone&lt;/strong&gt; 😳. Thanks again &lt;a href="https://www.instagram.com/mikivuckovich/"&gt;Miki&lt;/a&gt;, you set the bar high for the next set of people to answer my questions.&lt;/p&gt;
&lt;p&gt;A bunch of new interviews are already in the pipeline, so follow Skate or Bike via &lt;a href="https://www.instagram.com/skateorbike/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/skateorbike/"&gt;Twitter&lt;/a&gt;, &lt;a href="https://facebook.com/skateorbikesite/"&gt;Facebook&lt;/a&gt;, &lt;a href="http://skateorbike.tumblr.com/"&gt;Tumblr&lt;/a&gt; or &lt;a href="https://skateorbike.com/feed.xml"&gt;RSS&lt;/a&gt;.&lt;/p&gt;</description><author>huphtur</author><pubDate>Mon, 02 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://huphtur.nl/introducing-skate-or-bike/</guid></item><item><title>Looking back on 2016, and forward to 2017</title><link>https://benovermyer.com/blog/2017/01/looking-back-on-2016-and-forward-to-2017/</link><description>&lt;p&gt;2016 was a rough year. We lost a lot of good people; the loss of Carrie Fisher in particular hit me hard. Politically, the year was disappointing. But 2016 was also a good year for me personally. Doors and eyes opened. 2017 should continue that trend, if I read the signs correctly.&lt;/p&gt;
&lt;h1 id="victories-in-2016"&gt;Victories in 2016&lt;/h1&gt;
&lt;p&gt;I returned to Silver Gryphon Games. While this has not borne fruit yet, it marked a commitment that's important to me. I lost a lot of weight in the early part of 2016. I followed a paleo diet, practiced parkour, and started to see increased energy levels and a better self image. I learned what it meant to be a manager, but not until later in the year. For the first part of the year, I was a “manager” but didn't fully understand the difference between a technical lead and a manager. In November, it finally clicked: managers focus on the big picture. Technical leads bridge the gap between big picture and technical execution. That realization gave me new energy and a powerful sense of purpose.&lt;/p&gt;
&lt;h1 id="challenges-in-2016"&gt;Challenges in 2016&lt;/h1&gt;
&lt;p&gt;One of the biggest stressors for me in 2016 was personal finances. I moved out of my old apartment earlier than I should have. For two months, I was paying for two apartments. I misjudged my cash flow and missed payments on some things for the first time in over five years. Weight and diet were also challenges. While in the first quarter of the year I lost over thirty pounds, the last quarter of the year saw a slight reversal. I gained back ten of those pounds. My diet changed from paleo-ish to unrestricted. My drinking became even more of a problem in the latter half of the year. For the first time in my life, I had a couple days where I couldn't remember large chunks of the previous night. It feels like my memory generally has gotten worse, though I don't have data to support that, or even to suggest that the two are connected.&lt;/p&gt;
&lt;h1 id="goals-for-the-new-year"&gt;Goals for the New Year&lt;/h1&gt;
&lt;p&gt;I'm going to regain my budgetary sense from early 2016 and put significant effort towards paying down debt. This is my primary goal in 2017. I will return to a controlled diet. I'm cutting back on eating out. I love cooking, so this isn't that difficult for me. It's going to require paying attention, though. The big difficulty here is going to be work lunches, since I don't care for sandwiches or microwaved leftovers. Getting my drinking under control is going to be both simple and difficult. In 2016, I drank most often when at home playing video games. Since those two habits are so intertwined, I will need to find a way to sever the connection. In general, I believe I'll be able to succeed at my goals in 2017. I have great hope for the future.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 01 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2017/01/looking-back-on-2016-and-forward-to-2017/</guid></item><item><title>Why I am leaving behind nearly one million followers</title><link>https://macleodsawyer.com/blog/why-i-am-leaving-a-million-followers/</link><description>&lt;p&gt;I wrote this when I was announcing why I was leaving behind most of my digital properties and no longer focusing on growing my social media accounts with a brief history describing my journey.&lt;/p&gt;
&lt;p&gt;You can find the article posted to the International Business Times &lt;a href="https://www.ibtimes.co.in/why-i-am-leaving-behind-nearly-one-million-followers-by-macleod-sawyer-711012"&gt;here&lt;/a&gt; or continue reading below.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The reasons why I wanted to grow in social media are numerous, I haven’t quite figured out the precise reason why I started this journey, but I have a few theories. I may have started using social media to get out of my depression and deprivation of social interactions due to my own introverted-ness and the constant bullying and harassment I received in school. It may have been a need to show the world “who is boss” and who is important through the social currency known as “followers”. It may have been a sense of success when everyone else was telling me to fail, and it may have been a goal created out of spite.&lt;/p&gt;
&lt;p&gt;Whatever it was, I was thirteen. I was a thirteen year old who wanted to rule the world from their keyboard.&lt;/p&gt;
&lt;p&gt;When I was 14, I started producing music, not good music, but it was a hobby I wanted to turn into a career. I was an electronica producer who needed fans. Who wanted to be signed. Who needed marketing.&lt;/p&gt;
&lt;p&gt;I went to Tumblr as my source of marketing. I started a blog called “TheHipsterLifestyle”, it was 2012, and I knew hipsters were big. Within six months I had 25,000 followers.&lt;/p&gt;
&lt;p&gt;My plan was to grow the blog, and then push my absolutely horrendous music to the masses. It worked. A lot of people heard my music, some didn’t have ear drums and really liked it. I eventually got signed to a record label. Once I got signed, I realized I didn’t want to be a producer full time. I wanted to go back to my six year old dreams of being an entrepreneur and turn this into a company either directly, or by using the followers as a way to market a future company. Over the next few years I grew that following to roughly two hundred thousand followers. All organically. Not a single cent was spent.&lt;/p&gt;
&lt;p&gt;When I was 16, I started a company devoted to social analytics and taking in and using our algorithms the different ways that posts created engagements through follows, shares, likes, and more.&lt;/p&gt;
&lt;p&gt;Three months later – the company was acquired. We had nearly a thousand users.&lt;/p&gt;
&lt;p&gt;I kept growing my followings, created dozens of blogs. Most failed. But a good percentage succeeded. Probably around 40%. If I didn’t believe in the blogs or lost interest in the content, I shut them down. That was what caused most of them to fail and I knew it.&lt;/p&gt;
&lt;p&gt;I am 19. I’ve ran more than a few companies in that time, I even dropped out of high school in my 11th year after my company was acquired to focus full time on it. Over the last five years of growing my social media following across Tumblr, Facebook, Twitter, and Instagram I have amassed somewhere around 875,000 followers.&lt;/p&gt;
&lt;p&gt;I am leaving that all behind – at least momentarily.&lt;/p&gt;
&lt;p&gt;I know how to market, and I know how to sell. Over the last two years I have grown tired of social viral focused marketing. I have grown tired of the effort. That’s why this past year I switched full force into politics and education on my blogs. I had great success, lots of growth, and earlier this year I even had my work archived in the Library of Congress for “being a influence on society and politics for future research” or something like that. None of my success would ever have happened if it wasn’t due to 13 year old me wanting to rule the world from my keyboard.&lt;/p&gt;
&lt;p&gt;I am eternally grateful to younger me, that guy knew what was up (he really didn’t, but he thought he did – and I will be proud to say the same in the future about current me as well).&lt;/p&gt;
&lt;p&gt;But I am tired.&lt;/p&gt;
&lt;p&gt;I am tired of constantly seeing so much useless information fill my screen, it hurts. I noticed that the more I use Social Media like Tumblr I get more depressed. Now there is a counter argument that I use Social Media more when I am depressed, but I know it’s linked to social media. Don’t argue with me on this.&lt;/p&gt;
&lt;p&gt;I am launching a new company, a new initiative, something absolutely life changing in the next few months. This project no longer relies on social media, and it requires nearly all of my attention.&lt;/p&gt;
&lt;p&gt;I am leaving nearly all social media so that I can focus. I find myself in my boredom typing “fac” or “tu” into the address bar or mindlessly clicking on the app icons and scrolling before I catch myself.This needs to stop. I deleted my Tumblr app and I severely limited my twitter following list. Want to know what I noticed? My motivation is back, I am reading 1–2 books a week again, and I am happier.&lt;/p&gt;
&lt;p&gt;I want to make this a full-time thing. I want to be happier full-time and I want to be reading and working full-time. I want to be happy.&lt;/p&gt;
&lt;p&gt;The only thing standing in my way is social media, the only thing standing in my way is the constant numbers game that runs through my head. Every day I see my social currency of “followers” go up and down, it’s anxiety inducing and I hate it.&lt;/p&gt;
&lt;p&gt;There is so much potential in these followers and I realize that — but it’s not anything I personally want to get into. I am tired of marketing, I am tired of advertising, and I am tired of continually coming up with content that I really don’t care about. Even the content I do care about (like on my main property), do I really care? Do I really care about the memes? Do I really care about pop culture?&lt;/p&gt;
&lt;p&gt;Not really, and it actually hurts anytime I read through it or share it. I don’t know why I’ve kept it going — again it’s probably the numbers game.&lt;/p&gt;
&lt;p&gt;I stopped caring about followers a long time ago, but it still hurts when I see the numbers drop even by one. If my activity is even on par with the day before than I think I am a failure. If my selfie doesn’t get 200 notes (likes &amp;amp; comments) then I feel bad, and that’s just wrong. This isn’t what is suppose to happen. I shouldn’t let social currency dictate how I feel or my moods. Only I should dictate my feelings and moods. I don’t need anyone else’s permission or approval.&lt;/p&gt;
&lt;p&gt;I just don’t care for social media anymore. I have a lot of followers, nearly a million, and I have a deep “fan” network of people who honestly look up to me. I understand that, and I am eternally grateful for them. I know that one of the only real reasons I have kept blogging is for them. For years, its been about them. I care about them a lot, they have helped me so much, and I know that I have been a huge help to them.&lt;/p&gt;
&lt;p&gt;This decision wasn’t easy, and it’s been something I have been contemplating for two years. I’ve wanted to get away from social media for so long, and have only stayed for the fans — or friends — that I have created along the way. I honestly do love them, but it’s time for me to be me and be happy.&lt;/p&gt;
&lt;p&gt;I require the happiness of focusing and working on my own projects to keep me afloat. Life goes on whether I am online or not. I really do feel bad, I was a mentor to a lot of people, I feel like a failure to them.&lt;/p&gt;
&lt;p&gt;This is a needed evil so that I can move on and live the life that I honestly want to live. A lot of people disagree (my parents included) with this choice. I want to refocus on what I care about, I want to have the time to create this company and try to make the world a better place (cliché I know — but its honest).&lt;/p&gt;
&lt;p&gt;I’m moving into the hardware industry that requires no social marketing in the way that I have created. My followers are spread out all over the world, and very few are from the area that I am in. My followers are 98% millennials between 13 and 22. They are nowhere close to the demographic for my company.&lt;/p&gt;
&lt;p&gt;I want to see this company be a success even if it’s just on a minor scale, and that requires doing everything I can to only do things that will help my direct future with this company. This wasn’t an easy decision in any way. But it’s time for me to move on with my life, leave the work that I owe my entire career and life to, and become better. I owe everything to my awesome followers and the social networks that have made me who I am. I love you guys, you guys mean the world to me.&lt;/p&gt;
&lt;p&gt;But, for now — this is goodbye to my “social empire”. I am just going to post my internal thoughts to Twitter and Medium, and leave behind the behemoth of social currency and tumblr. I don’t know where this will take me, but I know it’s for the best. I will re-evaluate my choice in the next few months. For now, I am putting the accounts on hold.&lt;/p&gt;
&lt;p&gt;Thanks for all the fish.&lt;/p&gt;</description><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Sun, 01 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/blog/why-i-am-leaving-a-million-followers/</guid></item><item><title>2017 Predictions</title><link>https://justingarrison.com/blog/2017-01-01-2017-predictions/</link><description>After 9 years of predictions I've been wrong with my predictions more often than I've been right.</description><author>Justin Garrison's Homepage</author><pubDate>Sun, 01 Jan 2017 02:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2017-01-01-2017-predictions/</guid></item></channel></rss>