Quadrotor Ball Juggling 2010-12-08
Quadrotor ball juggling : Autonomous drone helicopter playing keepsie-upsies with a ping-pong ball
Quadrotor ball juggling : Autonomous drone helicopter playing keepsie-upsies with a ping-pong ball
The New Pornographers are in the UK this week, playing Bowlie 2 , and more pertinently a show this Thursday , at what is apparently now called the O2 Shepherd's Bush Empire . What is more exciting is that this is their first time over here with Neko .
Here's a lovely interview with Carl about it. I have a ticket for Thursday night in my INBOX.
One of the things I initially missed most, when shifting from emacs to zed was magit, which has been my main git interface for IDK, let's say about 20 years 🤷.
I'm a bit of a sloppy worker, but a meticulous git user, lots of atomic annotated commits, many linear branches, I'm cherry picking and rebasing, and stashing, and magit integrates all of this naturally into the normal flow.
Zed has git integration, obviously, but it's entirely basic - pull, push, commit, branch, diff, that's about it. It does let you stage incrementally, which is most of the problem solved, and of course, there is a terminal integration, so you can pop a shell and use git CLI (like a farmer 🤪).
It's OK, but clunky, obviously. A little bit of friction and dissonance in this slick world of modern native editors that were actually made this century. I think the kids are a lot looser with git than I am, and perhaps they have a point, but I like the discipline.
You probably figured out what's coming next, if you bothered to read this far.
I've been using the zed LLM integration to write commit messages for a while - it's pretty well suited to that, given a bit of context, you can generate a draft commit message that summarises the changes, and it's you tweak and approve them before you apply. It's a pretty good example of the kind of low-hanging, small improvement, you can achieve with even simple model, precisely applied to a narrow context that involves generating prose. Smoothing out busywork.
Obviously, zed is pretty agentic 🤢, because that stupid word is all the rage these days. I guess you can open a chat box and ask your editor to vibe code your whole application. (Good luck with that, if you do, I think that's liable to create more work in integration than it saves in writing, maybe that's just me)
I use the agents for a bit of boilerplate here and there - refactor this, replace these magic numbers with proper constants, redo this part to use an iterator, what is the type checker complaining about here, how do I configure the language server to disable a misfeature, again, it's not too bad at doing think kind of drone effort, and there is a small but appreciable productivity gain to be had.
This last week, I was suddenly inspired to cross the streams, and something interesting happened, surprising me enough to bother drafting a post on the topic. I don't really like to thought-leader, but occasionally something will delight me enough to want to share.
I wanted to tidy up a messy WIP branch that collected a couple of different ideas in progress, (and had also coincided with me correctly figuring out how to enable auto-linting in zed, so I suddenly had a lot of aesthetic formatting corrections dropped suddenly into an already untidy sandbox)
A minute or two fiddling with rebase in magit, but in zed...? Time to roll up my sleeves, and flex, and take out the ol' git pitchfork, or hitch up the rebase propagator to the reflog tractor (I do not really know what farmers do). But, wait. I wonder if...
So I pull up the agent and ask it "can you run an interactive rebase on this branch please, and group all the white-space only changes into one commit, the other formatting changes into another, and then separate the removal of the obsolete class from the other feature work?"
And, it kind of worked! It got stuck a couple of times, and I had to pop in and edit a couple of things, and I restarted it over with the order of the commits I wanted a little more explicitly instructed once I recognised where the conflicts were going to land, but I got the result I intended, certainly with no more fiddling about than I would have had to do if I'd been performing the task manually, maybe less? It's hard to measure, but I enjoyed the experience.
One thing I definitely realised. It was less irritating. I was able to complete a disruptive, yet necessary chore, while in the middle of doing something more interesting, with much less context switching than performing it manually. And that got me thinking about interfaces a bit more. Chat bots are unquestionably a very ergonomic interface.
Increasingly, I am starting to think that a key part of unlocking the value of LLMs, may be through thinking about them more as solutions for interface design problems.
Git is a classic case. Git's interface sucks space balls, everyone knows it. I mean I know a few people who like it, and I'm happy for them (but I think they are weirdos). It does allow for a bunch of studly machismo and nerd flexing, for anyone who has invested enough time in learning its arcana to impress people with stunt-git trick shots, and that can be fun. I have definitely enjoyed being the knuckle-cracking "stand back everyone and stop panicking, I know how to fix this" guy on a number of occasions, but that is a sideshow. You can do circus tricks with power tools, and some people do, but it's not the reason the tools were made.
Git has a compelling storage model, and a commit graph workflow that solves a bunch of annoying challenges with incremental and concurrent code editing and integration, efficiently and better than previous source code version systems. That's why it became a huge success.
Git's horrible ergonomics and implicit barriers to entry, but compelling powers of sharing and integration, allowed GitHub to spring into existence, as a multi trillion zillion company from out of nowhere, just by slapping a nicer set of user abstractions on top of git's ugly robotic core. (in the process accidentally inventing some other significant ergonomic problems, like pull request based workflows, and IDK, tag driven releases, but I guess that's a different blog post)
Git's foul ergonomics are what pulled me into learning magit, which has a reasonably steep learning curve of its own, but also follows the emacs way of having a lovely manual. It's a better thought out UI. It also leverages many common emacs behaviours, so when you're working in emacs already, which I typically was, again, you get this reduction of context switching.
Why is this so important? At this point, it's tempting to dive off into a side bar about "programmer flow state", a long held shibboleth of the developer community about which I don't have much truck, but many thousands of words can be found about it on the web already. - I don't like anything that reinforces programmer identity as a higher state of being, and I dislike how easily this concept is weaponised towards shunning collaboration and social work (e.g. "coders must not be interrupted during holy flow state") , again this is clearly a different adjacent blog post - but the notion is not fundamentally baseless.
Programming tasks often require holding a lot of accrued context about a chain of thought, and carefully expressing those in a narrow, precise domain, incrementally progressing towards a well defined future state. It's not easy for a human mind to do that, it takes a bit of effort. Effortlessly breaking out of one domain into another mode of expression isn't really possible. To do that even passably well, perhaps you would need a different kind of "mind", even?
I think version control is interesting here, precisely because it's liminal stuff. It's programming-adjacent work in a certain sense, it's a chore - any time you have to break thread to address some version control nonsense or busy work, you are in essence interrupting yourself. It makes a lot of sense to try and find a low friction simplified user interface to mediate these kind of tasks. Like GitHub, or magit. The ideal is to minimise the amount of disruption you face while working on these background or side channel threads of work. You can mitigate against this in two main ways I think. You can look for ways to simplify the UI to better suit a particular working context, as we have been discussing; alternatively you can divide the work and make the secondary context a first class task that's managed separately.
One way to do this is to structure the way you work so you can plan your version control stories a little ahead of time, and use discipline in your task management to make it better fit onto the VC, with strategies like formal branching and ticketing protocols, rigorous task mapping that accounts for tech debt, probably integrated into a project management system.
Another way you can do it is to make it literally someone's job and push the load out sideways - examples of this might be code review protocols, gatekeepers for merges (in the olden times, with less sophisticated version control software, I've often worked on teams where there was a nominated 'merge master', whose entire job, or a large portion of it would be to basically do the integration and harder version control work on behalf of the feature developers), also other adjacent roles like scrum masters, or DBAs.
That train of thought got me thinking about SQL. I think SQL is another interesting example of 'programming-adjacent work', although it might be a bit more subtle of an example than it first appears. Let's have another digression then. I really like SQL, although it's obviously covered in warts and sharp edges, I've always appreciated it's utility, and to a certain extent it's ergonomics. It does share some of the properties I've discussed with git - it's very often a boundary, and context shift away from the main thread of programming, and programmers tend to hate it, and like to avoid it, and make up nasty memes about it for slack, and that kind of thing - just like version control (or meetings 😘), it's essential and necessary work in a lot of software development, but it's another liminal place, where you have to get pulled out of the context of thinking about your feature work, and software architecture, and land in another place for a while with an annoying external syntax, and a lot of aggravating round trips into different tooling.
Indeed, over the years, a very common programming pattern is to try and slap a more program-ergonomic abstraction layer in front of the SQL, once again to try and minimise the friction and narrow the interface - I'm thinking of things like various ORMs, 'noSQL' database engines that bring the data modelling and querying closer to the application layer, all of them moderately successful, and yet SQL still hangs around everywhere, slightly annoying everyone, like a remote senior cousin inevitably invited to every wide social gathering, tolerated, rather than enthusiastically invited.
That's because SQL is already an ergonomic abstraction. It's kind of the ur-DSL. SQL is there because databases have a lot of inertia associated with them. All the data is often where the money is. Data is the raw stockpile of materials, the raw ingredients of the information that's necessary to run large information technology applications. Data tends to accrue value cumulatively, and you want to keep it all in a big lump in one place (this is why we have terms like 'data-mining' and 'data-warehousing'), so you can correlate it, and leverage sexy network effects from having it all integrated into one humongous data domain. Once you pass a certain critical data mass, you need to access it multi-modally , i.e. there will be many different use cases for the same information sets, different users and different applications will emerge from, or require access to, various intersectional pieces of that data blob. Now, reading and updating that data blob by hand, in your preferred programming stack would really sting. You'd still have to leave your application software context, but you'd now need to delve into a world of low level file systems, and data packing, and indexed data access, and write locking, and concurrent editing, and wire protocols, and cache invalidation, and the whole nine yards of that side of computer science.
I pause a little here, because I realise I'm probably making it sound kind of fun to a particular audience segment (amongst which I include myself, periodically), but let's not lose track of the core point. If your intended task is to make a cool dating app that helps your users get laid, low level storage systems coding is a horrible, high effort context switch away from the feature track you're working on. And of course, all this data access code you're having to do while you go will also need tracking in your version control system, more context switches. Instead, we SQL.
As an aside, I have found LLM coding assistants to be generally pretty bad at SQL writing. I have two hand-wavy personal theories about why this is the case
I'm tempted to infer something from those two sub-points about SQL requiring fundamentally different kinds of reasoning to other forms of writing, but I'm probably just seeing the face of Poseidon appearing in the patterns of my mental sea foam... I'll leave it there for now. (a third parallel blog post? This stuff is getting fractal). BTW - The name for that fascinating phenomenon is *pareidolia* , and it's something worth keeping in mind when discussing "AI" concepts...
Ahem... Another really interesting aside is to have a look back at the history of SQL. SQL is rather old. It's basically my age, and I've already pointed out I've been using emacs professionally for at least a few decades. SQL emerges from IBM in the 1970s, as a research project, greatly influenced by E.F. Codd's classic article 'A relational model of data for large shared data banks'
The primary designers of SQL were Don Chamberlin and Ray Boyce, part of IBM's system R research project, who were tasked with looking into ways to apply Codd's relational / mathematical principles of database modelling to IBM's database businesses. IBM's database business at this point was most of IBM's business, and IBM's database business was pretty huge. Prior to relational databases, the existing big iron database management systems were awkward weird transactional / hierarchical databases, like IMS/360 where you pretty much had to write a specific computer program to be batch executed from a queued transaction management system. Each 'query' was more akin to an independent program. In order to change the report, you'd develop a new program, and you would need appropriate programmer time and skill to do it, and your best turnaround for results would be several hours, probably more like days.
So the system R researchers wanted to make this more flexible, but their ambitions didn't end there. Chamberlin and Boyce wanted to make information retrieval accessible to non-programmers. Here's Chamberlin
"Ray and I hoped to design a relational language based on concepts that would be familiar to a wider population of users. We also hoped to extend the language to encompass database updates and administrative tasks such as the creation of new tables and views, which had traditionally been outside the scope of a query language.[...] What we thought we were doing was making it possible for non-programmers to interact with databases. We thought that this was going to open up access to data to a whole new class of people who could do things that were never possible before because they didn’t know how to program."
Can you see where I'm heading? SQL is a frantically successful example of what we used to call '4GLs', (fourth generation languages), when I was a school kid, (although by that point, the text books - and what we didn't yet call the hype cycle - were already breathlessly excited by the imminent arrival of the Fifth Generation Languages, and systems...). The terminology is dated, and stretchy, and marketing-fed, but the central gist is - 4GLs are languages that were operating at a higher abstraction level. Your inputs and controls would describe a program at an abstraction level much higher than the operation of the system, and the 4GL would write a program for you that ran at the lower level. All a bit hand-wavy, but SQL querying has some really interesting properties related to this delegation.
The query planner is worth a little thought - The query plan uses a bit of maths, and some heuristics and a bunch of information and sampled data about your system, and works out a series of reads and sorts and filters that produce the data structures your query is requesting. Crucially you don't tell it HOW to do it, just WHAT you want it to do. (sorry, the upper case is a bit addicting, I'll stop). Most of the time you don't think about it too much more than that. However, most SQL database systems will show you their plans if you ask them, typically by using the EXPLAIN keyword, which will show you what the planner thinks it should do to build the result set you wanted. If you don't like what it's decided you can't tell it to do things differently, but you may teach it to do things differently, typically by updating the available indexes and constraints, or maybe by re-balancing the statistics it uses to decide about cardinality and seek times, and that kind of thing.
Here again we have a division of labour - the idea is that the structural and statistical and optimising and runtime bits of maintaining the SQL system can be delegated to the programmer and technician classes, who can be more concerned with the implementation and operational parts, and the query writer (a non programmer, if you remember) can just get on with expressing their tasks in a lower friction, narrowed domain, where they don't have to context switch out as hard from their task at hand, writing lovely business reports for the sales and finance teams to make slide decks from.
Now I'm not saying that SQL writing is 1970s prompt engineering, but I'm also not not saying that, right?
Here's Don again, after the fact
"Ray and I were wrong about the predominant usage of SQL. Typically, SQL is embedded in a host programming language and used by professional programmers"
SQL was, as I have said, a spectacular success. It's still bloody everywhere, fifty years on. It was also an abject failure. The syntax is a mess of unaligned clauses with special cases everywhere (INSERT and UPDATE have such radically different approaches to clauses but sort of do the same thing. So does DELETE really). You need to understand maths to do it properly. You also need to understand the precise details of the database schema. The database schema is maintained in a separate dialect that's somehow intertwined with the querying DSL and uses the same interfaces, but again obeys a different syntax and semantics. Record locking is both implicit and explicit. The concurrency model is insane and nobody actually understands it properly. NULL breaks everything including query logic. And most damningly, it's never used as an interactive REPL by non-programmers. It's folded into programs mostly. In fact these days, an eye-wateringly huge number of applications bundle an entire SQLite embedded RDBMS inside their application deployment.
There's a pattern emerging here I think - querying and reporting wasn't quite entirely programming adjacent busywork, but it was business-adjacent drone work, and SQL was an attempt to narrow the interface with an ergonomic DSL that got out of the user's way and reduced the scope of the context switch needed to engage with the reporting system. It kind of failed at the interface, if you ask me (and most folks who have to use it), but it did succeed amazingly at reducing the complexity of the context switch. Using SQL to mediate data persistence inside your application is kind of like using magit to fold your git operations right inside your emacs workflow, they both serve to shrink down the cost of flipping out of your primary task domain, into some other essential, dependent domain.
Either reduce it to a tight DSL, or extract the work and organise it so it can be delegated to another worker. Sometimes, you put a DSL on top of a DSL, to tune it down even further. Sometimes you build a team to own the work in this domain. What if you build a DSL over a DSL but the DSL could sort of work like a team you can delegate tasks to? That's a compelling interface, that is.
When I look at it like this, using an agent REPL in zed to run git operations strongly reminds me of that (failed) SQL/4GL promise. I tell the thing the result I want from it, and it builds a plan of execution, and I can iterate on that, interactively. Only this time, I'm using literal English sentences to describe the narrow domain the system has trained itself on, not some bastard awful pidgin version of it, that somehow ends up with the worst features of both natural languages, and programming languages. Sorry SQL, it has to be said. And you know what, I kind of love you anyway.
I think this pattern can be found in several places of software development, if you squint right. Programming-adjacent work gets reduced with DSLs or narrow abstractions, which bring the benefits of reducing that tedious, expensive context switch. I guess we have lots of it in CI automation, pipeline building, that kind of thing. DevOps is built out of this stuff, infrastructure as code, deployment charts, meta deployment charts, run-books, playbooks. These domains are also places I've found LLM-based assistants super helpful - help me grind out some yaml please so I can add a pull request pipeline that does this thing I just thought of, without me having to spend quite so much time reading up the stupid YAML syntax for this weeks CI system, and spending hours sitting in a push/fail/edit/push loop on some git forge. GraphQL over REST apis - maybe? Unit test generation and test harness design is mostly busywork in a DSL following some declarable constraints. I think I already mentioned figuring out the precise type annotations for things. It makes me think that coding-assistants are perhaps more of a user interface paradigm than they are a coding one. More like a 4GL than a semantic IDE.
What's my point? I'm not completely sure (he says after several thousand words)
You wait two and a bit years for a blog to show up and then all of a sudden there's two of them!? I seem to have accidentally started a new blog. OMG.LOL, a rather whimsical web service I've belonged to for a while, is dropping new features on it's members for the holiday season, in the form of a charming animated advent calendar. The theme of the season is 'blogging', and right there on day one, they gave us a weblog service, weblog.lol.
So I'm over there at cms.weblog.lol. And I appear to be attempting to post a review of a different christmas pie every day, in a fit of seasonal over-enthusiasm. It will never last. So far I'm three for three though, and having fun.
Do check out omg.lol btw. It's my favourite kind of internet thing really, user-focused, a paid service (no grotty ad trafficking), (it's cheap too, right now it costs $5 per year, although the price is rising in January, get in soon if you want to, you can buy several years in advance) For your money you get a cute namespace of your choosing. Obviously I am cms, and a bunch of other neat stuff. Weblogs! (we already mentioned these). A customisable home page. A DNS subdomain, to do what you like with. A nice short email address, with forwarding. A mastodon instance, an irc server for members, a pastebin, probably some other things I've forgotten. Keybase proofs!
It's cool! Loads of 'small web' vibes, a built in community, and a bunch of fun tools. Definitely gives me nice warm fuzzy 'early internet' feels. I've managed to convince two other people I know to sign up so far. You should too! But in the meantime. I'll be over there blogging. And also maybe over here blogging? I'm such a blogger these days.
Back again! Literally years since my last post. Is blogging back? It feels a bit like people are slightly more excited about self-hosting content again than they have been in a couple of years, it's true. The big incumbent social networks are feeling a bit less solid than they used to. Facebook has been laying people off and visibly throwing money away chasing a dorky-looking, implausible VR business that almost nobody (save for the investors) seems interested in. Twitter has gone private, rather publicly, and at the time of writing seems to be in the process of reinventing itself as Twitter 2.0, whatever that turns out to mean. Right now, it seems to mean far fewer people posting, looking at my logged in timeline. Mastodon is having a moment. Maybe blogging is back!
While I am mildly excited by these winds of change, none of this is really anything to do with my sudden return to posting. My motive is something considerably less idealistic. I've moved web-hosts again, putting this post clearly into the least exciting, yet most solipsistic form of personal blogging, namely, updates on infrastructure and apologies for lack of content, addressed to an almost entirely imaginary audience!
My motive for moving hosts is worth a minor note, and also feels very 2022. My hosting costs have shot up so much, primarily due to the dramatic surges in energy costs of the past six months, that it no longer seems economically viable to use even cheap commercial hosting to prop up a vanity website I barely make any use of. So I've taken the very retro step of bringing it all back in house. Literally in-house, this page is now running off a tiny low-power media PC repurposed as a basic Linux server, connected up to my home DSL connection, and sitting in the cupboard behind the television in my front room. I had fun doing it, but it was an extremely manual process, and as a result of that I'm quite sure there's a few bugs and glitches hanging around, and some stuff will be weird until the all of the DNS edits are fully propagated.
They are still annoyingly hard to track down, but I finally sourced a breadmaker. And I have made some bread. And eaten some of it, and it was good. Astonishingly simple to use, just tip in some slop, select a program and then wait. Although the timer only goes up to 13, meaning I had to get up at 6:30 to release it. On the positive, this is exactly how real bakers do it and so I feel I am close to becoming a master baker.
It is a Panasonic 2511-KXC I can't really offer an objective review. I have never used a bread maker before, and I chose it mainly because it was the only one available in SE England. It has a nut dispenser, although I have not yet put my nuts in it .
Tiny Pilot Kind of surprised that this works, but it's a neat idea if you have too many headless home servers (and I do).
I've been having persistent niggles with my home router / 802.11x base station / DSL modem. It's a D-Link DSL-2740B , itself bought as a replacement for my ISP-provided machine, an O2 wireless III (a re-badged Thomson SpeedTouch) which proved itself a low performer at both wireless and routing, and particularly dismal at doing both simultaneously.
I picked up the D-link cheaply, in a clearance bin in John Lewis. In most respects it has been a splendid replacement for the O2. WiFi is fast, routing is consistent, ADSL sync is better. However, it does have one stupid bug. It can't do DHCP reliably. After a certain period, it starts sending out broken leases to clients; either issuing them with IP addresses that are already in use, or more commonly issuing a working address, but nullifying the nameserver settings. A reboot will restore sanity, but involves an irksome couple of minutes of network outage. Afterwards it is only a matter of time before the problem re-emerges, noticeably quicker if there's an increased rate of new leases issued, such as a group of visitors armed with smartphones popping in.
I'm consistently amazed at how flawed home router appliances are. How anyone 'normal' is supposed to cope with these things, I have no idea. I've updated the firmware to the last available revision, fiddled with the limited options in the admin interface, to little avail. Web searches turn up a few people commenting on the same problem, but no solutions offered. This leaves me with three straightforward, yet unappealing options.
/etc/bootpd.plist file this will create, e.g. / etc/bootpd.plist.template , and then disable internet sharing again, which will remove the /etc/bootpd.plist file if it still exists. Now rename your template back to /etc/bootpd.plist and edit it.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Subnets</key>
<array>
<dict>
<key>_creator</key>
<string>cms</string>
<key>allocate</key>
<true/>
<key>dhcpdomainname_server</key>
<string>208.67.222.222,208.67.220.220</string>
<key>dhcp_router</key>
<string>192.168.1.1</string>
<key>lease_max</key>
<integer>3600</integer>
<key>lease_min</key>
<integer>3600</integer>
<key>name</key>
<string>192.168.1</string>
<key>net_address</key>
<string>192.168.1.0</string>
<key>net_mask</key>
<string>255.255.255.0</string>
<key>net_range</key>
<array>
<string>192.168.1.12</string>
<string>192.168.1.254</string>
</array>
</dict>
</array>
<key>bootp_enabled</key>
<false/>
<key>detectotherdhcp_server</key>
<integer>0</integer>
<key>dhcp_enabled</key>
<array>
<string>en0</string>
</array>
<key>replythresholdseconds</key>
<integer>4</integer>
</dict>
</plist>
/var/db/dhcpd_leases , which will be a persistent database for issued leases. Now connect to the router, and disable it's DHCP server. /usr/libexec/bootpd . If you run it from a terminal with a -d flag, it will stay in the foreground and emit debugging info to stdout. You'll need root privileges for it to run, I just used sudo /usr/libexec/bootpd . Now request a dhcp address from a different network client. I used an iPad. It's a good idea to make a note of the network MAC address. If everything is working, you should see some output acknowledging the request, and then some more as a lease is issued. The client should then configure it's network interface with all the settings from your Subnet definition above. If it doesn't, and the output isn't helpful enough, there's also a further -v switch for more verbose logging. /System/Library/LaunchDaemons/bootps.plist . You can install this persistently into launchd like so sudo launchctl load -w /System/Library/LaunchDaemons/bootps.plist
sudo launchctl list should then show a com.apple.bootpd service enabled. If for some reason you need to disable it once again, you can uninstall the service using sudo launchctl unload -w /System/Library/LaunchDaemons/bootps.plist
I have been rather enjoying wearing a mask outside ever since the bad times began. All the way back in Feb or maybe March, I forget which, time seems more broken than usual, I was improvising by looping a scarf several times around my lower face. I own, and enjoy a lot of scarves, and the weather back then was fairly amenable to swaddling one's entire head in designer fabrics.
Subsequently, as we set in for the long haul, my much cleverer partner ordered the whole family some reusable ones, from Deakin and Blue. Easier to fit, and more effective, and I switched over to this. It's swimwear fabric, basically a speedo for your lower face, and I've been lining it with one sheet of kitchen roll, square folded, which is comfortable enough, and gives a few layers of filtering. The mask is reversible, patterned on one side and black on the other, but I always wear the black side out. I think they other side is floral, but I'm not even sure of that.
I realised I find it fun to wear. It feels like wearing a disguise. Another layer of private bubble on the roam, an extra shield to accompany the earbuds. Thinking about it, so many of my childhood heroes were masked. I think I'm quite into masks. We had the lone ranger and Zorro on the telly, alongside Batman and Robin. Robin Hood had a hood, of course. I remember trying to figure out how Spider-Man could even see through his striking mask design, and how I might some day figure out how to make one. Masks are just cool. Under normal circumstances I'd feel a bit weird wearing one everywhere, and I think it would provoke suspicion, but currently I can prowl around looking like a plank, but imagining I'm a badass. It's nice to have found some minor positive thing emerging out of all the drama of pandemic season. I should probably invest in more masks, get some more interesting colour going on.
Something I'm enjoying far less is any tone of dedicated anti-mask rhetoric, examples of which do seem to be floating around my internet. I find it very hard to understand. Not quite as hard to understand as the mobile phone mast burning, but still. Even if you don't find obscuring your face as childishly gleeful as I do, I don't know why you'd want to make a stand about not wearing one. Even if I assume the conversations on social media are distorted, and amplifying extreme minority views, as they usually do, even when I'm out and about I think I'm probably seeing less than 1% of people wearing them, (although I've not counted properly). This seems a shame. Especially given that I'm living in the eighth ranked hotspot on that leaked sheet of areas for concern(!).
It seems pretty obvious to me that even a very imperfect mask will still impart some reduction of transmission, and it's a numbers game we're currently in. The cumulative benefit of lots of small reductions everywhere are still a useful contribution. Most of the rhetoric I've seen in both directions seems more focused on the individual, arguing that they don't filter much out, or it's some kind of curious affront to personal freedom, or urging people to think of campaigning for it like a seat-belt or an airbag for a car. This perspective is almost entirely wrong. A mask is not something to wear for personal protection, it's something small you can do to help everyone else, that is most effective when everyone else is also doing it.
I realise we live firmly in the age of the self, but I do remain confused how a country that passionately adopted the weekly ritual doorstep clap nation-wide, in a matter of weeks, is less keen to rush into this, arguably more useful, performance piece. I wonder what the missing mechanism is, if it's messaging, or psychology, or something more profound and deeply entrenched.
Still, I have my fun, and don't really plan to stop any time soon. I have been wondering about getting some sequins in, or if I could get some custom patterns ordered. I guess if this all goes on long enough we'll see redbubble and stickermule and the others adding masks to their standard merch templates.
How about some photos of squid flying through the air? I've heard anecdotal reports of this sort of thing happening, which on the face of it sound reasonable, if not a little far fetched. They do possess all the right sort of equipment, and controlled jet propulsion through the air isn't really that far from their usual method of locomotion at speed, which is controlled jet propulsion under the water, after all.
The full writeup in the parent post contains plenty of detail about a recent observation of groups of squid exhibiting fairly controlled, short flight. Not only does the article contain lots of interesting links to scientific write-ups of arial squid observation , but it also contains several high-resolution photo images of the buggers captured in the act.
It would make a lot of sense for them to use as an evasive action. Squid can manage impressive accelerations in their submarine environment, but through the air, they would perform even more rapidly, over short distances. "Short" is of course, relative. One of the write-ups based on observations estimates 20cm squid reaching 10m in a controlled flight. They seem to form their bodies into lifting, braking and stabilising shapes as they go. Squid are ace.
I'm amused that on porting his blog to wordpress jwz has seemingly reached the same level of disgruntlement with wordpress in about a day that it's taken me twelve months or so to reach.
Don't get me wrong, wordpress certainly gives you all sorts of awesome features OOTB, but at a certain cost of complexity, which makes things tricky to customise. Themes are hard to tweak, and the cost of entry to plugin-writing is large enough to put-off simple customisation in favour of out-sourcing to the lazyweb directory of plugins, which correspondingly increases the complexity of your install.
Most pertinently, there's the security record, a cynic might suggest it's a lack of security record. I'm gradually coming around to the line of thought that the frequency of updates actively contributes to the problem. The continual treadmill of manually updating drives people to investigate the auto-upgrade procedures, which are all built around interfaces that sound to me like designed-in exploit vectors, like having all the .php files in the software tree writeable by the httpd user, or running an FTPd service on the webhost that can chdir to the http script directories. Furthermore, the autoupgrade process is prone to terrifyingly unfriendly fail-states .
I'm not sure if there are any significantly appealing alternatives out there. I think there's probably a circular life cycle to the blog software used by any mildly technical person , that moves serially from 'simplest possible lazyweb solution', through 'this simple thing has been customised past the point of sanity, I'll write my own' all the way through to 'writing blogging software is hard, I'll just use wordpress' and subsequently right back to square one.
The elephant in the room is the simplest option. Just host your data in an fully managed service like wordpress.com , or tumblr or posterous . Or if you really don't care about handing every last bit of data you can generate about yourself into the possibly malevolent skynet-cum-panopticon Google-monster, you could get all oldskool with blogger As ever, I just can't get with the idea of giving all my content to an at-best disinterested third party. After all, that's where jwz started out , and look where that's got him. Manually migrating to wordpress, and grumbling.
If you can read this message, it means I have properly configured blog posting by email. Is this useful? Is this a good idea? Time will tell.
You wait six months for a blog post and then I suddenly update all the things at once. Here we are. Site redesign. New Server. New software release. Lets tackle those in order
I launched this version of my blog originally as 'in-progress' software before it was quite ready, after spending a few years faffing around with experiments intended to replace WordPress. One day I had something I wanted to publish, and WordPress was broken, and the thing was nearly working so I hit go. It wasn't feature complete, and there was completely minimal styling, but I thought it looked OK enough, until a friend pointed out it looked completely insane on a mobile. I felt pretty embarrassed, so I quickly cobbled together a mobile-first grid-oriented thing using zurb foundation 5 as a framework, because that was what we were using at work at the time, and it seemed like an excuse to learn a bit about how it worked. I subsequently reworked it to use foundation 6 with a slightly styled theme based on my old WordPress colours and there we are. Of late, the amount of gubbins needed to support the foundation classes has been a bit of an encumbrance, and so I decided to do away with it. This time I just hand-wrote the styles again, I think CSS has moved on a bit and hope browsers are generally a bit better behaved. Seeing as we were doing this, I did a new theme, it's based on my emacs colours. I don't care that you hate it, no.
I'm sure you all heard, ARM hardware is the new hotness now. As a natural contrarian, I was already hosting my site on an ARM server and so it's clearly time for me to move to AMD64. Not quite. For years I've been having fun hosting this place on one of scaleway's ARM C1 instances, which appealed to my quirky taste in alternative computers, as well as being super-cheap, and in many ways, offering far better raw performance than a VPS or a cheap cloud instance. Seriously. I was running about twelve services per instance, and my own hand-written site software, and performance was more than acceptable. I even hit the front page of the reddits and the orangenews a couple of times with my tech dithering, and soaked up big blog traffic spikes, no sweat. However, scaleway haven't offered any useful updates to their core platform since they experimented with, and withdrew a 64 bit ARM beta, and now seem to be moving more towards a VPS/Intel vision, and it was really becoming a bit limiting to be stuck on Debian 9 and 32 bit. So I moved house, installed some containers on an existing server I had sitting around and now we're live, in Belgium .
This is a little bit tied in with the last item there. The site engine here is written in common lisp, and for the longest time I just had it running out of an interactive repl attached to an emacs. Yes, including the #1 NackerYews story days. I moved it to a systemd service, for process supervision, and proper logging and things like that, and I wanted to get some kind of release management regime in place. So I had a fun time figuring out good ways to build standalone lisp apps, and how to package them up for Debian, and now I kind of have tagged release builds. I'm also running in my own cowboy cloud, sticker-ed together out of LXC, so the blog now can be deployed as a clean, ephemeral contained service any time I want to do a release. Particularly this part of things was becoming quite the aggravation, cross-building for ARM32 isn't really trivially feasible with common lisp, and although I had a lot of fun for a bit building debs on a raspberry Pi tucked under my desk, I eventually ran out of patience trying to keep ABI back-compatibility with older Debians.
My process probably seems a little bit archaic and convoluted to anyone used to thinking about this kind of thing in a modern context. It is true that there are lots of simpler abstractions and services for doing this kind of thing these days. Perhaps less intuitively, doing things the bale-of-twine and pencil sketch cowboy manner I've pitched for is also crazy easy compared to what I remember hand wrangling sites of old used to be. LXC is fairly straightforward to install on Debian stable OOTB. (unprivileged mode is still a bit of twerking, but if you follow the recipe exactly, straightforward enough). Debhelper vastly simplifies deb building (although I'll concede you do still have to do way too much) and gpb is simpler yet in some ways. Quicklisp, buildapp and quickproject make lisp dependencies and builds almost pleasurable. Cloudflare and certbot wildcards make swapping hosts around with full TLS almost disconcertingly straightforward compared to what I've been accustomed to in the past.
Of course this is still a rolling set of dependencies which may appear complex or unfamiliar, but in a lot of ways there's also a whole lot of faff and bookeeping overhead removed, no accounts or APIs, third-party apps and frameworks to keep up-to-date. Most of this task list was concerned with a full bootstrap from a naked host. For ongoing support I just have to compile debs using standard make, launch empty containers with standard templates, and write posts and maintain code with a straightforward text editor. And there's complete autonomy of hosting and running, I'm not really locked into anything, which is exactly where I prefer to keep things. The modern-day indieweb refuses to die!
In my piece yesterday, about my blog on last.fm I didn't link correctly to the article . Fixed now.
The other day at work , prompted by a shoutbox conversation with one of our users , I did a little bit of exploring some of the artist catalogue data. The idea was to find band names that were repeating words, such as ' Talk Talk ' and ' The The '. Coincidentally, I had a freshly installed database server with just this sort of information on it, and needed a good excuse to stress test it a little. PostgreSQL's regular expression support is brilliant , and it was a very trivial exercise to quickly knock up a query that returned promising data. In the process of refining it, I got a chance to play around with the Hadoop cluster. I wrote the whole thing up over on the company blog, if you'd like further details. Fame fame fatal fame, it can play hideous tricks on the brain, as the song goes .
Yesterday at work , I had to clean after up a particularly freaky Slony-I replication fault. I still haven't managed to understand quite what went wrong there. So this morning, I arrived at work in full diagnostic mode, jokingly grumbling about 'howfuckedismydatabase.com'. Laurie was particulary amused by this curmudgeonly joke, and we bantered about it. I pitched a few ideas about how such a joke site might operate, and we left it there and moved on.
Except Laurie didn't. Despite my attempts to dissuade him, he registered the domain, and started knocking together some pages based on the earlier jokes. I chipped in a couple more suggestions, and suggested some error messages, and within twenty minutes or so he had an operational site . Then we shared it with a couple of like-minded people, and left it be. A few of the other people at work passed it around, and a couple of people submitted it to reddit.
Within an hour or so things had started to really snowball. One of the reddit submissions gathered hundreds of upvotes, and for a period of time we were the number one story on hacker news . Laurie added a twitter button and a comment form to the site, and retweets and emails started accumulating fast. By mid-afternoon the site was approaching 200 hits a second, which it handled with aplomb, because he had coded it efficiently, and
configured the server sensibly.
It felt great to watch so many people comment positively about some of my dumb jokes, pretty much in real time. It gave me a really direct experience of something I'd always innately understood about the internet, but had not yet witnessed close to home; the ability to quickly reach an appropriate audience for almost any content, regardless of how specialised. Our little shared joke quickly reached out to thousands of people, who found something within it they also related to. This really amazes me.
It also showed me something about my own character. While I was perfectly happy to joke about the idea, it needed somebody like Laurie, with the skill and enthusiasm to pick up on it and make it into something tangible and exciting. I'd instinctively shied away from broadcasting it further than my desk, and my initial reaction was that developing it any further would be a waste of time and money. I was very wrong about that, it turned out to be an interesting experience, and enormous fun. I think this means I should endeavour to be a little less cynical.
Wasps punish fake fighters : Science demonstrates that wasps made up to look tougher than they are receive punishment beatings.
I ran into some problems while I was trying to install python bindings for the Growl notification framework on my MacBook Pro. My Mac is running the current release of Snow Leopard ( 10.6.4 ) and I'm using a python.org installed binary package of python, under /usr/local/python. Building using distutils and the supplied setup.py failed, seemingly because the compiler was unable to find quite routine include files, such as stdarg.h and float.h .
/Developer/SDKs/MacOSX10.4u.sdk/usr/include/stdarg.h:4:25: error: stdarg.h: No such file or directory
This error message both confused and perturbed me, because stdarg is a fairly fundamental component of a working C library, and I am pretty certain that my compiler isn't that fundamentally broken.
Picking apart the build output from the generated Makefile, I see that it is setting the -isysroot gcc flag, to /Developer/SDKs/MacOSX10.4u.sdk/ . I presume this is because the python installation is built to use the OS X 10.4 compatability SDK. This is why it's pulling in /Developer/SDKs/MacOSX10.4u.sdk/usr/include/stdarg.h . That header is a stub, and included the following stanza
/* GCC uses its own copy of this header */
#if defined(GNUC)
#include_next
#include_next is a gcc extension to cpp, and instructs the preprocessor to start searching for the include file again starting with the next directory on the include path after this one. Standard libraries like stdarg and float can be quite compiler specific, and as the comment indicates, GCC is expected to have it's own copy of this header file, which would be put away somewhere under /usr/lib/gcc .
At this point, a nagging memory of building cocoa apps with XCode resurfaced, suggesting that the 10.4 SDK isn't compatible with gcc-4.2 ( the system default gcc under snow leopard ). GCC 4.0 is supplied though, for use with building against legacy SDKs. On this whim, I tried exporting CC=/usr/bin/gcc-4.0 and rebuilding, and everything worked as it should.
From inspection, it seems like the snow supplied leopard python is built to use 10.6 SDKs and gcc-4.2 and may well be a more sensible python to use. Further googling ducking , turned up this bug report .
Salamanders are amazing creatures : Could they really be photoysynthesising symbiotically?
It's Not 50/50 : Pigeons outperform humans at optimising the Monty Hall problem
The man who guarded the secret of the Beatles : David Hepworth knows his onions.
Male fish in Mexico sports sexy 'moustache' : Scientists have measured the way female Mexican mollies (Poecilia sphenops) respond to males with varying top lip furniture, and discovered a clear preference for a moustache.
It's been a good long while since I've been able to blog anything of substance. Some of that is down to lack of time, I've been frantically busy the last few months, much as you'd expect. There also were some dull technological barriers that were making it awkward to update and maintain this site. <br><br> I've moved the hosting to a new location, it's currently residing on a xen virtual server instance provided by <a href="http://linode.com">linode</a>. While I was migrating things around, I've tried to package it up a little more portably, and in future I ought to be able to move it easily to anywhere I can run a linux host. I also took the opportunity to tidy up the page templates, and cobble together a new theme. I'm still poking that around a little bit, let me know if you find any rough edges.<br><br> <h4>New job!</h4><br><br> Aside from adjusting myself to my <a href="http://beatworm.co.uk/blog/ada/im-a-rapper-with-a-baby/">wonderful new daughter</a>, I've gone and got myself a new job. I wasn't really aware that I was looking for one, but life can surprise you like that sometimes. I'm now working as a Database Architect at <a href="http://last.fm/user/colins/">Last.fm</a> and I couldn't be happier about that. Not only is last.fm an awesome site, which has long been one of my favourite things on the web, but the intersection between high volume web services, big databases, and music nerdery is very definitely my kind of niche.<br><br><br><br> <h4>Move to London</h4><br><br> One small drawback with this full-time role was that it was based in London. We did weigh up the various commuting options, but after some deliberation, decided to take the plunge, and relocate, at least temporarily to London.<br><br> This meant finding somewhere to rent. Somewhere to rent that would take a baby and a dog. A location in the city with suitable dog exercise routes close at hand. Ideally a place from which I could daily commute to <a href="http://maps.google.co.uk/maps?f=q&source=s_q&hl=en&geocode=&q=last.fm&sll=53.800651,-4.064941&sspn=16.450021,44.428711&ie=UTF8&hq=last.fm&hnear=&ll=51.528457,-0.086882&spn=0.004052,0.010847&z=17&iwloc=A">Shoreditch</a> without too much trouble. Obviously we'd have to be able to afford it on one salary, whilst still maintaining a mortgage on the house in Bristol in the interim. Rather a tall order.<br><br> After balancing up the variables we settled on the Balham/Clapham area. After a few complicated expeditions up to view properties with little success, we managed to secure something with only days to spare, just down the road in Tooting Bec. A rather roomy <a href="http://maps.google.co.uk/maps?f=q&source=s_q&hl=en&geocode=&q=Elmbourne+Road,+Wandsworth&sll=51.434735,-0.150461&sspn=0.008628,0.015535&ie=UTF8&hq=&hnear=Elmbourne+Rd,+Wandsworth,+Greater+London,+United+Kingdom&ll=51.434655,-0.150611&spn=0.008575,0.015535&z=16&layer=c&cbll=51.434733,-0.15047&panoid=hH03gMlSJRXaMcWDe_cQ_w&cbp=12,273.93,,0,6.37">ground floor flat facing right onto Tooting Bec common</a>. It's just a short walk to the Northern line, which leaves me with a manageable half-hour or so trip to work, door to door.<br><br> So the last few months have seen quite a furious pace of changes. Mostly I've been finding it all invigorating, and exciting, rather than incapacitating, but things can seem to be wooshing by, and there <em>definitely</em> aren't as many hours in the day as there used to be. Five years ago I'd have been amazed at what the me of 2010 would be getting up to. Interesting times.
Ultima V running on TI calculators : Presumably they already have nethack.