Notes

Tom Oliver's profile picture
Tom Oliver

I just happened to stumble across The Dandy Warhols' new song - “I’d Like To Help You With Your Problem (feat. Slash)” and its pretty good.

The music video is mostly AI generated, with all the weird/creepy artifacts and distortions you may expect. A genius move since this is exactly the dreamy, hazy, vague, feeling their music has always conveyed to me.

Its amazing how over all the years of cinema, humanities attempts to convey the sensation of dreaming have never even came close to what AI can do. As the underlying models improve, we are likely to see fewer of these hallucinations in generated content, which I find a little bit sad. I love the mental image of a giant machine, lying motionless in deep slumber, engineers prodding at the wires in its brain, hoping to influence the direction it takes as it drifts through a dream.

I like this analogy because explains why AI halucinates.
What do we call it when we halucinate in our sleep? ...A dream.

It reminds me of the anime pluto which I saw on netflix. The plot is based on our desire to create a robot with a more human mind, with scientists going to ever greater lengths to balance human-like emotions with the cold hard logic expected of machines. One scientist takes it a step too far by creating the "ultimate" robot by simulating the lives of billions of humans in its brain. But there was one problem, the robot would not wake up. It was in an endless dream. Eventually the scientist found a way to wake up the robot by forcing an overwhelming emotion into its brain, rage.

Oof, lets not do that.

Tom Oliver's profile picture
Tom Oliver

世界音痴 穂村弘世界音痴 穂村弘

世界音痴 穂村弘

明らかにペルソナじゃないけど頑張って読んでみた。 短歌について何もわからないし、調べても読めるものは一つも見つからなかった。それでもこの本はすごく面白かった。短歌と難しい日本語は通じなかったけど昔から「世界音痴」を体験してる人だから、なんとなく作者の気分がわかる。 ある部分は僕とあんまりにも似すぎて、それなりの恐怖感を感じた。このままじゃ自分も39歳になっても実家に住んでるだろうって。

読んで共感したポイントが山ほどあったけれど、特に心に響いた文のみに絞る。

(降順)

  1. 金額に合わせて小銭を揃えるという、その時間に耐えられないのである。面倒なのではない。店員を待たせている時間そのものが熱湯のような痛みを伴って感じられるのだ。そしてお釣りを受け取ると、ばっとコートのポケットに投げ込んでしまう。今度は受け取ったお釣りを財布に収納する時間に耐えられないのである。別に私の背後に客が並んでいるわけではない。せめてレシートだけでもその場で捨てたいのだが、それができない。私のポケットには財布の外側に常に大量の小銭とレシートが溢れていて気持ちが悪い。
  2. 表面が白っぽくなった大トロのパック(半額)を手にとって買おうか買うまいか、得か損か、まだまだうまいかもう腐りかけか、迷っているとき、不意に「ああっ」と叫びたくなる。「人生って、これで全部なのか」
  3. <親密さ>をそっくり残したままの、恋の終わりは苦しい。「たからもののシャツ、うちにあるよ」「うん」「送ろうか」「うん」「たからものなの?」。それは、いつもの二人の、変わりなく親密なやり取りでありながら、同時に恋の終わりの会話なのだ。
  4. 「今日こそ蜂蜜を買うぞ」「おー」と勇んで蜂蜜屋に直行する。「いらっしゃいませ」と迎えてくれた店員は人間の女性だった。棚に並んだ何種類もの蜂蜜の色は微妙に違う。中の一つに私が手を伸ばすと、「それは小心者向きでございません」と店員さんの声。驚いて瓶から手を放す。
Tom Oliver's profile picture
Tom Oliver

So this year I thought I'd start recording the books I read. Mainly so I don't get to the end of the year and think "What did I read?".


The first book that I have read this year is called:

陽気なギャングが地球を回す

面白かった。伏線回収がすごい本だった。 普通は強盗系の話とかはあんまり好きじゃないけどこの本は面白かった。 信じ難い部分も多かったけどあらすじは複雑で予想できなかったから最後まで読んで楽しかった。 いつかはまた読みたいと思った。

Tom Oliver's profile picture
Tom Oliver

First impressions of Remix vs. Nextjs (pages router)

  • Obviously Remix is the newer kid on the block, so expect library support etc. to be less comprehensive.
  • It seems that Remix has changed its routing system recently. Unfortunately many of the tutorials out there use the old one (directory based), which is confusing.
  • Remix is less of a black box than Next. You are allowed to configure the entry.client.tsx and entry.server.tsx in any way you want to. This lets you take control of exactly how you do SSR and hydration.
  • At the time of writing, Remix heavily leans into using the latest React features like renderToPipeableStream which you will see in your entry.server.tsx. Unfortunately a lot of libraries are not up to date and still use renderToString in examples, like mui. So it can take a while to figure out how to integrate all of your libraries so that they are happy doing SSR.
  • Remix is a framework who's main abstraction is the data fetching on the server side. Nextjs (page router) has a similar concepts with getServerSideProps, getInitialProps etc, but it seems that Remix's solution is more all encompassing and unifying.
  • Nextjs is in weird limbo state at the moment where you have to choose between the pages router and the app router when you create your project. This is fine if you are sure exactly what feature you need, but in the case where you don't really know, Remix might be a safer bet.
Tom Oliver's profile picture
Tom Oliver

Nx hanging

Ok I'm using Nx as a monorepo manager for a project and got into to some very strange behavior. There are several node apps in the repo and to run them, you use npx nx serve <my-app-name>. Sometimes tho, after updating an npm package I would get an error like:

LOCK-FILES-CHANGED
please restart nx daemon using `nx reset`

Unfortunately I couldn't reproduce the error message exactly at the time of writing, so this is the best I could remember.

Anyway, no matter how many times I run nx reset, my npx nx serve commands would just hang. Zero output at all. As I suspected the daemon, I tried to view its logs. To find out where the log file was I did:

$ npx nx daemon
Nx Daemon is currently running:
- Logs: /home/tom/Documents/project/node_modules/.cache/nx/d/daemon.log
- Process ID: 33785

But when I tried to cat the log file it apparently did not exist!

So presumably the daemon was in some kind of infinite death loop... I never got to the bottom of the cause, but did manage to find a solution.

There is an environment variable that disables the daemon because its more of a performance optimisation than a critical feature. So now I just export NX_DAEMON=false and everything seems to work ok.

If you use a nix devShell like me you can just add it to the shellHook like so:

NIX
...
devShells.default = pkgs.mkShell {
shellHook = ''
export NX_DAEMON=false
'';
};
...
Tom Oliver's profile picture
Tom Oliver

Have you heard of semantic Javascript ?

You probably answered "No" because I just thought of it 😇

Everyone knows they should be writing semantic HTML but why not apply the same standards to a "real" programming language.

Semantic programming is all about using the constructs a language provides in such a way as to convey intent to the target audience, whether that be human or machine. In HTML we have the classic example of using the <footer> tag instead of just spamming <div> everywhere. Lets apply that logic to Javascript.

Here's some non-semantic JS.

1
ah, a for loop, I wonder what it does.
2
I have to look inside the loop to find out that we are transforming each element.
JS
let arr = [1, 2, 3]
1for(let i = 0; i < arr.length; i++) {
arr[i] =2arr[i] * 2
}
1
ah, a for loop, I wonder what it does.
2
I have to look inside the loop to find out that we are transforming each element.

now for something semantic

1
This one word tells me that we are transforming each element somehow, without me having to read any further!
JS
// we are doing the exact same thing as before, just better.
let arr = [1, 2, 3]
arr = arr.1map((x) => x * 2)
1
This one word tells me that we are transforming each element somehow, without me having to read any further!

I think you get the idea...

But just in case, here is another scenario...

1
Not sure what this while loop is going to do
JS
1while(i < arr.length) {
...
// do some operation
res = ...
}
1
Not sure what this while loop is going to do

Compare the above to this:

1
This word means we are going to combine the array in some way.
JS
let res = arr.1reduce((acc, cur) => {
...
// do some operation
},{})
1
This word means we are going to combine the array in some way.

So.. what do you think?

Ok, maybe this is just an excuse to get you to do some functional programming.

You got me! 😘

Tom Oliver's profile picture
Tom Oliver

Here's how to burn audio to a CD from the command line.

SHELL
# Remove spaces from filenames
for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done
# Convert all tracks to wav
for i in $( ls ); do ffmpeg -i $i $i.wav; done
# Normalize the volume across all tracks
normalize -m *.wav
# Burn to disk
sudo wodim -v -dev='/dev/cdrom' -audio -pad *.wav
Tom Oliver's profile picture
Tom Oliver

So this is one of the first times I have actually come across a hurdle when it comes to developing software on old computers. A couple days ago I started experimenting with bun, which is amazing by the way. One of the big selling points is that it is really fast, but this speed seems to come at a cost...

As I use NixOS, I installed it the usual way by adding it to my configuration.nix. But alas, life isn't always simple. It seems to install ok, but when I tried to run bun I got an error immediately:

SH
illegal hardware instruction (core dumped)

Wow an actually hardware error! I haven't seen one of those since I was trying some overclocking! So the problem comes down to the fact that bun uses some cutting edge CPU instructions that weren't around in 2012. Now, on other Linux distributions you can simply use a bash script to install bun à la:

SH
curl -fsSL https://bun.sh/install | bash

Apparently it checks your CPU and in the event it finds something of a certain vintage it installs a baseline version of bun which I guess doesn't use any of the funky CPU instructions it would usually. Unfortunately the nix package does not at the time of writing do this. There is actually a PR open to fix this but it has not been merged yet. So for the time being you can basically just take the code from the PR, save it to a file locally and build the baseline version yourself.

  1. Download and save this file.
  2. Now to build is, run:
SH
nix-build -E 'with import <nixpkgs> {}; callPackage ./default.nix {}'
  1. You should now be able to run bun by doing:
SH
./result/bin/bun
Tom Oliver's profile picture
Tom Oliver

I witnessed this absolute corker of a bug in the office today.

After a force reboot (its a long story), we noticed that the cursor was flickering on my colleague's Ubuntu laptop. After some googling, we realised that this flickering only happens at 200% fractional scaling. Setting to any other value like 175%, 150% etc. works perfectly fine.

https://askubuntu.com/questions/1234189/cursor-flickers-on-primary-display-when-fractional-scaling-is-enable-for-dual-mo

Despite the link above being more than three and a half years old, it appears that even today, this bug can still be observed in the wild, in its natural habitat, on Ubuntu.

Tom Oliver's profile picture
Tom Oliver

It's taken me far too long to discover this foot-gun in express.

I started a new express project the other day and realised that my request bodies were all empty! Spent a good hour thinking it was a problem in the client or the proxy etc... but was actually just because I forgot to apply these two middlewares.

So the question is, why are these middlewares not enabled by default????

JS
const app = express()
// this populates req.body when the payload is json
app.use(express.json({ type: "application/json" }))
// this populates req.body when the payload is urlencoded
// (e.g when a form gets submitted)
app.use(express.urlencoded({ extended: true }))
...

Sensible defaults are just something we don't deserve I guess...

Tom Oliver's profile picture
Tom Oliver

Optimistic VS Pessimistic Locking

Imagine you are on a plane and you need to pee. You're a stubborn guy. When you leave your seat, you are determined to pee one way or another. You must assume your fellow passengers are as least as stubborn.

Optimistic Locking

There is a single toilet located in the middle of the plane that can be accessed from multiple directions. You are sitting at the back and can only see the entrance to the toilet that is in your direct line of sight. You want to know if its ok to go to the toilet so you check the overhead light which says "vacant". Assuming that it will remain vacant for the entirety of the time it will take you to reach your destination, you get out of your seat and commit to peeing. Now one of two things are going to happen:

  1. The toilet is vacant by the time you get to it - Success
  2. Someone else has slipped into the toilet via an entrance you couldn't see during the time it took you to walk there. Since you have committed to peeing, you have no choice but to do so in a cup - Failure.

Pessimistic Locking

Due to your toilet paranoia you reserve a seat on a specially designed plane. It is designed such that each seat is directly adjacent to a toilet and has excellent visibility of all its entrances. Because of this, you are able to in a single instant, both check that a toilet is free and enter it. It is therefore guaranteed that you nor any other passenger will be forced to pee in a cup.

So obviously there is a dilemma here.

The specially designed plane will carry less passengers due to its emphasis on providing the stubborn peeing passenger peace of mind. The normal plane will be more efficient but has to account for the occasional cup of pee getting knocked over.

What have we learned?

There is no "correct" way to design a plane, only trade-offs.

Tom Oliver's profile picture
Tom Oliver

Some lesser known nice things about Japan 🗾

  • Ambulances are loud, but not too loud.
  • When Police cars do unexpected things like making a U-turn suddenly, they politely inform everyone nearby with a megaphone.
  • When large vehicles make a turn near a pedestrian they play a vocal warning "Watch out! I'm about to turn left!"
  • Dog owners carry a bottle of water to wash away any pee the dog might do on a walk.
  • There are lots of outside gyms.
  • There are lots of summer festivals which aren't exclusively an excuse to get drunk.
  • Its not okay to be ugly.
    • You better look your best if you're thinking about leaving your home.
    • Foreigners usually get the benefit of the doubt.
  • Lots of stuff made in Japan for Japanese people only. (Films, cars, appliances...)
  • There is one and only one right way to do everything.
    • If you order something in a cafe or a restaurant, chances are they'll tell you the right way to consume it.
    • e.g. You order an iced coffee creamy thing from a local cafe.
      1. First taste the top and bottom layers independently before mixing them both together with the straw...
  • There is a lot of wildlife everywhere.
    • Probably more wildlife in Tokyo than in any National park in the UK.
  • There are dry ice machines in some supermarkets.
  • Some cars have a horn? that says in a polite voice "Please watch out, a car is passing by!" to unsuspecting pedestrians that haven't noticed.
  • Relaxing background music automatically starts playing the instant your skin comes into contact with the toilet seat.
  • Safety first
    • At petrol stations there is an "anti static electricity pad" for you to touch before filling up your car.
  • The sky is big. Power cables on a hot sunny dayPower cables on a hot sunny day
Tom Oliver's profile picture
Tom Oliver

Its been a while since I did any data modelling in typescript.

TS
// An example of a user management system
// Define user status type, just an enum
type UserAccountStatus = "ACTIVE" | "DORMANT" | "DELETED"
// Define a base type
type BaseUser = { name: string; status: UserAccountStatus }
// Create concrete types using the base type
type ActiveUser = BaseUser & { status: "ACTIVE" }
type DormantUser = BaseUser & { status: "DORMANT" }
type DeletedUser = BaseUser & { status: "DELETED" }
type User = ActiveUser | DormantUser | DeletedUser
// Create the type of function we want to implement
// Make return type a promise because we talk to the DB
type DeleteUser = (user: ActiveUser | DormantUser) => Promise<DeletedUser>
// do a temporary implementation of the function
const deleteUser: DeleteUser = (user) => {
const deletedUser: DeletedUser = { ...user, status: "DELETED" }
// define a helper that we haven't got yet
return writeUserToDB(deletedUser)
}
// declare the type of the helper like so:
declare function writeUserToDB<A extends User>(user: A): Promise<A>
Tom Oliver's profile picture
Tom Oliver

Bought some books with the intention of learning Chinese but yeah its pretty hard.
As long as I don't give up completely I might be ok at it in the region of say... a decade?
Which is really not too long when you think about it.
So I guess nothing to complain.

Tom Oliver's profile picture
Tom Oliver

This was super helpful for implementing webmentions on my site! Thanks!

Tom Oliver's profile picture
Tom Oliver

Oh, looks like I have to paste the link explicitly for it to work.

Anyways, here it is:

https://blog.rubenwardy.com/2022/03/17/plant-monitor/

Tom Oliver's profile picture
Tom Oliver

Not as cool as this post right here am I rite m8s??? 🌳💻🎉

Tom Oliver's profile picture
Tom Oliver

So this is what shouting into the void feels like...

Hello, this is my first "note".

Probably not going to write too many until I'm sure I have web mentions all working.