Christian Scott

I work as a frontend infrastructure engineer at Canva in Sydney, Australia. You can see some of my work on github, follow me on twitter, or send me an email.


What’s the difference between a Rust char and a Go rune?

Rust and Go have similar ways of dealing with UTF-8 encoded text. Rust gives you the .chars() method on strings, which returns a sequence of chars (no surprise). Go on the other hand gives you []rune(str), which returns a slice of runes. What’s the difference between these two things? The answer is that a char is a Unicode Scalar Value, whereas a rune is a Unicode Code Point. That is… not very helpful. Read more

What percentage of hacker news readers block trackers?

Last night I submitted a post of mine to hacker news called “Making rust as fast as go”. It was rather popular – I’m not sure what the highest position it got to was, but I saw it hit at least the number 3 spot. I have two analytics providers set up on my site – google analytics, and netlify analytics. They each collect data in quite different ways. Google analytics tracks via an embedded javascript snippet, whereas Netlify tracks page views on the server. Read more

Making rust as fast as go

Update: as some keen HN commenters have pointed out, it looks like the rust program is not actually equivalent to the go program. The go program parses the string once, while the rust program parses it repeatedly inside every loop. It’s quite late in Sydney as I write this so I’m not up for a fix right now, but this post is probably Fake News. The perf gains from jemalloc are real, but it’s likely not the allocators fault. Read more

Is mobx magic?

When I was first introduced to mobx about a year and half ago, you probably could have convinced me that it was magic. The idea that my react components knew how to update when I mutated properties on an object was bizarre. Since then, I’ve been introduced to a few techniques and javascript features that made it click. I don’t know how mobx actually works, but I can now see how it’s possible. Read more

Estimating the answer to a hard puzzle

Some coworkers and I were having a crack at the following puzzle a few weeks ago: Consider a party with N people. Everyone writes down their name on a piece of paper and throws it in a bag. We shake up the bag and each person draws one name from the bag. You are in the same group as the person you drew. What is the expected number of groups? Read more

Big Red Buttons

A lot of “good advice” that’s easy to internalise is also easy to ignore. A classic example of this is “correlation does not imply causation”. Every nerd worth their salt knows this, but falls victim to it all the time. This bloomberg article is a classic example. It claims that moving overseas when you’re young boosts your salary. Young people who have moved overseas may have higher salaries, but there’s no reason to believe that the moving caused their salaries to be higher. Read more

Avoiding race conditions in JS

Race conditions?! Javascript?! It’s a real thing, I promise! Let’s say you have some service that loads a User object from your API. You back the getById method with a cache because you’re a responsible developer, and you share a single instance across several locations in your app because you want those sweet, sweet cache hits. UserService might look something like this: class UserService { private readonly userCache: Map<string, User> = new Map() async getById(id: string): Promise<User> { let user = this. Read more

Bytes, Code Points and Grapheme Clusters

Let’s talk about text. Specifically, text encoded using utf8. How many characters would you consider to be in the string 'a'? What about 'é'? $ node > 'a'.length 1 > 'é'.length 1 I’d say that this lines up pretty closely with what I expect. There’s some trickery going on here through, which can be revealed if we use the Buffer object in node, which is populated with each of the bytes in a string: Read more

Garbage Collection Hook in Python

Credit to Jake VanderPlas for triggering this discovery with this tweet. Turns out there’s a data model method (aka dunder method) that’s called when an object is deleted in python. This includes when the object is garbage collected. We can expand on the thing Jake was trying to do in the above tweet by decrementing the instance count in the “destructor” method class InstanceCounter: _num_instances = 0 def __init__(self): InstanceCounter._num_instances += 1 def __del__(self): InstanceCounter. Read more

Breaking down "A monad is just a monoid in the category of endofunctors"

“…just a monoid…” Associativity is a property of some binary operations where the order of operations does not matter, e.g. since addition is associative,(a + b) + c = a + (b + c) A finitary operation is an operation with finite arity An algebraic structure is a set A together with a collection of finitary operations on A A semigroup is an algebraic structure with a single associative binary operation. Read more