Less Consuming, More Creating

Mike Crittenden posted a good quote from a random Hacker News commenter:

Less consuming, more creating.
Doesn’t matter what it is, doesn’t matter if it’s bad.

This quote actually sums up this blog quite nicely. The first line explains why it came to exist. The second line describes how it continues to exist.

Happy 1,000th post.

Ballarat Beer Festival 2023

My friends and I returned to Ballarat today for the Beer Festival. It was another stunning day for it: sunny, mild, not too hot. Much like last year I took an earlier train to walk around Ballarat a little. Not much to report here: very little has changed. But I never see Ballarat so it’s good to walk around a little. My friends were on the train behind mine and I caught up with them when I boarded at Ballarat. We then made our way to Wendouree park for the festival.

We were given a plastic pot when we entered and brewers typically offered either a tasting size, a half pot, or a full pot of a particular drink. Half pots are usually the best value for money: you get a decent amount to enjoy but you pace yourself and avoid reaching your limit before you tasted everything you wanted to. I made that mistake last year: buying too many full-sized pot servings. I went half pots this year.

I also made the mistake of not making notes of the beers I tried last year. I made sure to record them this year. Given the occasion, I decided to go for drinks that I wouldn’t normally go for. In other words: lots of sours today. I’m not a sour drinker and I think I eventually reached my enjoyment limit of them today. But that’s fine: I guess it’s good finding my limits this way.

Here’s a quick rundown of the drinks I tried:

  • Fox Friday “Feeling Peachy” Fruited Sour: This was less sour and more on the bitter sweet side. The peach flavour came through strong, which took the edge off and made it quite refreshing. Made for a nice starter.
  • Dollar Bill “Australian Wild Ale”: This was a regular ale and a little more bitter than I was expecting (although that could’ve been because of the peach sour). It felt like a heavy sort of ale. Maybe a little too heavy for me. Not sure it’ll be something I go for again.
  • Mountain Culture “MS DOS” West Coast IPA: Nothing too remarkable about this. Just an IPA. But a decent IPA. Will definitely have again.
  • Wild Life Citrus Sour: I can’t quite remember the make up of this sour. I think it was lemon and blood-orange. Definitely something and blood-orange, as the blood-orange taste really came through. I didn’t think much of this but that’s probably because I reached my limit for sours at this point. This brewery was also advertising a “pineapple sour,” which would’ve been amazing, but sadly they weren’t pouring it when we arrived. Might have affected how I thought about the blood-orange drink: feeling that it was playing second fiddle to the pineapple one.
  • Prancing Pony “10 Year” Beer: This was one my friend got but he offered me a taste of it. It was a pilsner IPA but more on the pilsner side. It’s probably one I can see myself drinking if it wasn’t for it’s alcoholic content. It was quite high: 7.5%, or 3 standard drinks in a 500 ml can. That’s just a little too high for me. The can was quite something though.
  • Molly Rose “Strawberry Sublime”: This was a low alcholoic strawberry and lime gose. A bit of a mix of sweet and sour. It was nice, but it really wasn’t doing it for me, and frankly I’m not really sure why I went for it at this point in the day.

The event was back in Wendouree park, and was pretty much like last year. Which is good: they did a good job last year.

But there were a few small changes this year. For one, more tables were placed under the trees, which was a good move. There were more tables in the sun last year, which never had anyone on it for long as people preferred the ones in the shade. I think there were fewer brewers this year too. It might have been because of the layout change but it felt a little smaller this year, and some brewers from last year didn’t make an appearance.

Also, no finska this year.

But all in all, it was a good day. Good excuse to get on a regional train out to the country for a change.

Very hot today. Mercury hovering just under 40°C, with every chance that it may get hotter than that. But you know what? I rather it be hot today than tomorrow. Why? You’ll find out tomorrow. In the meantime… cheers! 🧊☕️

A home-made ice coffee on a kitchen bench

🔗 From Bing To Sydney

Hmm, it’s hard not feeling a little unsettled after reading this Stratechery post. One thing’s for sure, I’m a bit more doubtful of the post I wrote two days ago.

Anyone making a software tool that converts times between time-zones, please let me enter the time-zone as an offset from UTC.

Something that only accepts time-zone abbreviations or city names are problematic. For one thing, zone abbreviations are location specific. Dealing with technology mainly developed in the US, I’ve got into the habit of writing AEST when I want Australian Eastern Standard Time. But I wouldn’t bat an eyelid if I saw one of my compatriot use EST to mean the same thing. Is your tool smart enough to recognise this, or will it just default to US Eastern Standard Time?

Now granted that’s one that’s got a work around. But let’s say I want to know the time on Low Howe Island. I’d probably use LHST for that, but does that mean “Lord Howe Standard Time” (UTC+10:30) or “Lord Howe Summer Time” (UTC+11:00)? Both of those abbreviate to LHST, and your tool will need to be smart enough to know the particular date and whether or not summer time is in effect. If you think you can handle that edge case, take a look at the list of time-zones abbreviations on Wikipedia to see how you’d be able to handle BST.

What about city names? Yeah, city names might work, but you have to make sure your tool knows of every city out there. I’ve been trying to use Numi to convert from Melbourne time to Apia time. The docs seem to suggest that typing in 13:00 Melbourne time in Apia should work. But as far as I can tell, it doesn’t seem to recognise this as a time-zone conversion expression. It seems to give up and just give me 1:00 pm the answer, possiably because it doesn’t know about Apia1. I’m wondering if it even knows about Melbourne (I don’t know what each of the colours mean).

Numi session with an attempt to convert 1:00 pm in Melbourne to Apia time, and the result is 1:00 pm when it should be 3:00 pm.

And let’s not forget the issue of multiple cities having the same name. Melbourne could refer to Melbourne, Australia or Melbourne, FL, United States. I’d like to see how your tool handles Portland (keep in mind there’s a Portland in Australia as well).

So, please. Make it easy on everyone, including yourself, and just recognise UTC±xx:xx. It would be so much easier and less ambigious if I could just to 13:00 UTC+11:00 to UTC+13:00. Or whatever, pick a syntax that works for you.

And if you do have support for this, please make sure you document it somewhere.


  1. Apia is the capital of Samoa ↩︎

Ignoring Bard to Speak to Paulie

So this happened today.

Our team was testing the integration between two systems. The first system — let’s call it Bard — can be configured to make API calls directly to Stripe, or be configured to use the second system — let’s call it Paulie — to call Stripe on it’s behalf. Bard has a REST API that is used by the HTML front-end to handle user requests. Paulie is designed to be completely isolated from the front-end and has a simple gRPC API that Bard calls. Whether or not it Bard calls Paulie at all is determined by the value of an SSM parameter.

The test was setup with Bard configured to bypass Paulie and make calls directly to Stripe. The way we were to verify this was to tail the logs of both Bard and Paulie, make a REST-API call, and confirm that logs showed up in Bard but not Paulie.

I got called by those running the test to help, as they were seeing something unusual: when the test was performed, logs were showing up in Paulie. The system was configured for Bard to ignore Paulie and go directly to Stripe, and yet Paulie was being spoken to.

So we started going through the motions. We checked to make sure we had the correct version of Bard deployed, checked the SSM parameter, traced through the code, restarted Bard a couple of times to make sure it was configured correctly. And after every check we tried the test again, to nothing changing: logs will still coming through from Paulie.

We were at it for about 15 minutes. I was staring to go through the more esoteric explanations for why this was happening, like whether we were using SSM parameters incorrectly and we may have been using an old configuration or something. Then as I was going through the traces one last time before giving up, I noticed something: there were no traces from Bard. This REST-API it had did all sorts of things like contact the database before going to Paulie or Stripe so I was expecting something like that to show up. Yet there was no evidence of any of that happening.

I then asked how this was actually being tested. And you can probably guess what the response was. Turns out the person running the test wasn’t using Bard’s REST-API at all, and was making gRPC calls directly to Paulie.

Well, naturally, if you called Paulie directly without calling Bard, it doesn’t matter what Bard is configured to do. 🤪

Now, I don’t write this because I’m angry or annoyed. In fact, I came away from this feeling very zen about the whole thing. Mistakes like this happen all the time, it’s fine.

But it’s a perfect opportunity remind myself that working on tech can sometimes give you tunnel vision, and that sometimes the explanation isn’t technical at all. Sometimes the answer is much simpler than you think.

🔗 ChatGPT clearly has a place

I tried ChatGPT for the first time this morning. I needed a shell script which will downscale a bunch of JPEG images in a directory. I’m perfectly capable of writing one myself, but that would mean poking through the ImageMagick docs trying to remember which of the several zillion arguments is used to reduce the image size. Having one written for me by ChatGPT saved about 15 minutes of this (it wasn’t exactly what I wanted, I did need to tweak it a little).

A ChatGPT session where I ask for a script that reduces the size of JPEG files in a directory.

I don’t know what the future holds with AIs like this, and I acknowledge that it has had an effect on some peoples’ living (heck, it may have an effect on mine). But I really can’t deny the utility it provided this morning.

Flights and accomodation for the Europe trip booked. It’s been hanging around my to-do list for the last two months. Good to finally check that off.

I suspect, in a world where companies are replacing staff with AIs, that the organisations that choose to keep the humans on will have the competitive advantage. You can’t form a connection with a machine.

New Stuff Setup Weekend

A bunch of new stuff I’ve bought has arrived recently and this is the weekend I finally get around to setting it up.

New Furniture

The largest one is a new couch. I’ve been sitting on a second-hand two seater that my parents gave me when I’ve moved out. It did the job but it was getting quite old and saggy, and I’ve been finding myself wanting to have something larger that I can lie across. So about six months ago, I bought a new couch. It was meant to come last December, but got delayed thanks to Covid-19 supply chain issues. But it finally arrived this Saturday.

But before it can be delivered, I had to prepare the way, as they said. I did that on Friday, moving the old couch around to make space for the new one and also taking the opportunity to clean up a little.

An empty space where the new couch will go, with the old couch to the right, beside the bookcase
Preparing the way for the new couch. The old couch is temporarily beside the book shelf.

The placement of the old couch is a little awkward, but it will only be for about a week and a half before it leaves my house.

Delivery time was between 10 and 12 on Saturday morning, and it was near the end of the delivery window when the movers eventually arrived. There was some concerns about getting the couch through the door but they managed to do so by standing it up on its side and sliding it through.

The new couch placed in the living room. The couch is a maroone reclying three seater
The new couch.

The delivery went smoothly, but I wouldn’t call it a great “first launch” experience. Apparently it’s policy not to take all the packing material, which means it’s something I have to deal with. It’s not a huge problem, and it’s not the first time I had to get rid of waste over several weeks, but it did take the shine out of enjoying a new piece of furniture.

A pile of packing material waste in the living room
All the waste I need to sort and throw out.
A wooden board propped up against a wall
Most of the waste is plastic and cardboard, but there's also this wooden board. I'll probably keep this. Might be useful in the future.

But that aside, it’s great having a new couch. One interesting thing about the long time gap from purchase and arrival is that I forget how it felt trying it out in the store. It’s firmer than I remember and the height of the seats are a little short. It’s feels like a whole new experience from scratch. But I expect I’ll get use to it over time. And it’s not like I didn’t realise these properties when I actually tried it out during the shopping phase.

All in all, I’m really happy with it.

New Electronic Devices

Today (Sunday) was all out electronic devices, starting with a new M2 Mac mini.

A M2 Mac mini in its box
The new M2 Mac Mini

This will replace my 2018 Intel Mac mini, which will become a home server. This is actually the first Apple Silicon computer I own. I’ve been using a M1 MacBook Pro for work for a year and a half, and I’m reasonably confident that the M1 chips will handle the type of things I’d like to run.

Going through the setup was pretty seamless. I tend to start all new machines from scratch, meaning I don’t migrate anything over. Since the old Mac mini will be still around, I’ll move projects and documents over to the new Mac over time.

The one thing that didn’t work out as well as I expected was my USB audio interface. I’ve been using a Roland Quad-Capture as my audio interface and while I was getting ready to move to the M2 chip, I did a search to see whether Roland had drivers that worked with Apple Silicon. At the time I thought they did, but when I tried installing them they didn’t work at all. Another look today confirmed that there was no driver support the M2 chip.

This was a bit of a setback. I think next time I make sure to actually do a search for “thing M2 support” instead of just browse the driver download page and infer support for something when it doesn’t explicitly say “does not support M1 Macs”. It would also be helpful to remember that MacOS 10.X does not equal MacOS X. 🤦

Anyway I’ve got another audio interface on the way. It’s another Roland product, since I think something designed for music production means the device will be able to handle low latency audio. I also need something with MIDI since I do occasionally use it for music production. This new one uses the built-in MacOS audio drivers so hopefully I don’t need to worry about driver support going forward.

Apart from that, I’m still in the process of setting the Mac up. It always feels a little strange moving to a brand new machine. It’s like moving house or going to a holiday let: everything its new to you, you need to find out where things are, and none of your old things are there. But it’s also a good opportunity to form a few new habits. For example, I may try using Safari as my browser instead of Vivaldi, and start using Mac-Assed Mac Apps like NetNewsWire in lead of web-apps. I might be a little more judicious about keeping my Download folder cleen as well. I saw a cronjob that will remove things in that folder after a week. I’ll give this a try and see if a clean Downloads folder works for me.

The last bit of kit is a new Smart Keyboard Folio case for my iPad.

An iPad Smart Keyboard Folio in its box
The new Smart Keyboard Folio

I finally bit the bullet and replaced my old keyboard folio with a new one. The keyboard was completely non functional in the end and the lining was starting to peel off, so it was probably time for a replacement anyway.

An old Smart Keyboard Folio, with the top lining starting to peel off
The "retired" Smart Keyboard Folio. Notice the lining above the keyboard starting to peel off.

I’ve only tried the new one for a few minutes as I was looking up passwords and setup instructions for the new Mac. So far it’s working well. The only concern I have is that I’ll have to go through this again in three years time.

So that’s all the new stuff I got setup this weekend. Most of the setup will continue over the next few weeks, especially the new Mac, but I’m happy I got the most of it done.

Spotify Video Follow-up

Some follow-up from my post about Spotify videos. I looked into this a little and from what I understand they’re not full videos but “short looping video clips that play during certain songs,” at least according to this website.

So I guess my initial belief is incorrect. Spotify might have music videos (they’re a bunch of articles about them thinking about it in 2020-21) but this looks to be completely different.

Furthermore, you can turn them off. They’re called “Canvas Video Clips”, and if you go into the preferences of the Android mobile app, sure enough there’s a switch for them.

Spotify preference screen with the toggle for Canvas visualisations enabled

Not sure why I missed that when I was looking for that option earlier. I guess because I was looking for a preference with the name “video” in the label. But this switch seems to work and after I turned it off, this visuals stopped.

Still toying with the idea of cancelling my subscription for other reasons but at least this is one less concern I have for using the service.

I just realised there’s a downside to cross-posting my Micro.blog posts to Mastodon: I can’t use hashtags ironically anymore. Not that I’m in the habit of doing so, but the occasional one would be nice.

Hmm, how to adapt? £thinking

Computers may have bested humans in Go but we still hold the advantage when it comes to Go. 😉

(Although for how much longer is still an open question)

Toying with the idea of cancelling my Spotify subscription. There are a number of reasons for this, but one that really gets to me is the insistent need to show video when playing a song. And there’s no way to turn it off anywhere (I tried looking for one).

I listen to music when I’m walking or driving or doing something that needs my visual attention. But even if I am in a position to stare at my phone, I don’t want to be watching music videos. So why is my bandwidth being wasted streaming a video when an MP3 will do?

So obnoxious it borders on being offensive.

Trying out Keyboard Maestro to automate some niggly things I occasionally need to do. Got my first macro working, which converts a selected string FromCamelCase to UPPER_SNAKE_CASE.

Screenshot of a Keyboard Maestro macro which converts the selected string from CamelCase to UPPER_SNAKE_CASE

So far I’m impressed. Looking forward to finding other things I can automate away with this.

I don’t know what I need to do to get Swift Packages working.

It never seems to work for me. The option to add dependencies are in the menu, but when I try to use them, they error out or cannot resolve the dependencies for some reason.

This is in addition to not being able to see or edit “Package.swift” as a text file, which I thought was the whole thing with this.

Is it the version of Xcode I’m using? Does it work for anyone outside of Apple? Libraries are being released with Swift Package support so it must work for someone.

Read my last post during lunch to see how well it read. Couldn’t get past the third paragraph without thinking: wow, this is really boring. Rewriting it helped a little, but it’s still rather dull. Maybe it’s the topic?

In either case, it’s something I need to work on. 🧑‍💻

On Higher Order Functions In Go

It’s a bit surprising that higher-order functions like map and filter have not caught on in Go.

They seemed to have caught on quickly when they were added to Java. One of the long standing issues back then was the clunky and verbose approach to writing closures. Java 8 fixed this with the introduction of the lambda (the -> operator). Suddenly, what once took multiple lines of boilerplate could be done in a single expression. The underlying mechanism was still the same but the new syntax was enough to get people to use it (amongst other things, read on).

I don’t see that in Go. With generics in Go 1.18 reducing the need for interface{} and type assertions, I would have expected the tide to turn a little: more maps and filter functions, and way less for loops. But it hasn’t seem to happen yet. I still see those same for loops that I’ve been seeing over the last eight years.

I’m not sure of the reason but I can guess I could be explained by two things.

The first is Go’s culture. And yeah, you could describe Go as having a culture1. It’s one that’s quite conservative and methodical. Fancy ways of doing things that sacrifice readability in favour of terseness is usually frowned upon. It’s proper to make sure the code is clear, even if it takes more room on the screen.

The culture comes through in the design of the Go language itself. A classic example is the use of the error type rather than exceptions. And I think it partly explains why higher-order functions have not caught on. It’s not because you can’t do it. At least you had proper closures in the language, which is something you couldn’t say about Java, back in the pre-1.8 days.

But I don’t think culture is enough. You couldn’t say that using higher-order functions in Java 1.6 was a big thing back then either2. What got them moving so quickly?

This is where I think reason number two comes in, which is the lack of standard library support. When Java 8 came out, every collection type was retrofitted with a bunch of higher-order methods which made it trivial to map, filter or reduce anything you need. There was event a new streams package, allowing you to build pipelines that are nothing but higher-order methods. All of this was useful and fun to work with, and people naturally wanted to use them.

Nothing like this existed when Go 1.18 was release. Nothing like this is in the upcoming release of Go 1.20.

Now, to be fair, this is very characteristic of how Go maintainers add features. They take their time, making sure not to break backwards compatibility or locking themselves into a design that is difficult to evolve. And I understand the reasons for why they want to go slow here. But that means that an “official” package of higher-order functions will take time to be ready. And no such package exists now. Sure, there are open-source and experimental ones out there, but would you be using those for any production level code? Maybe adding one more for isn’t exciting, but at least it doesn’t involve another dependency (and you’re already using for loops in several of your other functions anyway).

So I guess I’ll need to wait a bit longer for higher-order functions to be more of a thing. I can’t say I’m not disappointed: one of nice things about working in a language like Ruby, JavaScript, or even Java itself, is all the higher-order functions they have. I’m still hopeful that they will come eventually. After all, generics are only a year old. And Go as a language may move slowly, but at least it’s still moving.


  1. Maybe another way to put it is a “way that things are done.” ↩︎

  2. Unless you’re writing Android apps, in which case you’re forced into a culture of anonymous classes for all the callbacks you need to write. ↩︎

Spent the last week updating my travel blog a bit. Started writing about the the trips around the south pacific I took for work almost 10 years ago. I’ve been wanting to write about this for a while, before I forget most of it. I’m glad that I’ve finally got around to doing so.

A watched kettle never boils, and a watched clock will not get the train arriving sooner (sadly).