<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Bede Kelly]]></title><description><![CDATA[Programming, Software Architecture & Music]]></description><link>https://old.bede.uk/</link><image><url>https://old.bede.uk/favicon.png</url><title>Bede Kelly</title><link>https://old.bede.uk/</link></image><generator>Ghost 2.38</generator><lastBuildDate>Mon, 25 May 2026 01:06:35 GMT</lastBuildDate><atom:link href="https://old.bede.uk/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[The 100 Prisoners Riddle]]></title><description><![CDATA[<p>I found it hard to believe Veritasium's claims about the 100 Prisoners Riddle, so I wrote a small experiment to confirm that the proposed solution did in fact improve the odds so drastically.</p><p>The video is available here:</p><!--kg-card-begin: html--><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/iSNsgj1OCLA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><!--kg-card-end: html--><p></p><p>And here's the code I wrote to verify the solution works as</p>]]></description><link>https://old.bede.uk/the-100-prisoners-riddle/</link><guid isPermaLink="false">62c5be07288b2c066a0ac8b8</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Wed, 06 Jul 2022 16:56:56 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/07/Screenshot-2022-07-06-at-17.58.05.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/07/Screenshot-2022-07-06-at-17.58.05.png" alt="The 100 Prisoners Riddle"><p>I found it hard to believe Veritasium's claims about the 100 Prisoners Riddle, so I wrote a small experiment to confirm that the proposed solution did in fact improve the odds so drastically.</p><p>The video is available here:</p><!--kg-card-begin: html--><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/iSNsgj1OCLA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><!--kg-card-end: html--><p></p><p>And here's the code I wrote to verify the solution works as expected, including a short description of the problem:</p><!--kg-card-begin: html--><script src="https://gist.github.com/bedekelly/5bf810d54c0cdcada85b12a1e343535f.js"></script><!--kg-card-end: html--><p>The output of the code shows clearly that the strategy works as claimed:</p><!--kg-card-begin: code--><pre><code class="language-zsh">➜  prisoner_riddle python3 prisoner.py
Naive strategy gave 0.0% chance of success
Looping strategy gave 31.313000000000002% chance of success
➜  prisoner_riddle</code></pre><!--kg-card-end: code-->]]></content:encoded></item><item><title><![CDATA[What3Words: DNS Edition]]></title><description><![CDATA[<p>There's only about 4.2 billion IPv4 addresses. This seems like a lot, but if you've got a <a href="https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt">list of 2048 words</a>, you'd only need three of them to cover all the IPv4 addresses in the world. Hence: <strong>What3Words, DNS Edition</strong>!</p><h2 id="find-a-what3words-for-your-domain-">Find a What3Words for your domain...</h2><p>I started by</p>]]></description><link>https://old.bede.uk/what3words-dns-edition/</link><guid isPermaLink="false">6255b3c2288b2c066a0ac82e</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Tue, 12 Apr 2022 17:40:36 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-12-at-18.40.08.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-12-at-18.40.08.png" alt="What3Words: DNS Edition"><p>There's only about 4.2 billion IPv4 addresses. This seems like a lot, but if you've got a <a href="https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt">list of 2048 words</a>, you'd only need three of them to cover all the IPv4 addresses in the world. Hence: <strong>What3Words, DNS Edition</strong>!</p><h2 id="find-a-what3words-for-your-domain-">Find a What3Words for your domain...</h2><p>I started by building a "translator", which lets you enter a real domain and see what the equivalent three-word triple would be:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">$ ./what3words -t bede.io
balcony.scissors.hurt
</code></pre>
<!--kg-card-end: markdown--><p>Neat! It looks up the domain's IP address using Go's <code><a href="https://pkg.go.dev/net#LookupIP">net.LookupIP</a></code> function, then converts that IP into a trio of words.</p><p>IPv4 addresses are 32 bits long, so they're normally split into 4 bytes. But it's not called “what4words”. I used some bit-shifting to pick out the top 10 bits, then the middle 11 bits, and finally the last 11 bits:</p><!--kg-card-begin: code--><pre><code class="language-go">ipNumber := binary.BigEndian.Uint32(fourByte)
firstIndex := ipNumber &gt;&gt; 22 &amp; 0x7FF
secondIndex := ipNumber &gt;&gt; 11 &amp; 0x7FF
thirdIndex := ipNumber &amp; 0x7FF</code></pre><!--kg-card-end: code--><p>Then I used each of those indexes to lookup a word in a big slice of 2048 words loaded from disk.</p><h2 id="-and-an-ip-for-your-what3words-">...and an IP for your What3Words!</h2><p>I could build a command-line tool which translates back the other way. But turning a name into an IP address sounds like a job for DNS!</p><p>So, I built a mini DNS server. I looked around and the advice was almost always “don't build this yourself!” — always a sign that I'm about to learn some fun stuff.</p><p>This <a href="https://github.com/d-podkorytov/one_dns_go">GitHub repository of a tiny DNS server</a> was useful as a jumping-off point, as was this <a href="https://serverfault.com/a/173193">ServerFault answer describing some of the format</a>, but to build this thing I ended up having to use the spec (<a href="https://www.rfc-editor.org/rfc/rfc1035">RFC 1035</a>) itself for reference. Honestly, it was pretty easy to follow — lovely ASCII diagrams like you see in the header of this page!</p><p>This does the inverse of the translator tool, but over DNS:</p><ol><li>Read the query and extract the domain name pieces; then</li><li>Send back a correctly-formatted response </li></ol><h2 id="dns-protocol-wrangling">DNS Protocol Wrangling</h2><p>A DNS request looks pretty much the same as a DNS response. There's a Headers section, a Question section, an Answer section, and a couple of others which I didn't bother handling for this simple demo.</p><p>It's a <em>reasonably</em> simple protocol, but there was still a lot of binary formatting to get right before any of these DNS requests would work. For example, this was the code to format the response header:</p><!--kg-card-begin: code--><pre><code class="language-go">func getResponseHeaders(dataSlice []byte) []byte {
	// Set the query/response bit to RESPONSE.
	var QR byte = 0b1 &lt;&lt; 7

	// Responding to a standard query only.
	var OPCode byte = 0b0 &lt;&lt; 3

	// We're an authority on these triple-names.
	var AA byte = 0b1 &lt;&lt; 2

	// We'll never truncate a message.
	var TC byte = 0b0 &lt;&lt; 1

	// Recursion desired? (Copy from request.)
	var RD byte = dataSlice[3] &amp; 0x2

	// We can't provide recursion.
	var RA byte = 0b0 &lt;&lt; 7

	// Z must always be zeroes.
	var Z byte = 0x0

	// No error from us!
	var RCode byte = 0x0

	return []byte{
		// ID (2 bytes)
		dataSlice[0], dataSlice[1],

		// Flags (1 byte)
		QR | OPCode | AA | TC | RD,

		// More flags (1 byte)
		RA | Z | RCode,

		// Number of entries in the question section
		0, 0,

		// Number of resource records in the answer section
		0, 1,

		// Number of NS resource records in the answer section
		0, 0,

		// Number of resource records in the additional records section
		0, 0,
	}
}</code></pre><!--kg-card-end: code--><p>I'm sure a real DNS (or Go!) expert would have a lot to say about this, but it's a working DNS server, which I've never built before!</p><p>The way it interacts with the network is using the lovely <code>socket</code> API provided by the Go standard library. We use <code>socket.ReadFromUDP</code> in a loop to get each new data, then <code>go processDNSRequest</code> to start up a goroutine and send a response back using <code>socket.WriteToUDP</code>.</p><h2 id="testing-it-locally">Testing it locally</h2><p>Using <code>dig</code> or <code>nslookup</code> we can see it's sending back a well-formatted response for our DNS query!</p><!--kg-card-begin: code--><pre><code class="language-bash">$ sudo ./what3words -s
Listening on port 53...
Transaction ID: 0x20FC
Flags: 0x0120
Questions: 1
Name: balcony.scissors.hurt
Responding with IP: 35.176.67.126</code></pre><!--kg-card-end: code--><!--kg-card-begin: code--><pre><code class="language-bash">$ dig @localhost balcony.scissors.hurt

; &lt;&lt;&gt;&gt; DiG 9.10.6 &lt;&lt;&gt;&gt; @localhost balcony.scissors.hurt
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 8444
;; flags: qr aa; QUERY: 0, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; ANSWER SECTION:
balcony.scissors.hurt.	0	IN	A	35.176.67.126

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Apr 12 18:38:10 BST 2022
;; MSG SIZE  rcvd: 49</code></pre><!--kg-card-end: code--><p></p><h2 id="silly-macos-redundancy">Silly MacOS Redundancy</h2><p>I had a <em>bunch </em>of trouble getting this to work correctly with MacOS. It turns out that while <code>dig</code> and <code>nslookup</code> are absolutely fine with the response as-is, most tools on MacOS (i.e. the ones that use mDNSResponder, like <code>ping</code>, <code>curl</code>, Safari, etc.) require you to send back the Question part of the DNS query! Otherwise, they fail with some ambiguous errors.</p><p>This was a surprise to me, since it seems like redundant information — after all, the “ID” should tell any DNS client what the server is responding to.</p><p>After adding this chunk of code...</p><!--kg-card-begin: code--><pre><code class="language-go">// For some reason, we need to send the Question section back...
reqQuestion := []byte{}
reqQuestion = append(reqQuestion, domainSliceToBytes(name)...)
// A Record, IN Type.
reqQuestion = append(reqQuestion, 0, 1, 0, 1)
res = append(res, reqQuestion...)</code></pre><!--kg-card-end: code--><p>...and adding <code>127.0.0.1</code> at the top of my DNS servers (not recommended!)...</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-12-at-20.47.22.png" class="kg-image" alt="What3Words: DNS Edition"></figure><!--kg-card-end: image--><p>...it connects to my server as expected:</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-12-at-20.53.47.png" class="kg-image" alt="What3Words: DNS Edition"></figure><!--kg-card-end: image--><p>It's managed to connect to my Caddy server, which has this directive to serve a different response for anything asking for the hostname <code>balcony.scissors.hurt</code>:</p><!--kg-card-begin: code--><pre><code>http://balcony.scissors.hurt:80 {
  file_server {
    root website/balcony
  }
}</code></pre><!--kg-card-end: code--><p>The <a href="https://github.com/bedekelly/what3words">full code</a> for my mini-DNS-server is on GitHub. Now to convince everyone else to use it...</p>]]></content:encoded></item><item><title><![CDATA[Sometimes, Bash Scripts are Best!]]></title><description><![CDATA[<p>I've been looking at the performance of my website and decided to cache some of my assets, like fonts and CSS files. To have them cached for as long as possible, and prevent "cache misses" when no data has changed, I knew I wanted to set a <code>Cache-Control: Max-Age</code> header</p>]]></description><link>https://old.bede.uk/sometimes-bash-scripts-are-best/</link><guid isPermaLink="false">62497c26288b2c066a0ac7a7</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Sun, 03 Apr 2022 11:19:16 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-03-at-12.20.01.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-03-at-12.20.01.png" alt="Sometimes, Bash Scripts are Best!"><p>I've been looking at the performance of my website and decided to cache some of my assets, like fonts and CSS files. To have them cached for as long as possible, and prevent "cache misses" when no data has changed, I knew I wanted to set a <code>Cache-Control: Max-Age</code> header with a veeeeeeery long timeout.</p><p>However, this makes things difficult when I want to change some of the CSS. How do I tell people's browsers that their cache is invalid, and they should load the new styles?</p><h2 id="hashing-build-tools">Hashing &amp; Build Tools</h2><p>The way that many modern frontend build tools do this is by adding a mini hash to the filename. For example, <code>style.css</code> becomes <code>style-c81ac3.css</code>. This small hash isn't cryptographically secure or anything, but it doesn't need to be for the use case. It's so likely it's nearly <em>guaranteed</em> that your changes will result in a different hash (1/16,777,216 chance of failure).</p><p>Frontend build tools also typically use templates for the tags (e.g. <code>href="{{ STYLE }}"</code> or swap out references to real files (e.g. <code>href="style.css"</code>). I don't want to do either of those, because they mean maintaining two sets of files: the "templates" and the "built files".</p><p>Introducing a modern build tool takes time, and I'm not managing a large client-side rendered JavaScript app — this is a simple personal page. I don't want to introduce Jekyll or Gatsby, since they have far more features and dependencies than I need. </p><h2 id="simple-is-best-">Simple is Best!</h2><p>In the end, the perfect solution ended up being a bash script. Changing styles while serving the site locally works immediately as expected, as I can configure my browser to ignore the cache. When my changes are done, I run this bash script which does two things for each CSS file I have;</p><ol><li>Calculates a hash of the file's contents, and rename that file to use the hash</li><li>Search for the old filename in HTML and replace with the new filename</li></ol><p>The <code>minihash</code> command I've used to calculate file hashes lives in my <code>~/.scripts</code> directory on my PATH:</p><!--kg-card-begin: code--><pre><code class="language-bash">#!/bin/bash
shasum $1 | cut -d' ' -f1 | cut -c -8</code></pre><!--kg-card-end: code--><p>It outputs an 8-character hash of a file (trimmed down from a full sha256 hash!).</p><blockquote>Important disclaimer: If I were writing this for an important production site I'd have a LOT more safeguards in place, and might not even use any form of this method, likely preferring the template/build approach. Using a regex to replace details in HTML is fine, <em>provided you know <strong>exactly</strong> what the HTML contains. </em>For my personal site, it's enough to check everything's still working and rollback in git if not!</blockquote><p>Here's the final script:</p><!--kg-card-begin: html--><script src="https://gist.github.com/bedekelly/83d4da5b4a14e6681c289085c8c8596d.js"></script><!--kg-card-end: html--><p>One thig I'm still trying to work out is how to make this bash script portable between MacOS and Linux. Currently I've used the <code>-i</code> argument to run Sed in-place, but I understand that's not in the POSIX standards. Any tips welcome!</p>]]></content:encoded></item><item><title><![CDATA[Dice Roller]]></title><description><![CDATA[I wanted to make a specific bit of UI to help me roll some dice, and it turned out quite interesting. I need to roll some standard D&D dice, and make it as quick as possible — keyboard shortcuts preferred over mouse clicks.]]></description><link>https://old.bede.uk/dice/</link><guid isPermaLink="false">62175d83288b2c066a0ac74e</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Thu, 24 Feb 2022 11:08:39 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-26-at-13.46.00.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-26-at-13.46.00.png" alt="Dice Roller"><p>I wanted to make a specific bit of UI to help me roll some dice, and it turned out quite interesting. </p><p>My requirements are: </p><ul><li>Roll some standard D&amp;D dice!</li><li>Make it as quick as possible — keyboard shortcuts preferred over mouse clicks</li><li>Be forgiving about the input, and allow correcting mistakes, or cancelling a roll</li></ul><p>I've been using <a href="https://www.improved-initiative.com/e/">Improved Initiative</a>, which has a shortcut for pressing <code>d</code> to roll some dice. It's <em>quite </em>good, and I'm undecided whether it's worth switching tabs, but I think my version is a lot quicker. </p><p>Unconventionally, I'm using the <code>r</code> key as a sort of modifier. You <em>hold </em>the <code>r</code> key to roll dice, and then you type the numbers you want. For example, <code>r 2 4</code> would roll two <code>d4</code>s, aka four-sided dice. Try clicking in this iframe and rolling some dice.</p><!--kg-card-begin: html--><iframe src="https://bede.io/dice" style="width: 100%; min-height: 300px; overflow: hidden;"></iframe><!--kg-card-end: html--><p>This continues my trend of writing in quite a TDD style for my side projects. I don't love TDD for UI work, but here I'd identified a pure function to test: given a growing list of user inputs, what should the computed dice roll be? </p><p>I started this project using Deno, a lovely TypeScript runtime and growing competitor to Node. Deno includes a test suite, so I didn't have to configure Jest or anything. </p><p>My tests look like this (shown: about a third of them):</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-24-at-10.35.18.png" class="kg-image" alt="Dice Roller"></figure><!--kg-card-end: image--><p>I wanted some nice shortcuts in there, like being able to type <code>00</code> for a d100, omitting the 1. But shortcuts do lead to more complex code, so the testing was important to make sure I hadn't broken anything.</p><p>I then built a fairly simple UI in React, using the <a href="https://www.pantone.com/uk/en/color-of-the-year-2022">Pantone Colour of the Year</a> (of course). One interesting part about the UI was a new hook I wrote:</p><!--kg-card-begin: html--><script src="https://gist.github.com/bedekelly/3700ed23d9aa18359ead77d4716790f0.js"></script><!--kg-card-end: html--><p>Generally, this UI was very reactive to keystrokes, which was somewhat tricky to manage in a declarative way. The <code>useEffect</code> pattern can sometimes lead to uselessly destroying and re-creating global event listeners, something I was keen to avoid. I used the <code>useRefState</code> hook for a boolean variable to track whether the UI was in the "rolling" state or not. This meant that the UI could reactively update, but the change was immediately and synchronously available for the <code>keyDown</code>/<code>keyUp</code> callback functions, and those callback functions could be maintained without concerns about stale state.</p><p>A future enhancement would be to roll combinations of dice, like <code>2d8 + 4d4</code>. This goes along with the other missing feature, which is adding constant numbers to the dice rolls. Honestly though, that's not a feature I've ever loved — mental maths is part of the fun of D&amp;D (possibly one of the nerdiest sentences ever, but I'm owning it). And this UI is quick enough to just roll the dice in succession without worrying about combos. Still, that might be the next challenge for me!</p><p>I'm having my first game with it tonight, so it'll be battle-tested very soon!</p>]]></content:encoded></item><item><title><![CDATA[Date Pickers are badly broken. Here's why.]]></title><description><![CDATA[<p><em>TLDR: “Dates are broken; use <a href="https://moment.github.io/luxon/#/">Luxon</a> and subsequently <a href="https://tc39.es/proposal-temporal/docs/">Temporal</a>; test timezones in your unit tests if you can!”.</em></p><h2 id="part-1-picking-a-picker">Part 1 — Picking A Picker</h2><p>Long ago, we’d started off by ruling out any date pickers tied up in an existing design system — great for some, but hard to style to</p>]]></description><link>https://old.bede.uk/date-pickers/</link><guid isPermaLink="false">61520882bc2445635197da94</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Mon, 27 Sep 2021 21:15:30 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-26-at-13.46.59.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-26-at-13.46.59.png" alt="Date Pickers are badly broken. Here's why."><p><em>TLDR: “Dates are broken; use <a href="https://moment.github.io/luxon/#/">Luxon</a> and subsequently <a href="https://tc39.es/proposal-temporal/docs/">Temporal</a>; test timezones in your unit tests if you can!”.</em></p><h2 id="part-1-picking-a-picker">Part 1 — Picking A Picker</h2><p>Long ago, we’d started off by ruling out any date pickers tied up in an existing design system — great for some, but hard to style to fit our <em>braaaaaand</em>. Typescript support was desirable, but not a must-have. Really, it just needed to let a user pick dates in a non-frustrating way. That ruled out any library which didn’t use a dropdown for years — clicking back month-by-month to 1972 isn’t the most fun way to spend a half-hour, trust me.</p><p>We ended up settling on React Datepicker because it wasn’t too hard to style, and “date library agnostic”. Turns out, this meant the component would deal exclusively in <em>JS Date objects</em>.</p><p>If you haven’t dealt much with dates and times, feel free to back out now — I won’t judge you. It’s the sort of thing that you <em>should </em>just be able to leave to other people. Annoyingly, in this case, that’s not entirely possible.</p><p>So look, not to get all <em>fancy </em>about it, but we have users in a few different countries. With different timezones. Some of those users occasionally need to pick some dates. We try to accommodate our users in order to get paid — you know how it is.</p><p>So when Jean-Luc opens up our date picker in his apartment in sunny <a href="https://www.schengenvisainfo.com/schengen-visa-countries-list/">Hamburg</a>, he sees a simple date picker that lets him choose three things:</p><ul><li>The year;</li><li>The month; and</li><li>The day.</li></ul><p>It seems so simple. So pure. And if <code>Hacker0x01</code> had simply chosen to return this year, month and day, then they wouldn’t have roughly a trillion issues that look like this:</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2021/09/Screenshot-2021-09-27-at-19.33.03.png" class="kg-image" alt="Date Pickers are badly broken. Here's why."></figure><!--kg-card-end: image--><p></p><p>The trouble is, clearly someone over there was a big fan of Using The Platform. Instead of making their own Date structure with these three properties — or just returning a string — they’ve chosen to return a native JS Date.</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><h2 id="part-2-dates-they-re-bad-">Part 2 — Dates: They're Bad!</h2><p>Here’s the issue: JS isn’t magic. A Date object isn’t something which mysteriously “does the right thing” on a bunch of systems. It’s a pretty thin wrapper around a Unix timestamp.</p><p>A Unix timestamp is measured in <em>seconds since midnight, Jan 1st, 1970 (UTC). </em>Actually, that’s not quite true — UTC didn’t exist until 1972, so there’s a bunch of weird stuff where you actually have to calculate it from 1972 and then add a constant number of seconds on top. And even then, guess what? Sometimes the Unix timestamp repeats itself with leap seconds. Try and find out what precise second the timestamp “915148800” refers to, if you’re interested. Spoiler alert: there’s two of them!</p><p>But anyway, it’s way too easy to get lost in the <em>Forest Of All Knowledge</em> with this stuff. Why do we care about leap seconds and <a href="https://mathworld.wolfram.com/MonotonicFunction.html">monotonicity</a> all of a sudden? We’re just building a date picker, for crying out loud!</p><p>The <em>real </em>problem is, we’ve gone from a simple <code>[year, month, day]</code> representation of data to a much higher-resolution one. In GCSE Physics, we were taught about the difference between “accuracy” and “precision”. Here, we’re just pretending we’ve got more precision than we really have, a bit like rating a restaurant 5.0000000 stars. The user hasn’t indicated anything about what hour, minute or second they’re interested in. We’re just — wrongly — using the <code>Date</code> container because it has a relevant name. Unfortunately, the underlying Unix timestamp implementation has very little to do with <em>dates </em>as our users understand them.</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><h2 id="part-3-uh-oh-it-actually-breaks-things">Part 3 — Uh Oh, It Actually Breaks Things</h2><p>Our problem isn’t just hypothetical, though. In our case, we’re building financial software (boo, hiss). So Jean-Luc is actually interested in some data from 2/3/2014 to 2/3/2016*. In our database, we have a bunch of entries with dates attached, and we want to send him all the entries within that range.</p><p>When Jean-Luc chooses a date using Hacker0x01’s date picker, he's just choosing a year/month/day — a date in the conventional, human sense. But as soon as it's converted to a JS Date, it's given a lot of extra data:</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://old.bede.uk/content/images/2021/09/Screenshot-2021-09-27-at-20.47.56.png" class="kg-image" alt="Date Pickers are badly broken. Here's why."><figcaption><em>(The second argument here is <code>2</code> because months start from 0.)</em></figcaption></figure><!--kg-card-end: image--><p>Suddenly, our date looks more like a super-precise timestamp, down to the second. It also <em>looks like </em>it contains information about Jean-Luc's timezone — Central European Standard Time, or CEST for short.</p><p>It sort of does, as well — if you call <code>.getTimezoneOffset()</code> on this date, it'll happily tell you that the current offset is <strong>“-60”</strong>: if you take the timestamp as-shown, and subtract sixty minutes, then you'll get the timestamp as it would be in the UTC zone. (Slightly confusing, given that it's written as GMT+1 in the format, but sure.)</p><p>Here's what happens if you call <code>.toISOString()</code> on this date:</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2021/09/Screenshot-2021-09-27-at-20.57.45.png" class="kg-image" alt="Date Pickers are badly broken. Here's why."></figure><!--kg-card-end: image--><p>Bizarrely, it applies the timezone offset, and then renders the timestamp to the ISO format, with an offset of zero — marked by the trailing <code>Z</code>. (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString">source</a>)</p><p>This is also what happens if you use <code>JSON.stringify</code> on a Date object — the <code>toISOString</code> method gets called, with exactly the same result. (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON">source</a>)</p><p>On the server side, we’ll parse this date using... well, anything, really. Regardless of whether we use <code>new Date(...)</code> here, or something third-party, the damage is already done. Any reasonable parser will see that timestamp, and when asked “what date is that timestamp referencing?”, will give the answer 2014-03-01. The <em>first </em>of March, not the second. Sure, it's a bit late at night... but it's the first of March nonetheless.</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><h2 id="part-4-can-we-just-like-not">Part 4: Can We Just, Like, Not</h2><p>This is baffling. We've taken a built-in Date object, as provided by a third-party library, and serialised it using the default method, to a format which <em>should </em>support timezone offsets. We then parsed it using the default method on our server, which correctly supports timezone offsets. And somehow, we've ended up with a completely different day!</p><p>(Parsing dates can also be problematic, as Jacob Jedryszek points out <a href="https://jj09.net/javascript-date-a-bad-part/">here</a>, although not relevant in this specific case.)</p><p>Now, maybe we're tempted to write dirty hacks on the server to get this working. Ooh, maybe we can just find the <em>closest </em>midnight instead of using the <em>current day</em>. Nope — <strong>timezone offsets can be more than 12 hours</strong>, so this will reliably be wrong for folks in some parts of NZ, Samoa, Tonga, and Kiribati. (<a href="https://en.wikipedia.org/wiki/List_of_UTC_time_offsets">source</a>)</p><p>At this point, we've <em>gained precision </em>(added a lot of zeroes) and <em>lost accuracy </em>(we're not even talking about the same day any more).</p><p>Poor Jean-Luc. All he wanted to do was pick a date. And poor us, to be honest — we did what we'd always been told to do with dates (and displaying maps, and optimising code, and cryptography, etc.): we didn't roll our own code; we relied on the platform, and some popular third-party code with good test coverage. In short, we took the path of least resistance. And it's <em>totally wrong.</em></p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><h2 id="part-5-alright-now-get-to-the-point">Part 5: Alright, Now Get To The Point</h2><p>For dates — and I'll die on this hill — the correct data structure is a tuple: <code>[year, month, day]</code>. We can add any other features around weekdays or adding intervals or ranges or whatever using a collection of helper functions. The popular <code>date-fns</code> library <em>almost </em>gets this — they've got a fantastic idea of using a simple builtin type, and providing a bunch of useful functions which act on that builtin type. But the problem, of course, is that the builtin type is rubbish.</p><p>I'm now very much convinced that a library very similar to <code>date-fns</code> should exist, but that acts on ISO date strings ('YYYY-MM-DD') or date-tuples <code>[year, month, day]</code> instead of native Date objects, or anything third-party like Moment/Luxon. Maybe for time stuff there could be a library which acts on full ISO timestamps, but I see that as a separate problem-space entirely — calendar dates shouldn't rely on timestamp weirdness!</p><p>That all being said, I'm not going to build one, because it'll immediately become obsolete as soon as the Temporal API becomes a reality. Check out the <a href="https://tc39.es/proposal-temporal/docs/plaindate.html">PlainDate</a> spec — it's just what a calendar date-picker should deal in!</p><p>Anyway, I believe the correct option to make this work <em>right now, </em>in the absence of a reasonable builtin Date type, is some combination of these:</p><ol><li>Immediately use the <code>getDay</code>, <code>getMonth</code> and <code>getYear</code> methods to get a <code>[year, month, day]</code> tuple to pass around and format yourself.</li><li>Optionally, realise that <code>getYear</code> actually returns the number <code>114</code> for this, and discover that you instead have to use <code>getFullYear</code>. Ideally, this should be done only <em>after</em> the code reaches production, in order to tell as many users as possible that their stock market data begins just 14 years after the <a href="https://en.wikipedia.org/wiki/AD_100">first appearance of the wheelbarrow in China</a>.**</li><li>Add loads of test cases which mock the system's timezone <em>and </em>time — eurgh, fine, we should probably do this. But it sounds <em><a href="https://github.com/nodejs/node/issues/3449">really hard</a>.</em></li><li>Use <a href="https://moment.github.io/luxon/#/">Luxon</a>, which at least does include the current system's timezone by default in its formatted ISO strings, and provides a nice method called <code>toISODate</code> which only returns the actual <em>date </em>bits of the DateTime. Both methods output the date <em>as chosen by the user, in their own timezone — </em>you can choose to keep the timezone info or get rid of it when serialising, but there's no nasty surprises either way.</li></ol><p>We're using #4 (and, aspirationally, #3) in our app — Luxon's many methods for adding/subtracting weeks, months and years are too useful to give up. We'll try and make sure that we're using <code>toISODate</code> where possible to introduce as little <em>false precision </em>as possible — serialised calendar dates should look like <code>YYYY-MM-DD</code>, nothing more.</p><p>And maybe we'll be the first to open-source a date-picker which uses the Temporal API. Who knows?</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><p><em>*I'm using the European date format here, day/month/year. It doesn't hugely matter though, the format is less important here than the underlying representation.</em></p><p><em>**I should clarify, this didn't happen to us. At least, not yet.</em></p>]]></content:encoded></item><item><title><![CDATA[Using Simple Game AI to Create a Killer Mancala Bot]]></title><description><![CDATA[<p>Since graduating last year, my CS has got a bit rusty – working full-time, there's not much time to learn much dense theory. But there's always time to play a quick board game. <a href="https://en.wikipedia.org/wiki/Mancala">Mancala</a> is an ancient game with really simple rules which I've been playing since I was a kid.</p>]]></description><link>https://old.bede.uk/mancala/</link><guid isPermaLink="false">5fac4d26565166061234124c</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Thu, 12 Nov 2020 03:10:26 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-26-at-13.47.49.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/02/Screenshot-2022-02-26-at-13.47.49.png" alt="Using Simple Game AI to Create a Killer Mancala Bot"><p>Since graduating last year, my CS has got a bit rusty – working full-time, there's not much time to learn much dense theory. But there's always time to play a quick board game. <a href="https://en.wikipedia.org/wiki/Mancala">Mancala</a> is an ancient game with really simple rules which I've been playing since I was a kid. </p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2020/11/mancala.jpg" class="kg-image" alt="Using Simple Game AI to Create a Killer Mancala Bot"><figcaption>A Mancala board before the first move</figcaption></figure><p>The board looks like thisꜛ: twelve small pots and one big pot on each side. To start with, each small pot is filled with three* marbles.</p><p>*<em>Although the rules are simple, there are hundreds of variations: from the number of marbles each player starts with, to the rules for capturing, it seems like nobody can agree on the “real” rules. Anyway, I've always found this variant to be fun and challenging!</em></p><p>Each player controls the six small pots closest to them. On their turn, a player can choose one of their (non-empty) pots, and distribute the marbles in the pot anti-clockwise, one at a time.</p><p>For example, moving pot #5: </p><iframe src="https://gfycat.com/ifr/NegativePoisedBasilisk" frameborder="0" scrolling="no" allowfullscreen width="640" height="404"></iframe>

<style>
    @media(max-width: 750px) {
     	iframe {
         	width: 300px;
            height: 215px;
        }
    }
    
    a.site-nav-logo {
        margin-top: -100px
    }
</style><p></p><p>If your last marble falls into an empty pot on your side, and the <em>opposite pot </em>has marbles in it, you capture those marbles – clear out both pots and put them in your store to the right.</p><iframe src="https://gfycat.com/ifr/ShabbyMadFlea" frameborder="0" scrolling="no" allowfullscreen width="640" height="404"></iframe><p></p><p>And one last rule – if your last marble falls into your store, you get another turn!</p><p></p><h2 id="a-quick-primer-on-game-ai">A Quick Primer on Game AI</h2><p>While playing Mancala with myself in lockdown is fun for a little while, it's much more fun to have an opponent.</p><p>In university we learned about a game AI technique called <em><strong>MiniMax </strong></em>(and its less fashionable younger sibling, <em><strong>MaxiMin</strong></em>). Today, I'll be using MaxiMin to try and <em>maximise </em>the <em>minimum possible score </em>achievable by every move.</p><p>For example, let's imagine a simple two-player game where we both have two choices – <strong>A</strong> or <strong>B</strong> – and the game has a running score every turn.</p><p>Let's say that we're playing this game, and the current score is zero. By choosing <strong>A</strong>, I  know the score will become +1 in my favour; by choosing <strong>B</strong> I know it'll be +4 in my favour. Both options are great, but option B seems like the smartest one!</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2020/11/Screenshot-2020-11-11-at-22.02.25.png" class="kg-image" alt="Using Simple Game AI to Create a Killer Mancala Bot"><figcaption>Greedy game-playing</figcaption></figure><p>That's looking only 1 move ahead – it's what we might call a "greedy" strategy; taking the highest total score we possibly can each turn.</p><p>This is a half-decent strategy, and it's how most people start learning to play games like Mancala! In a lot of situations, though, humans can beat it by thinking a couple of moves ahead.</p><p>For example, let's look a couple of moves into the future. </p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2020/11/Screenshot-2020-11-12-at-13.22.36.png" class="kg-image" alt="Using Simple Game AI to Create a Killer Mancala Bot"><figcaption>Game tree showing the four possible outcomes of two opposing moves</figcaption></figure><p>If we're playing Green, it's the "greedy" choice to pick option B straight away. But then, regrettably... it's Blue's turn. Blue is trying to <em>minimise</em> our score. So Blue <em>could</em> choose B, but why would they do us any favours? If they're playing well, they'll chose A, and we'll end up on a score of -3 after two moves. </p><p>This is the core idea of MaxiMin – assume your opponent is playing perfectly, and maximise the score you're <em>guaranteed</em> to get. In this case, you can pick option A and guarantee that you'll have a score of at least -1. Not great, but not as bad as if you'd picked B!</p><p></p><h2 id="applying-ai-to-mancala">Applying AI to Mancala</h2><p>The great thing about Mancala is that there's at most 6 choices you have at any time. So you can relatively easily look 7 or 8 moves into the future without much computation time at all – it's under a couple of million configurations, which <a href="https://v8.dev">V8</a> crunches through in no time!</p><p>The only minor complication to just plugging a Mancala game into MaxiMin is when you can repeat a turn – but that's not too hard to account for in code.</p><p>The algorithm evaluates each move recursively. On the first player's turns, it picks the best moves for the first player; on the second player's turns, it picks the best moves for the second player. By doing this, it works out the optimal strategy to play against a <em>completely rational opponent</em>.</p><p>The base case of this recursive evaluation is to calculate the "final score" of the board – counting the marbles in both players' pots, combined with their stores, and taking the difference between the two. This base case is reached either when the depth limit is exceeded, or when no more moves are possible.</p><p>I've included this code below. The <code>updateBoard</code> function, which immutably creates a new board from the current board and a player/move, also returns a <code>nextPlayer</code> value. By passing down this, as well as the player whose score we're maximising, into the recursive call, we don't need to worry if the moves don't strictly alternate. At every level, we know whether to pick the move with the highest or lowest score!</p><script src="https://gist.github.com/bedekelly/8ae95faf266b7339db5b4b4e64d317e3.js"></script><p>Here's the full code to the game, including logic for calculating the next board states, captures and so on – it's a bit rough, but it gets the job done. I even did a few unit tests – which is honestly more than I expected of myself for a fun little side-project...</p><p><a href="https://gist.github.com/bedekelly/5f1d566df8368a8f08fec4acaec13aab">https://gist.github.com/bedekelly/5f1d566df8368a8f08fec4acaec13aab</a></p><p></p><h2 id="what-we-ve-all-been-waiting-for-">What we've all been waiting for...</h2><p>So, we've built this AI– how does it do in real games? Well, anecdotally, it's <em>scary </em>good: I'm not too bad at the game, but it kicks my butt almost every time. Playing the best game I can, and using the opening I'm most familiar with, it beat me <strong>23-13</strong>!</p><p>If you're interested to see how my Mancala-bot plays when it can see 8 moves in the future, try dragging the slider below to see me get owned in real-time:</p><div id="svelte-root"></div>
<link rel="stylesheet" href="https://static-electricity.s3.eu-west-2.amazonaws.com/mancala/bundle.css">
<script src="https://static-electricity.s3.eu-west-2.amazonaws.com/mancala/bundle.js"></script>
<style>
    
    input[type=range] {
      width: 100%;
      margin: 13.8px 0;
      background-color: transparent;
      -webkit-appearance: none;
    }
    input[type=range]:focus {
      outline: none;
    }
    input[type=range]::-webkit-slider-runnable-track {
      background: #3071a9;
      border: 0.2px solid #010101;
      border-radius: 1.3px;
      width: 100%;
      height: 8.4px;
      cursor: pointer;
    }
    input[type=range]::-webkit-slider-thumb {
      margin-top: -14px;
      width: 16px;
      height: 36px;
      background: #ffffff;
      border: 1px solid #000000;
      border-radius: 3px;
      cursor: pointer;
      -webkit-appearance: none;
    }
    input[type=range]:focus::-webkit-slider-runnable-track {
      background: #367ebd;
    }
    input[type=range]::-moz-range-track {
      background: #3071a9;
      border: 0.2px solid #010101;
      border-radius: 1.3px;
      width: 100%;
      height: 8.4px;
      cursor: pointer;
    }
    input[type=range]::-moz-range-thumb {
      width: 16px;
      height: 36px;
      background: #ffffff;
      border: 1px solid #000000;
      border-radius: 3px;
      cursor: pointer;
    }
    input[type=range]::-ms-track {
      background: transparent;
      border-color: transparent;
      border-width: 14.8px 0;
      color: transparent;
      width: 100%;
      height: 8.4px;
      cursor: pointer;
    }
    input[type=range]::-ms-fill-lower {
      background: #2a6495;
      border: 0.2px solid #010101;
      border-radius: 2.6px;
    }
    input[type=range]::-ms-fill-upper {
      background: #3071a9;
      border: 0.2px solid #010101;
      border-radius: 2.6px;
    }
    input[type=range]::-ms-thumb {
      width: 16px;
      height: 36px;
      background: #ffffff;
      border: 1px solid #000000;
      border-radius: 3px;
      cursor: pointer;
      margin-top: 0px;
      /*Needed to keep the Edge thumb centred*/
    }
    input[type=range]:focus::-ms-fill-lower {
      background: #3071a9;
    }
    input[type=range]:focus::-ms-fill-upper {
      background: #367ebd;
    }
    /*TODO: Use one of the selectors from https://stackoverflow.com/a/20541859/7077589 and figure out
    how to remove the virtical space around the range input in IE*/
    @supports (-ms-ime-align:auto) {
      /* Pre-Chromium Edge only styles, selector taken from hhttps://stackoverflow.com/a/32202953/7077589 */
      input[type=range] {
        margin: 0;
        /*Edge starts the margin from the thumb, not the track as other browsers do*/
      }
    }



    
    input[type="range"] {
      margin-top: 30px !important;
      margin-bottom: 30px !important;
    }
    
    ul {
      height: 140px;
    }
    
    @media(max-width:500px) {
        canvas {
            transform: scale(0.8);
        }
    }
</style><p>Thanks for getting this far – you're a trooper! If you've enjoyed this, or you think you can beat my Mancala AI, come follow me on Twitter (<a href="https://twitter.com/bedekelly#">@bedekelly</a>) – I generally post small coding projects I've been working on like <a href="https://twitter.com/bedekelly/status/1326132162576441346">this</a> or <a href="https://twitter.com/bedekelly/status/1322947067057213453">this</a>, and always include a link to the source code. Hopefully you'll see something you like! </p>]]></content:encoded></item><item><title><![CDATA[Testing Svelte with Knobs and Dials]]></title><description><![CDATA[<p>I'm super excited about Svelte! Compiling JS instead of doing virtual-DOM diffing is loads faster and opens up some amazing possibilities – once you get past the slightly weird syntax, that is.</p><p>A great test for whether I understand the basics of a framework is writing a Knob/Dial component. It</p>]]></description><link>https://old.bede.uk/testing-svelte-with-knobs/</link><guid isPermaLink="false">5fa3f6ce565166061234120e</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Thu, 05 Nov 2020 13:27:02 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-03-at-12.35.26.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-03-at-12.35.26.png" alt="Testing Svelte with Knobs and Dials"><p>I'm super excited about Svelte! Compiling JS instead of doing virtual-DOM diffing is loads faster and opens up some amazing possibilities – once you get past the slightly weird syntax, that is.</p><p>A great test for whether I understand the basics of a framework is writing a Knob/Dial component. It should work the same as in most music software these days – drag up, and it rotates clockwise, increasing the value; drag down, and the inverse happens. </p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2020/11/controlledknob-1.gif" class="kg-image" alt="Testing Svelte with Knobs and Dials"><figcaption>A Knob component with external state</figcaption></figure><p>This is a good test because it has three "representations" of a value:</p><ol><li>The actual value, maybe something like a volume from -12dB to +24dB;</li><li>The pixel offset of the user's cursor from their initial click location; and</li><li>The amount of rotation applied to the knob itself.</li></ol><p>Keeping these three values in-sync is an interesting problem. Dragging the cursor changes the pixel offset, which should affect both the rotation of the dial and the value reported by the knob component. </p><p>But not only that: the knob should also be "settable" from outside. In React-land, we think of this as a "controlled component" – if, say, the volume is being automated from elsewhere, it should be possible to control the knob (and its underlying values) without using the cursor. (In the gif above I've simulated this with a "set to 50%" button.)</p><p>I've found this is a great way to dig into whether I fully understand how data should flow in any given framework. For example, what's the "source of truth" of the three values: the pixel offset, the rotation, or the underlying value? </p><p>Almost always, it's a better idea to use the underlying value as the source of truth. But there's a few issues which occasionally crop up with this approach:</p><ol><li>The underlying value isn't actually accessible synchronously – e.g. all you have is a <code>set()</code> method, and a <code>get()</code> method which returns a Promise!</li><li>The underlying value can't be changed many times a second – maybe it's a parameter in a physics calculation happening in a web worker;</li><li>The underlying value isn't <em>linear</em> – for example, it makes sense to increase amplitude logarithmically for a perceieved linear increase in volume.</li></ol><p>Ideally, the Knob component should be built in such a way that these details don't matter <em>at all. </em>Integrating/extending this component to handle such cases is a good exercise in decoupling the UI and the inner workings of an application.</p><p>Here's my code for the animated example above – it's using Svelte's 2-way data binding, and anecdotally it seems a lot more performant than the React alternative – I think this is a case where the lack of virtual DOM diffing really shines!</p><p><a href="https://svelte.dev/repl/e76f28b965334d37a792ed1f2ecb67b1?version=3.29.4"><a href="https://svelte.dev/repl/fde0668b207045fa992fc04941b9508d?version=3.29.6">https://svelte.dev/repl/e76f28b965334d37a792ed1f2ecb67b1?version=3.29.4</a></a></p><p>And the code is copied here, if the Svelte online REPL doesn't work for you:</p><script src="https://gist.github.com/bedekelly/f4ddb1d5075dbb2585b5e49b9ffb517c.js"></script><p>Enjoy!</p>]]></content:encoded></item><item><title><![CDATA[Your First Day of Ultra-Wealth]]></title><description><![CDATA[<p>Imagine waking up one day and being told:</p><blockquote>“Every second you’re awake, you can spend £50.”</blockquote><p>What would you spend it on?</p><p>If you’re like me, your first thought would be food. That’s a seriously fancy order delivered to your door – a full meal for you and</p>]]></description><link>https://old.bede.uk/ultra-wealth/</link><guid isPermaLink="false">5dd233b8558b66053c973faa</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Mon, 18 Nov 2019 06:01:45 GMT</pubDate><media:content url="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-12-at-18.53.24.png" medium="image"/><content:encoded><![CDATA[<img src="https://old.bede.uk/content/images/2022/04/Screenshot-2022-04-12-at-18.53.24.png" alt="Your First Day of Ultra-Wealth"><p>Imagine waking up one day and being told:</p><blockquote>“Every second you’re awake, you can spend £50.”</blockquote><p>What would you spend it on?</p><p>If you’re like me, your first thought would be food. That’s a seriously fancy order delivered to your door – a full meal for you and a partner. But maybe the first order wasn’t quite up to scratch, so you try somewhere else: a dessert place this time. (Hey, you can afford a personal trainer now!)</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/-_86.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>Many people would start paying off their bills. Five seconds more, and this month’s electricity, gas, water, phone and internet bills (plus TV license!) are all paid in full (£250).</p><p>A big grocery shop to fill the cupboards (£100), and another couple of seconds elapse. Booking a day trip to the nearest spa to celebrate (£200, 4s); thirteen seconds in total have passed.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/bigstock-Wooden-kitchen-cabinet-full-of-81291536-1.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>Go ahead and get a bottle of wine in. Waiting just five seconds gets some premium booze (£250). And bring some friends round – a couple more seconds and all their taxi fares are covered.</p><p>Let’s set our sights a bit higher. On average, people in the UK have £15,400 in debt. That’s a genuinely huge amount of money that causes people untold amounts of stress. Perhaps we’ll have to wait overnight for that to be paid off? No, actually– it’ll take a little over 5 minutes.</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><p>Debt-free and well-fed, with great company for the evening, and full cupboards: we’ve spent under five and a half minutes so far.</p><p>To make it up to six minutes, we can pay our £1k rent for the month (20 seconds); all our travel costs for the month (£230 for a monthly zones 1-5 travelcard, or 5 seconds); another big shop (£100, 2 seconds); and spend the remaining 9 seconds (£450) on a whole new wardrobe.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/91718067-wardrobe-full-of-different-men-and-woman-clothes.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>Short-term needs (and some desires) fulfilled – after just 6 minutes – a lot of people start thinking about the medium term. Waiting another minute covers the next <em>year</em> of travel (£2400, 48s, rounded up for £600 extra out-of-London). Another four minutes, and the next year’s rent (£12k, 4m) is paid. After another minute, all bills for the next year (£200x12=£2400) are sorted too. Fourteen minutes after waking up, you can safely afford food for the whole year.</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><p>At this point, your quality of life is roughly the same – but you don’t have to worry about food, rent, bills or travel costs any more for the next year. If the money stopped flowing now, you’d still be able to quit your job and spend your time with friends, working on personal projects, creating art and learning. In real terms, you’ve been given £42,000, or a fairly high big-city salary after tax, all in the first 14 minutes.</p><p>A car is often the next big purchase people consider making. Especially outside of London, it can help immensely with employability and care of relatives, as well as just freedom to explore. Spending £30k for a new car will get you a nice Audi or Mini, and you’ll only have to wait 10 more minutes for it.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/audia4.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>So why not wait a little longer? Waiting an hour and a quarter, you could bag a brand-new Lamborghini – the 2020 Huracán Evo Spyder. And I’d be lying if I said I knew <em>anything</em> about what justifies its $290k price tag.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/ezgif-4-3357a50bec15.png" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>But this is a huge purchase for someone who lives in a pretty modest flat. Waiting 6 more hours (with bated breath), you can outright <em>buy</em> this luxury London apartment for £1m:</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/Screenshot-2019-11-17-at-20.06.43.png" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>Or if you decided to move outside London, this sprawling countryside mansion for nearly the same amount (and you’d have £50k left over for a <em>third</em> car, too):</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/Screenshot-2019-11-17-at-20.07.57.png" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><p>It’s been a hell of a day. If you woke up at 8:00am, you’d have been debt-free and comfortable by 8:06am; and fully paid-up for the next year’s expenses by 8:14am.</p><p>By 8:24am, you’d have a brand new car.</p><p>By 9:39am, you’d have a 2020 supercar which would turn heads anywhere in the world. (Let's call it 10:00 – just to get all the comfy extras.)</p><p>And by four in the afternoon, you’d have signed the deeds on a countryside mansion, or a luxury London penthouse – your choice. (If you waited till 10 in the evening, you could comfortably have <em>both</em>.)</p><p>Let’s say you were more charitably inclined, though. Instead of going for the second house, you could choose to fund a charity.</p><p><a href="https://givewell.org">GiveWell</a> recommends the Malaria Consortium’s “seasonal malaria chemoprevention” programme, and has verified that it’s capable of absorbing up to $66MM in funds. It estimates that the cost of covering one person for four months of its treatment programme is roughly £5.36 – that’d be nine people every <em>second</em>, with your newfound wealth.</p><p>Putting just a couple of hours into this programme could effectively protect sixty-seven THOUSAND people from malaria. That’s a huge number to comprehend, but in West Ham’s new stadium it’d look like this:</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/west-ham-juventus-london-stadium_3759807.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>(plus a big crowd of a few thousand waiting outside!)</p><p>It’s 7:00pm, and you’ve already saved the lives of countless tens of thousands of people you’ve never met. It’s easy to feel like you’ve done more than enough – after all, you didn’t <em>have</em> to give anything to charity.</p><p>We’ve been making some fairly large purchases, so it’s worth remembering just how fast the money is flowing in. In the sixty seconds from 7:00 to 7:01, you could buy:</p><ul><li>Another fancy meal for two, delivered to your door;</li><li><em>Each</em> current-generation games console (PS4, Switch, and Xbox One);</li><li>A night out in a posh London cocktail bar;</li><li>A Deluxe King room at the Savoy hotel;</li><li>£200 in premium skincare products;</li></ul><p>and still have nearly £100 left over to idly rip up as you start to wonder how you’re going to spend the rest of the cash. All in the space of <em>a single minute</em>.</p><p>From then until the end of the night, you’d accumulate £897k – enough for this ten-cabin mahogany sailing ship.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/7219420_20190916043439112_1_XLARGE.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/11/7219420_20190916043518059_1_XLARGE.jpg" class="kg-image" alt="Your First Day of Ultra-Wealth"></figure><!--kg-card-end: image--><p>Over the course of the day, it’s become clear that you have no reasonable way of spending the money you’ve been given. Your quality of life has been irrevocably changed: food, bills, and other incidental costs are now meaninglessly small amounts of money for you. It’s likely that you’ll have stopped thinking about money in units any smaller than £3000, which you accumulate in exactly 60 seconds. You’ll consider employing people just to advise you on how to spend your money, or to manage the cars and properties you’ll likely never spend much time with.</p><p>In total, you’ve been given £2.88 million for your first day.</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><p>The richest man in the world as of 15/11/19 is Bill Gates, with $110B (or around £85 billion). Widely acclaimed for his philanthropy, Gates’ fortune has nevertheless grown by £16B since last year, even taking into account his charitable donations.</p><p>For Gates, the thought experiment above is a reality – not just for one day, but for every day of the rest of his life. Even if his net worth never grew again, he could spend this amount of money every day – new stadiums full of people saved from malaria, new sports cars, new exotic homes – without seeing a dent.</p><p>In fact, if this spending went on for eighty <em>years</em>, he’d still comfortably be a billionaire.</p><p>The argument against higher taxes on the ultra-wealthy often goes that people have worked hard for what they have; that they’re just reaping the rewards of waking up early and “hustling” for decades. This argument relies on a lack of understanding of the true scale of billions of pounds, and insults the genuine working class who can often barely afford to pay their rent after long shifts in hazardous conditions.</p><p>While there are faintly more credible economic arguments regarding “job creation”, it seems clear that the supposed ”incentive” is too great – that simply <em>having</em> wealth on such a vast scale is an immoral act. Even despite Gates’ charitable contributions, his personal net worth increased by $19B over the last year: enough for another <em>eighteen years</em> of the unimaginable spending detailed above.</p><p>Whatever the case, it’s worth remembering this rule of thumb: each billion pounds is nearly a full <em>year</em> of new supercars, mansions, boats, and more – every single day. If that isn’t worth redistributing, I’m not sure what is.</p>]]></content:encoded></item><item><title><![CDATA[Guard Clauses and the List Monad]]></title><description><![CDATA[<p>Some Haskell code on StackOverflow with appealingly concise syntax turned out to be surprisingly deep, and teach me a new type! Here's the code (collated from <a href="https://stackoverflow.com/a/20644753">https://stackoverflow.com/a/20644753</a>):<strong> </strong></p><script src="https://gist.github.com/bedekelly/fe99f2d56e3ef9c8196ccdc9340eb372.js"></script><p>So by using the List Monad, we explore all its possible values. But what exactly is "guard"?</p><p>It turns</p>]]></description><link>https://old.bede.uk/modelling-nondeterminism-with-the-list-monad/</link><guid isPermaLink="false">5d82f7d98d18380516d04b31</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Thu, 19 Sep 2019 03:57:19 GMT</pubDate><content:encoded><![CDATA[<p>Some Haskell code on StackOverflow with appealingly concise syntax turned out to be surprisingly deep, and teach me a new type! Here's the code (collated from <a href="https://stackoverflow.com/a/20644753">https://stackoverflow.com/a/20644753</a>):<strong> </strong></p><script src="https://gist.github.com/bedekelly/fe99f2d56e3ef9c8196ccdc9340eb372.js"></script><p>So by using the List Monad, we explore all its possible values. But what exactly is "guard"?</p><p>It turns out, we're not just using a Monad here. In Haskell, we're actually using the fact that list is a MonadPlus: roughly, a Monad plus another type class called an Alternative. This type class makes sure that our data type has an "Empty" value.</p><p>The Alternative lets us define <code>guard True</code> as identity, and <code>guard False</code> as "Empty". This means that when we transform the do-notation into "bind" calls, and reach the guard clause, we continue with our "Empty" value if the guard clause didn't match.</p><p>What that means for lists is that when collating the final lists at the end, the branches where the guard clauses were false will be empty. Because of the "flattening" effect of bind with lists, those branches effectively don't appear in the end result.</p><p>So in our example, the branches where we tossed "Tails" don't matter – we're able to strip them out with a guard clause. </p><p>This is "Nondeterminism", in the sense that <em>all </em>possible branches of the code are followed. It's up to us, later on, to choose to analyse the outcome by e.g. picking a random branch.</p><p>And of course, here's the same code in my (somewhat clunkier) Python do-notation:</p><script src="https://gist.github.com/bedekelly/52c4caa0ad744159d07b6ca6a929438a.js"></script>]]></content:encoded></item><item><title><![CDATA[Monads and Do-Blocks in Python]]></title><description><![CDATA[<p>Functional programming is a bit like writing regular expressions, in that the effort-expended-per-character is really high. It’s always annoyed me how Enlightened Functional Programmers online love to use bizarre names like “ap” and “&lt;$&gt;” for their functions – it makes me wonder if they’re using some experimental compiler</p>]]></description><link>https://old.bede.uk/do-notation-for-monads-in-python/</link><guid isPermaLink="false">5d8201e38d18380516d04b15</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Wed, 18 Sep 2019 10:13:57 GMT</pubDate><content:encoded><![CDATA[<p>Functional programming is a bit like writing regular expressions, in that the effort-expended-per-character is really high. It’s always annoyed me how Enlightened Functional Programmers online love to use bizarre names like “ap” and “&lt;$&gt;” for their functions – it makes me wonder if they’re using some experimental compiler that charges them a few cents per character.</p><p>The reason for this seems to be that it’s really hard to name things that are as general as monads, applicatives, and so on. When Lists, Optional types and Future values are all monads, what do you call a method which works for all of them? <code>liftA2</code> might be a horrible function name, but I can’t really think of a better one.</p><p>Anyway, I’ve tried to avoid being too much of a functional programming extremist in this code. Primarily, that’s because I’m not smart enough to be one. But also, I didn’t want the code to be absolutely impenetrable to people who haven’t used monads before; I tried to make the API as reasonable as possible.</p><p>I’ve written a decent introductory explanation of monads at the bottom of this post: you’ll spot it by the radioactive signs. I think it gives a good overview of monads for people whose brains work like mine.</p><h2 id="do-notation-hacking-generators">Do Notation: Hacking Generators</h2><p>(Fair warning: if you're not an FP nerd, this might be intolerably jargon-y. Feel free to skip to the Monads explanation first and come back here.)</p><p>Here’s a sample of the sort of code you can write with this do-notation in Python:</p><pre><code>@do
def product2(monad_a, monad_b):
    x = yield monad_a
    y = yield monad_b
    return (x, y)
</code></pre><p>These monads can be anything: lists, optionals, futures, whatever. The only restriction is that you can’t interleave side-effects with the “yield” calls – they’ll be run more times than you expect. Side effects and other calculations are fine as long as they all go after the last <code>yield</code> keyword.</p><p>Why is this? Well, it stems from the fact that you can’t copy running generators in Python.</p><p>The <code>yield</code> keyword is used here because it lets functions behave like coroutines. That is, you can send values into them and get values back out again. Their execution is driven by an outside agent calling <code>next(g)</code> or <code>g.send(…)</code>.</p><p>Compilers (and people) understand do-notation as nested <code>bind</code> calls, where the function passed in to bind is, in some sense, a callback to the rest of the do-block. But where that’s hard to do in Python is where Lists are involved – calling <code>bind</code> will mean that the rest of the do-block needs to be run more than once.</p><p>In imperative, non-compiled-land, this means we need to somehow duplicate the state of our coroutine. Unfortunately, CPython doesn’t provide a way of doing this natively; PyPy used to, but now seems to exhibit the same error as Python.</p><p>To do this manually (and with the caveat that side-effects can’t be interleaved with yields), I wrote a function called <code>run</code> which recursively calls <code>bind</code> with a partial application of the unwrapped values we’ve got so far inside the do-block.</p><p>Here’s how it looks:</p><script src="https://gist.github.com/bedekelly/decd5c6da32471a8a99d34aa8279b78c.js"></script><p>Note that I’ve defined <code>__rshift__</code> on the monad class as just syntactic sugar for the <code>.bind()</code> method. The key here is the advancing generator, building up of <code>values_so_far</code> in the recursive call, and catching the final StopIteration when the generator is exhausted – that is, when the function is complete.</p><p>The fact that this is defined in terms of a recursive call via <code>bind()</code> means that it works for <em>anything</em> with a bind method. So lists and optionals work just how you’d expect them to. I’m planning to write some more interesting monads like Writer and Future, too, to show off just how flexible this notation is.</p><hr><p>If this has all been complete gobbledegook, please see my intro to monads below: it’s much more readable.</p><h2 id="-monads-explanation-">☢️ Monads Explanation ☢️</h2><p>I think the main benefit of monads is that you can write a lot of really general code which sequences them together, without needing to know what they actually /are/ under the hood.</p><p>Especially for object-oriented people, it’s useful to think of a monad like an interface. It’s got to have two methods in particular: <code>point</code> and <code>bind</code>. These are totally, ridiculously obscure names. And I think that’s why so much FP is hard to get into; because generally programmers are used to thinking about what methods /do/, instead of what /types/ they have.</p><p>(Note: I’m going to keep calling them “methods”, even though it’s not 100% correct – who cares.)</p><p>The “point” method lets you create a new instance of a monad. For the List monad, it transforms <code>x</code> into <code>[x]</code>. For the Optional monad, it transforms <code>x</code> into <code>Some(x)</code>. For the Future monad, it transforms <code>x</code> into a <code>Future(x)</code>. People tend to be pretty comfortable with the point method, because it’s basically a constructor. It “wraps” a type into the List, Option, Future, or whatever other thing you’re dealing with.</p><p>The “bind” method is slightly trickier. It takes two parameters: firstly the monad (list, option, future etc.) itself; and secondly, a function which transforms a regular value into the same monad we’re using.</p><p>Here’s the type signature of bind, for the List monad:</p><p><code>bind :: List x -&gt; (x -&gt; List y) -&gt; List y</code></p><p>And here’s the type signature of bind, for the Option monad:</p><p><code>bind :: Option x -&gt; (x -&gt; Option y) -&gt; Option y</code></p><p>You can make this more general-purpose by swapping “Option” or “List” here for whatever monad you’re currently thinking about.</p><p><code>bind :: SomeMonad x -&gt; (x -&gt; SomeMonad y) -&gt; SomeMonad y</code></p><p>This seems a bit weird, especially for Lists. Why would a function take a single value and return a list? Well, fair point. A lot of the time, you don’t really need a monad, and you could do with something a bit weaker – something like a Functor, which has a <code>map</code> method but no <code>bind</code>.</p><p>(Note: there’s actually a whole /hierarchy/ of types. If you’re thinking “hang on, you can map over lists! Is List really just a Functor?”, then you’re right – a Monad is a /subtype/ of Functor. That means anything you can do with a Functor – in this case, the “map” operation – you can do with a Monad, too.)</p><p>Where monads get useful, though – and how they’re often explained – is the idea of /sequencing computations/. I’m going to use JavaScript Promises as an example, but you should know that for <em>pedantic technical reasons involving objects with a ‘then’ key</em>, Promises aren’t actually Monads. But they’re like 98% of the way there, and they’re pretty ubiquitous.</p><p>Let’s look at some example Promise code in JavaScript.</p><pre><code>fetch(“https://bede.io”)
  .then(data =&gt; {
    return decode(data)
  })
  .then(decodedData =&gt; {
    return process(data)
  });
</code></pre><p>And let’s assume that these three things return Promises:</p><ul><li><code>fetch(url)</code></li><li><code>decode(data)</code></li><li><code>process(data)</code></li></ul><p>Now let’s think about the types in the code we’ve just seen. Specifically, what’s the type of the <code>.then()</code> method?</p><p>Well, let’s squint a bit, and say that because <code>.then()</code> is a /method/ – as in, it’s attached to the Promise object – then that Promise object can count as the first parameter to our function.</p><p><code>then :: Promise data -&gt; …</code></p><p>(In JavaScript you have to squint a bit to believe this. But it’s a bit more explicit in Python, where to write a method you declare <code>self</code> as the first parameter.)</p><p>Now let’s see what the next parameter is. We’re passing an anonymous function which takes <code>data</code> as its first parameter: this isn’t a Promise, this is just a bit of data. But we return <code>decode(data)</code>, which in our handy bullet-pointed-list above we’ve said above actually returns a Promise.</p><p>(Is <code>decode(data)</code> a real API? No. But there are plenty of browser APIs that accept data and return promises – take the method to convert fetch-data to an array buffer, for example. I just didn’t want to muddy the waters with implementation details. The important thing is the type of these functions, not what they actually do.)</p><p>So the value we’re passing into <code>then</code> is of this type:</p><p><code>&lt;anonymous&gt; :: data -&gt; Promise decodedData</code></p><p>In other words, our anonymous function accepts some data and returns a Promise of some decoded data.</p><p>We’re passing this function to our <code>.then</code> method. Let’s look at how the type signature looks now:</p><p><code>then :: Promise data -&gt; (data -&gt; Promise decodedData) -&gt; …</code></p><p>Now let’s try and fill in the blanks at the end. This is just a bit of JavaScript knowledge, but the point of <code>.then</code> is to let you <em>chain</em> promises together: what we end up with is a Promise of decodedData.</p><p><code>then :: Promise data -&gt; (data -&gt; Promise decodedData) -&gt; Promise decodedData</code></p><p>So we’ve written out our type signature for the <code>.then</code> method. Why am I spending so much time and effort on this?</p><p>Well, let’s have another look at our <code>bind</code> type from earlier:</p><p><code>bind :: SomeMonad x -&gt; (x -&gt; SomeMonad y) -&gt; SomeMonad y</code></p><p>See the similarity? Here we’re just renaming “x” to “data”, “y” to “decodedData”, and our monad to “Promise”.</p><p>(If you remember from earlier, to make Promise a monad, we also need a “point” to wrap any value into a Promise: <code>Promise.resolve(x)</code>  fulfills that requirement.)</p><p>The useful thing to take away here is that we’re able to string together chains of functions which accept plain data and return Promises. <code>fetch</code>, <code>decode</code> and <code>process</code> all let us do asynchronous computing without worrying about the results immediately, by giving us a Promise – a future result that we can slap a callback on.</p><p>This is what people mean when they say Monads let you sequence computations. A Promise is sort of like a “computation” on its value – it’ll resolve at some point in the future.</p><p>This is also what people mean when they say Monads are like a “computational context” for values. In the case of a List type, the “context” is that there’s more than one value, and we tend to do things to each value in the list. For an Optional type, the context is that the value might not be there, and we don’t try to call functions on values that aren’t there. If you want to write a monad, that context is <em>your job as a programmer</em> to write in the <code>bind</code> method, if you want to create a monad type.</p><p>There’s some rules about monads which I think are only useful to learn when you’re really invested in functional programming. They aren’t particularly intuitive and don’t really help you write general-purpose code. The idea of monads as the interface with “point” and “bind” is incredibly powerful, and lets you write genuinely abstract code. Worrying about homomorphisms at this point, I think, is more for the theory nerds – although there are some <a href="https://github.com/promises-aplus/promises-spec/issues/94">interesting implications for Promises</a>.</p><h3 id="do-notation">Do Notation</h3><p>This notation starts off being quite confusing, especially when people use the term “return” to mean subtly different things in different languages. But it’s a really smart idea.</p><p>Let’s say you have some variable which is of type <code>Future x</code>. As in, at some point in the future, you’ll have an <code>x</code>. And you have a similar variable of type <code>Future y</code>.</p><p>It’d be handy to sequence something to happen when both Futures are resolved. Ordinarily, we’d do that like this:</p><pre><code>future_x.bind(x =&gt;
  future_y.bind(y =&gt;
    doSomething(x, y)
  )
)
</code></pre><p>Inside the two nested functions, we have access to x and y as “real” values, and we can pass them to a function call, add them together, access properties on them, whatever we like. But the trick is that that inner function will only be called AFTER the futures have resolved.</p><p>However, it can get boring to have to write <code>.bind</code> a hundred times in a row. And we’ve only got so much horizontal space available. So people came up with a smart way of writing code which compiles to nested <code>.bind</code> calls:</p><pre><code>do {
  x &lt;- future_x
  y &lt;- future_y
  doSomething(x, y)
}
</code></pre><p>It’s the same outcome, but suddenly it looks more like the synchronous code we’re used to writing!</p><p>Although JavaScript doesn’t have support for do-notation syntax generally, it has introduced one special-case form of do-notation for an incredibly popular monad(ish) type: Promises.</p><pre><code>async () =&gt; {
  x = await promise_x
  y = await promise_y
  doSomething(x, y)
}
</code></pre><p>Although the comparison with JS promises and async/await is a useful one, it’s sometimes a bit limiting. For example, in functional languages like Scala, it’s possible to use do-notation with very different monads like the Option monad:</p><pre><code>do {
  x &lt;- maybeX
  y &lt;- maybeY
  doSomething(x, y)
}
</code></pre><p>In this pseudocode, <code>doSomething(x, y)</code> will <em>only</em> be called if x and y are both <code>Some</code> values. It’s exactly the same syntax, for a very different effect.</p><p>Equally, here’s a way to print all the possible combinations of a two-digit bike lock:</p><pre><code>do {
  a &lt;- [0..9]
  b &lt;- [0..9]
  print(a, b)
}
</code></pre><p>In this case, the values a,b,c and d will take on each <em>subsequent</em> value in each of their lists. So the printed results will be “0 0 0 0”, “0 0 0 1”, etc., all the way up to “9 9 9 9”.</p><p>Three completely different effects; all the same syntax. The common feature here is that we're leaning on the definition of <em>bind </em>for each type in turn: Promises (with <code>.then()</code> acting as our bind function); Optionals, and Lists.</p><p>In order to use this powerful compositional tool, programmers just need to implement two methods: <code>point</code> and <code>bind</code>. How <code>bind</code> works is largely up to them – so it's important to get right. However, when that's done, it can lead to powerful and abstract code which works for very diverse types.</p>]]></content:encoded></item><item><title><![CDATA[Hashtables in C: Table Doubling]]></title><description><![CDATA[<p>After revising some data structures recently, I thought it'd be an interesting challenge to write some of them in C. I started with a linked list, and then went on to use the linked list in a Hashtable. The code can be found <a href="https://github.com/bedekelly/c-hashtable">here</a><strong>.</strong></p><p>The interface is fairly simple, with</p>]]></description><link>https://old.bede.uk/hashtables-in-c-table-doubling/</link><guid isPermaLink="false">5d5da88c8b96d50516a853d1</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Wed, 21 Aug 2019 20:37:43 GMT</pubDate><content:encoded><![CDATA[<p>After revising some data structures recently, I thought it'd be an interesting challenge to write some of them in C. I started with a linked list, and then went on to use the linked list in a Hashtable. The code can be found <a href="https://github.com/bedekelly/c-hashtable">here</a><strong>.</strong></p><p>The interface is fairly simple, with <code>ht_set</code>, <code>ht_get</code> and <code>ht_delete</code> forming the main API for interacting with a hashtable. To create a hashtable the code provides <code>ht_create</code>, and to destroy it (fittingly) <code>ht_destroy</code> should be called. This last function takes pains to clear up each "chain" (linked list) as well as the underlying hashtable itself.</p><p>When <a href="https://old.bede.uk/profiling-hashtables-in-c/">implementing hashtables in the past</a>, I've fallen into the trap of allowing insertions/deletions become O(n) as the table grows. This is because I haven't implemented <em>Table Doubling</em>: a method for ensuring that the load factor of a hashtable remains low as more and more elements are added.</p><p>As soon as the load factor reaches a preset limit (defined in <code>hashtable.h</code>), the table will resize itself at the next <code>ht_set</code> operation. This is accomplished by iterating through each of the linked lists comprising the old hashtable, re-hashing every element, and adding it to a new table double the size of the original.</p><p>This resizing is a costly operation, but as the table grows it happens exponentially less frequently. For very small sizes of table, a linked list (or even simply allocating an array) may have less overhead; for larger maps this is ideal.</p><p>Here's the full code of the <code>ht_set</code> operation:</p><script src="https://gist.github.com/bedekelly/cbc793156637019326f102d12d574ca2.js"></script><p>To verify that the hashtable was performing as expected I profiled it in depth in this <a href="https://github.com/bedekelly/hashtable/blob/master/analysis/notebook.pdf">Jupyter Notebook</a>. This demonstrated that the time taken to insert, retrieve or delete a value didn't grow with the number of elements in the hash table. In other words, the <em>asymptotic time complexity </em>of these operations was constant: O(1).</p><p>Here's a chart from the notebook showing the (lack of) growth:</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/09/A5383C6C-6BB7-4F5A-8BC9-0B675CFF4F22.jpeg" class="kg-image"></figure><p>The maths behind log-log graphs is somewhat tedious if you don't already have a good intuition for it, but generally speaking the <em>slope</em> of a log-log graph indicates the <em>power </em>relationship. For example, if the slope of a log(y)/log(x) graph is 3, then we can say y is related to x^3. In this case, the slope is close to zero, so we can say y is a constant value – not related to the value of x, which in this chart is the size of the hashtable.</p><p>I also ensured that the table had no memory leaks by using Valgrind. In order to do this I had to use a Docker container, as Valgrind refused to build on my (beta) version of MacOS. This was a fairly straightforward use of Docker but did involve mounting the source directory as a volume, so the image wouldn't have to be rebuilt every time the source code changed.</p>]]></content:encoded></item><item><title><![CDATA[CSS Recreations]]></title><description><![CDATA[<p>Today I recreated some designs from Polaroid and RadioShack. As ever, I don't load images for any of these designs – everything is styled with fonts and CSS. Here are two designs roughly taken from Polaroid logos in use today: </p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/07/Screenshot-2019-07-09-at-23.47.52.png" class="kg-image"><figcaption>Polaroid logo on a white background</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/07/Screenshot-2019-07-09-at-23.48.19.png" class="kg-image"><figcaption>Polaroid logo on a black</figcaption></figure>]]></description><link>https://old.bede.uk/css-recreations/</link><guid isPermaLink="false">5d25176b6375a504f302c87c</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Tue, 09 Jul 2019 23:01:27 GMT</pubDate><content:encoded><![CDATA[<p>Today I recreated some designs from Polaroid and RadioShack. As ever, I don't load images for any of these designs – everything is styled with fonts and CSS. Here are two designs roughly taken from Polaroid logos in use today: </p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/07/Screenshot-2019-07-09-at-23.47.52.png" class="kg-image"><figcaption>Polaroid logo on a white background</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/07/Screenshot-2019-07-09-at-23.48.19.png" class="kg-image"><figcaption>Polaroid logo on a black background</figcaption></figure><p>The rainbow detail and trademark symbol here is taken from the <a href="https://www.underconsideration.com/brandnew/archives/new_logo_identity_and_packaging_for_polaroid_originals_done_in_house.php">Polaroid Originals logo</a>, and the Polaroid text is from the <a href="https://polaroid.com">main logo</a>.</p><p></p><p>I also had a go at recreating two blank VHS covers. Here's one from Radio Shack:</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/07/Screenshot-2019-07-09-at-23.39.46.png" class="kg-image"><figcaption>Radioshack "Supertape" VHS cover</figcaption></figure><p>This is copied mostly from a <a href="https://youtu.be/e9DfSCk-6Ko?t=25">video</a> reimagining VHS covers, presumably drawing on this <a href="https://66.media.tumblr.com/ebb006bc1abbacce2b844e2fbcc0da75/tumblr_pem5a1VI4N1usyxujo1_1280.jpg">original cover</a>. </p><p>And here's one from Polaroid, with a scan of the original cover on the left for comparison:</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/07/Screenshot-2019-07-09-at-22.00.39.png" class="kg-image"><figcaption>Polaroid VHS cover (left) and CSS recreation (right)</figcaption></figure><p>These are all available on my <a href="https://codepen.io/collection/DQkkay/">CodePen</a> – no really fancy tricks were used, other than abusing <code>linear-gradient</code> to define the multicoloured blocks:</p><pre><code>.colors {
    background: linear-gradient(to bottom, 
        rgb(24, 144, 174) 0%, 20%,
        rgb(161, 181, 41) 20%, 40%,
        rgb(246, 208, 47) 40%, 60%,
        rgb(231, 128, 36) 60%, 80%,
        rgb(224, 54, 101) 80%
    );
}</code></pre>]]></content:encoded></item><item><title><![CDATA[Cross-Platform Resume for YouTube]]></title><description><![CDATA[<p>I've been wanting a feature in YouTube for months now, and finally got to the point where I just decided to make it myself. The problem: if I'm playing a video on my laptop, how do I continue playing that video on my phone? </p><p>Currently, the best way I could</p>]]></description><link>https://old.bede.uk/cross-platform-youtube-resume/</link><guid isPermaLink="false">5cbb8536445dab0518ffc51e</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Sat, 20 Apr 2019 22:21:10 GMT</pubDate><content:encoded><![CDATA[<p>I've been wanting a feature in YouTube for months now, and finally got to the point where I just decided to make it myself. The problem: if I'm playing a video on my laptop, how do I continue playing that video on my phone? </p><p>Currently, the best way I could find was to right-click the YouTube video and select "Copy video URL at current time". I'd then use AirDrop to send that over to my phone. However, it'd tend to open in Safari rather than the actual YouTube app. Not good!</p><p>As any UX designer knows, the best design for a user is often something that takes as few clicks as possible. But I also didn't want to require any installation on the phone side – I have a few mobile devices and don't want to maintain anything for them.</p><p>The final product works like this:</p><ul><li>On any YouTube video, you can click a button next to the URL bar in Chrome</li><li>A QR code pops up</li><li>Scanning that QR code leads straight to the same YouTube video, at the same time</li></ul><p>This relies somewhat on two iOS features:</p><ul><li>The Camera app scans for QR codes by default; and</li><li>YouTube links are opened in the app</li></ul><p>I believe the second is also true for Android phones – but they'd have to use a dedicated QR code scanner app, which is another tap away. The iOS camera, by contrast, is available even on the lock screen.</p><p>Here's what the popup looks like:</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/04/Screenshot-2019-04-20-at-21.57.47.png" class="kg-image"></figure><p></p><p>It's not big enough to block out the video (and disappears as soon as you click off it). But it's easily big enough to immediately be recognised by the camera on my iPhone. </p><p>To define the behaviour and permissions of our Chrome extension, we use a Manifest file, <code>manifest.json</code>.</p><pre><code>{
    "name": "Youtube Resume",
    "permissions": ["declarativeContent", "activeTab"],
    "version": "0.0.1",
    "description": "Resume YouTube videos on another device!",
    "background": {
	"scripts": [ "background.js" ],
	"peristent": false
    },
    "page_action": {
	"default_popup": "popup.html",
	"default_icon": {
	    "128": "icon.png"
	}
    },
    "icons": {
	"128": "icon.png"
    },
    "manifest_version": 2
}
</code></pre><p>To make a popup appear when we click the button, we configure <code>background.js</code> to use a PageAction: this lets us declaratively specify that the popup should only appear while on YouTube.</p><pre><code>// background.js

chrome.runtime.onInstalled.addListener(function() {
  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
    chrome.declarativeContent.onPageChanged.addRules([{
      conditions: [new chrome.declarativeContent.PageStateMatcher({
        pageUrl: {hostEquals: 'www.youtube.com'},
      })
      ],
          actions: [new chrome.declarativeContent.ShowPageAction()]
    }]);
  });
});</code></pre><p>The popup itself is just an HTML page, and it's one of the simplest I've ever written – it really doesn't have to do much.</p><pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;body&gt;
    &lt;div id="qrcode"&gt;&lt;/div&gt;
    &lt;script src="qrcode.js"&gt;&lt;/script&gt;
    &lt;script src="popup.js"&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre><p>So, how do we replace our empty <code>"qrcode"</code> div with a real QR code? Easy – we use a library. I grabbed a copy of [qrcode.js](<a href="https://davidshimjs.github.io/qrcodejs/">https://davidshimjs.github.io/qrcodejs/</a>), because I've done enough Canvas drawing recently and I don't mind taking a shortcut. </p><p>To get the URL, we have to do some slightly convoluted things. The JavaScript which displays the QR code is running in the context of the <em>extension</em>, but – although I think there <em>is </em>a way to get the URL of the current page – there's no way of asking for the current time of the YouTube video. For that, we need access to the DOM, which the extension doesn't have. </p><p>To get around this, we inject code into the active page. (Don't worry – if this was distributed, we'd have to ask the user's permission to do this when they install the extension!). This code grabs the HTML5 video element from the page and requests the current time. It also grabs the URL of the current page, and strips out any outdated time information using a regular expression. </p><pre><code>// Inject a script into the active page.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    chrome.tabs.executeScript(
        tabs[0].id,
	{ file: "inject.js" }
    );
});</code></pre><p>To allow this script to be run multiple times, we use an IIFE – an immediately-invoked function expression – to prevent any errors caused by redeclaring <code>const</code> values like "url".</p><pre><code>(function(){
    const time = Math.floor(
      document.querySelector(".html5-main-video").currentTime
    );
    const href = window.location.href.replace(/\&amp;t\=\d+/g, '');
    const url = `${href}&amp;t=${time}`;
	
    // Send a message back to the extension:
    chrome.runtime.sendMessage({url: url});
})();</code></pre><p>Our injected script, though, can't affect the QR code displayed in the extension. To do that, we need to send a <a href="https://developer.chrome.com/apps/messaging#simple">message</a> back to the extension's JavaScript code – which we've configured to listen out for these messages and update the QR code accordingly.</p><pre><code>let url = "";
const qr = document.getElementById("qrcode");
const qrCode = new QRCode(qr, url);

// Listen for new messages.
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
	const url = request.url;
	qrCode.makeCode(url);
    }
);</code></pre><p>So, to summarise:</p><ul><li>The extension injects a script into the YouTube page when clicked</li><li>This script calculates the current time, formats the URL and sends it back to the extension</li><li>The extension can then display a QR code linking to this URL.</li></ul><p>Here's a screenshot of my iPhone scanning this QR code and popping up a quick action. Just tapping this notification takes me straight into the YouTube app and starts playing the video from the exact second I left off on my desktop. Neat!</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/04/IMG_1628.PNG" class="kg-image"></figure>]]></content:encoded></item><item><title><![CDATA[Pose, FLIP, Animations!]]></title><description><![CDATA[<p>I've been learning to use Hooks, and I thought it'd be a good time to get my head around the popular <a href="https://popmotion.io/pose/">Pose</a> declarative animations library. Animations have always been something I've shied away from – all the imperative code is scary! – but with libraries like Pose for React, it's much easier</p>]]></description><link>https://old.bede.uk/pose-flip-animation/</link><guid isPermaLink="false">5ca37f601eae7a0569139a41</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Tue, 02 Apr 2019 16:21:34 GMT</pubDate><content:encoded><![CDATA[<p>I've been learning to use Hooks, and I thought it'd be a good time to get my head around the popular <a href="https://popmotion.io/pose/">Pose</a> declarative animations library. Animations have always been something I've shied away from – all the imperative code is scary! – but with libraries like Pose for React, it's much easier to see how they can work with a declarative programming model.</p><p>Here's some simple code, roughly taken from the Pose documentation. It animates a box from its original size to being full-screen when clicked. Except this code doesn't actually run the animation – it just snaps between full-screen and back, with no animation in between. Can you see what's going wrong with it?</p><script src="https://gist.github.com/bedekelly/cbf115e8515423034c67726362500e7b.js"></script><p>If you spotted it straight away, fair play – you're more eagle-eyed than me. It took actually rewriting the Pose documentation code line-by-line to notice the difference: I'd defined the <code>posed.div</code> <em>inside </em>the component function. Presumably that meant the library couldn't store the state it needed in order to actually run the animations!</p><p>Here's a fixed version (also hosted <a href="https://simple-pose-demo.bede.io">here</a> if you can't see the page below!).</p><iframe src="https://simple-pose-demo.bede.io" width="400" height="230">Browser does not support IFrames.</iframe>
<div style="margin-bottom: 30px;"></div><script src="https://gist.github.com/bedekelly/b3f98ceb5498e894339fadc1e453f995.js"></script><p>I also prefer the look of the animation with a <code>'backIn'</code> easing function, which is easy to apply by overriding the default transition Pose applies:</p><pre><code class="language-javascript">const Box = posed.div({
    regular: { width: '10vw', height: '10vh', flip: true },
    fullscreen: { width: &quot;100vw&quot;, height: '100vh', flip: true, transition: { duration: 200, ease: 'backIn' } }
});
</code></pre>
<h1 id="flip-animations">FLIP Animations</h1><p>In my previous post about parallax with SVG images, I described how it's a good idea to avoid animating any properties other than <code>transform</code> and <code>opacity</code>. But above, it looks like we're animating the <code>width</code> and <code>height</code> properties. What's going on here – will this perform well?</p><p>The short answer is <strong>yes </strong>– the animations above run at a consistent 60fps. Specifying <code>flip: true</code> here enables FLIP animations, which calculates the changes which <em>would </em>be made by animating width, height, top, left etc., and animates them using <code>transform</code> instead. It's a cool technique, and actually not too hard to implement!</p><p>In short, the steps are: </p><ul><li>measuring the <strong><em>F</em></strong>irst state of the animation,</li><li>measuring the <em><strong>L</strong></em>ast state of the animation,</li><li>calculating the <em><strong>I</strong></em>nverse of the changes, and</li><li><strong><em>P</em></strong>laying the animation with transforms instead – hence, FLIP!</li></ul><p>The measuring is done by inspecting the DOM using tools like <code>getBoundingClientRect</code>, and the calculations are simple subtractions and divisions: the end <code>left</code> value minus the initial <code>left</code> value gives the value to plug into <code>transform: translateX(_)</code>, for example.</p><p>But luckily, we don't need to consider any of that – Pose does all the calculations needed for FLIP animations under the hood. So we can animate <code>width</code> and <code>top</code> to our hearts' content, always remembering to specify <code>flip: true</code>. Neat!</p>]]></content:encoded></item><item><title><![CDATA[60fps Parallax Animation with SVG]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/03/Screenshot-2.png" class="kg-image"><figcaption><a href="https://parallax.bede.io">Try it out here!</a></figcaption></figure><p>I mainly made this because I wanted to try out drawing in Illustrator, but I've also wanted to try recreating Github's cursor-based parallax (seen on their <a href="https://github.com/bedekelly/nosuchrepo">404 pages</a>) for a while now!</p><p>The scene is like a super-basic version of <a href="https://cdn1.artstation.com/p/assets/images/images/000/394/353/large/tim-vizesi-firewatchfanart-001.jpg?1420762879">some art from Firewatch</a>. To make</p>]]></description><link>https://old.bede.uk/60fps-parallax-animation/</link><guid isPermaLink="false">5ca0d8de1eae7a05691399d7</guid><dc:creator><![CDATA[Bede Kelly]]></dc:creator><pubDate>Sun, 31 Mar 2019 16:02:21 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/03/Screenshot-2.png" class="kg-image"><figcaption><a href="https://parallax.bede.io">Try it out here!</a></figcaption></figure><p>I mainly made this because I wanted to try out drawing in Illustrator, but I've also wanted to try recreating Github's cursor-based parallax (seen on their <a href="https://github.com/bedekelly/nosuchrepo">404 pages</a>) for a while now!</p><p>The scene is like a super-basic version of <a href="https://cdn1.artstation.com/p/assets/images/images/000/394/353/large/tim-vizesi-firewatchfanart-001.jpg?1420762879">some art from Firewatch</a>. To make it, I mainly just played around in Illustrator for half an hour or so. I probably drew about 10 birds of varying quality – I'm no artist so I roughly copied sketches I found on Google. I could have used my iPad for this but didn't want to pay any extra for a vector drawing app, so I just settled for the trackpad. I exported every layer as SVG – there's 9 in total, including the background gradient.</p><p>(By the way – there's a cool visual effect where it seems like the birds further away are being occluded by some kind of misty fog-of-war kinda thing. But they're not a different colour, blurred or anything like that – just smaller and less detailed.)</p><p>I took a look at how Github did it under the hood, and it seems like they use a jQuery library called <a href="https://github.com/cameronmcefee/plax">Plax</a>. That's cool, and it probably does some fancier stuff than what I'm looking for, but I want to write the code myself. Also, Github's animation clocks in at around 24fps on my Macbook Pro – we can do better.</p><figure class="kg-card kg-image-card"><img src="https://old.bede.uk/content/images/2019/03/Screenshot-2019-03-31-at-16.58.52.png" class="kg-image"><figcaption><a href="https://github.com/bedekelly/nosuchrepo">GitHub's Parallax 404 Page</a></figcaption></figure><p>The advice I've heard for keeping within a tight frame budget is to <em>only </em>animate two properties: <code>transform</code> and <code>opacity</code>. Seriously. No <code>background-color</code>, and definitely no <code>top</code> or <code>left</code>. That's fine for this though – we'll just use <code>transform: translate3D()</code> and calculate some offsets.</p><p>Traditionally, to calculate what a camera sees, you'd have all sorts of matrices set up to calculate distance and camera angles and so on. But that seems like overkill – we're rendering a flat landscape here, so we can take a big shortcut in assuming the perspective is already "baked-in" to the image layers. The mountains are only about 6 birds high, for instance – not thousands, like they would be if drawn to scale. Also, we don't need to sweat the details when a lot of the image is just jagged edges of things rather than recognisable features like trees.</p><p>For this scene, I've just used each layer's index to calculate how much it should move away from its initial position. So layer 0 won't move at all, layer 9 moves the most. I take the layer index, divide by the total number of layers, then multiply by some constant value which represents the furthest distance anything can move on screen.</p><p>The code to calculate and apply the parallax is super short: I've included it in full below.</p><script src="https://gist.github.com/bedekelly/a365f83cd5e9f0d721840cc728c4fd95.js"></script><p>I also added a couple of event listeners to track the mouse position (and the device orientation for mobile, although I haven't really spent enough time on it for mobile yet).</p><script src="https://gist.github.com/bedekelly/fea6720083392e11062f0af23ecc62fd.js"></script><p>The end result is super pleasing, and super performant – it easily stays at 60fps even when dragging the mouse around like crazy!</p><p>One thing I also wanted to try was blurring the mountains slightly. CSS has  <code>filter: blur(_px)</code>, which was my first port of call. However when I applied it to the furthest mountain – even though <em>that </em>property isn't being animated at all – I saw the framerate drop to 20-30fps. Not ideal.</p><p>Fortunately, SVG has its own way of applying filters, and after a quick tweak in Illustrator, the background was blurred – and the framerate was back at 60. Great!</p><p>Side note: as well as the framerate, the load time of this little experiment is super quick. Chrome records this as getting to interactive within 100ms, which is just unreasonably speedy. I'm putting this down to using vector images instead of rasters – and just for total speed-gluttony I added a <code>gzip</code> directive to the Caddy instance serving this webpage, so even the text assets are served super-fast.</p><p>Things that probably should be different:</p><ul><li>Exporting a background gradient as SVG instead of just using CSS <code>linear-gradient</code></li><li>Translating the background layer by (0, 0) instead of just skipping it altogether</li></ul><p>But I'm not really bothered about either of them – the target is to hit 60fps and it does just that! (The browser probably optimises away zero-translations anyway.)</p><p>Have a play around with it and let me know what you think!</p>]]></content:encoded></item></channel></rss>