|
|
|
|
|
|
Not bad for a first effort Today I got out needle and thread and made a new strap for my watch. My diary archives tell me that it was on 4th July 1998 when I last did this. I had been advised by a doctor that wearing a watch constricting my wrist might have been contributing to the wrist pains I had at the time, and after trying various other solutions (e.g. things that weren't actually watches, or just getting good at reading other people's watches upside down very quickly when their wrists turned towards me) I hit on the plan of making a custom strap which velcroed round my belt and had a little loop to fit to the watch. This turned out to be a great idea; I haven't had those wrist pains in years, so I could in principle go back to wearing a watch on my wrist, but I really wouldn't want to any more. It's very convenient not to have to take it off to wash up, and having my watch attached to my trousers makes it incredibly difficult to accidentally leave it at home or anywhere else. That custom watch strap was the very first thing I ever sewed. I had to more or less teach myself to sew in the course of making it, and my diary archive also records that I sewed my thumb to it in the process. Given that, I think, it's a reasonably decent result that it's lasted until today, when I finally decided it was so close to falling apart that I didn't trust it not to fail suddenly and drop the watch down a drain, so I sat down and sewed a new one. I'm not actually sure my sewing has improved all that much in the intervening thirteen years and ten months. I didn't sew myself to anything this time, but the actual stitching is in much the same robust but unaesthetic, purely functional style as it was on the first strap. The only real difference is that this time I made the strap out of leather rather than rucksack strapping, in the hope that it would be both thinner and less prone to unravelling. So, I wonder how long the new one will last! To do as well as the original, it'll have to survive until March 2026. |
| | |
|
|
|
|
Yet more C abuse In two recent posts here, I've suggested moderately evil things to do with the C preprocessor, both on the same theme of defining a macro that can be used like a loop keyword by following its invocation with a statement or block of your choice. Last week some further thoughts on the subject occurred to me, which were rather more comprehensive and also considerably more evil still. I think I've now taken that general idea to somewhere near the limit of its possibilities, by developing a general system of construction-kit macros that make it more or less feasible for people to develop custom loop types. The result is far too long to fit in this post, so I've put it up on my website. For those with a strong stomach and an interest in metaprogramming or C abuse or both, I present ‘Metaprogramming Custom Control Structures in C’: http://www.chiark.greenend.org.uk/~sgtatham/mp/. |
| | |
|
|
|
|
I shouldn't be allowed in a kitchen I mentioned two weeks ago that I'd cut my fingers chopping onions again. A few days after that I managed to cut my foot in the kitchen: I dropped a plate, which shattered on the floor, and since I happened to be barefoot at the time my toe was gashed open by a sharp piece of flying crockery. And last night I splashed boiling water over my hand while taking a pan of potatoes off the hob, and not content with that threw half the potatoes over the kitchen in the process. I've bought an onion-chopping gadget, but it's possible that what I should have bought instead was a chef, so that I could never set foot in a kitchen again. |
| | |
|
|
|
|
C abuse of the week I continue to be amazed at the number of bizarre things you can arrange to do using the C preprocessor, the switch statement, and a strong stomach. I've previously used the combination to implement coroutines, of course, and also a modified version of for which performs its test after the loop body rather than before it. Chris mentioned to me this morning the fact that you could write this sort of thing: switch (get_value()) case 1: case 2: case 3: do_stuff();
which has the handy effect of calling get_value() only once and then testing its return value against several possibilities (though they're constrained to be compile-time constant integers). But of course it's hopelessly ugly, so he challenged me to wrap it up in a macro or two. (Not that that stops it being ugly, exactly. But differently ugly. :-) The obvious solution seemed to me to be this: #define IF_IN_LIST(expr,list) switch (expr) case list: #define OR : case
which then lets you write compound statements that only look slightly un-C-ish: IF_IN_LIST(get_value(), 1 OR 2 OR 3) do_stuff();
But then I realised that if you dangle a few more oddities off the switch statement, you can do better. If you do it like this: #define IF_IN_LIST(expr,list) switch (expr) default: if (0) case list: #define OR : case
then your uses of the macro can now include an optional else clause! IF_IN_LIST(get_value(), 1 OR 2 OR 3) do_stuff(); else do_other_stuff();
(And naturally both versions work with either bare statements or braced blocks.) |
| | |
|
|
|
|
Ow Nasty cuts on two fingers of my left hand today, after an onion-chopping accident – two layers of the onion unexpectedly detached and slid along each other, one carrying the knife with it. This is the second time in recent years that this has happened; when the current cuts heal, the scar on my middle finger will sit next to a suspiciously similarly-shaped one on my index finger from 2009. Onions were the culprit on that occasion too. So perhaps, for my own safety, I should invest in a gimmicky kitchen gadget for chopping onions. A quick google this morning suggests that there are several quite different-looking designs, though, and I'm not at all sure which is likely to be most effective… |
| | |
|
|
|
|
Forgot my password! I got into the office today after a relaxing holiday of three weeks (plus yesterday) and found, embarrassingly, that I couldn't remember my work password any more. I could remember a password, but I was pretty sure it was the one from before my most recent change, and it certainly didn't work when I tried it. I can't believe that. First password I've forgotten in over a decade, surely. I had to go and queue outside the IT helpdesk room like a gormless student. I had a brief moment of hope when I got back to my desk and found the new password didn't work either. ‘Aha!’ I thought, ‘perhaps the password I'd remembered was right after all, and it's just my desktop computer that's confused.’ But no; after some more faffing, it turned out that password changes are just propagating slowly this morning and I had forgotten my original password after all. It's at moments like this I feel that companies ought to have a mechanism whereby you can turn round and go home and back to bed, on the basis that you're likely to do more harm than good if you continue trying to do work. |
| | |
|
|
|
|
RepugNaNt I had a disgusting thought just now. I needed to have some Python code check whether a dictionary contains a particular key/value pair. The obvious approach, if dictionary[key] == value:
isn't sufficient, because I need to not throw an exception if the dictionary doesn't contain any mapping for that key at all. An obvious way is to use a second clause to handle the latter case, so you end up writing if key in dictionary and dictionary[key] == value:
But that's unpleasantly verbose, and also undesirable if dictionary or key is a complicated expression or one with side effects. So I wondered if we could do better. Another possibility is to use the get() method of Python dictionaries, which lets you specify a default return value if the dictionary hasn't got the key in question. So you might say, for instance, if dictionary.get(key, None) == value:
But in order to be able to do that, you have to be able to think of a default that will guarantee to compare unequal to value; for instance here, what if the value is None? If you know something about value (e.g. its type) then this is probably feasible one way or another, but one can imagine more general situations in which that wouldn't be the case. I think the right answer, in fact, is to write if (key, value) in dictionary.viewitems():
where viewitems() is a standard method which presents the dictionary as if it were a set of ordered pairs. (You could also use dictionary.items(), which would be semantically equivalent, but much slower due to constructing an explicit list and then iterating along it.) But before I found the viewitems() method, I thought a bit harder about the get() approach. Perhaps, I thought, I could define a class with a comparison method that always returned false, so that an instance of that class would compare unequal to anything, including itself. And then, as I thought the phrase ‘compare unequal to anything, including itself’, a stray neuron fired in my head. I think this would work pretty reliably: if dictionary.get(key, float('nan')) == value:
and its only downside is that it is the most disgusting thing ever! :-) |
| | |
|
|
|
|
Sometimes I have an idea and then just wish I hadn't Many Unix programmers will be familiar with the utility variously called strace, truss, ktrace, dtrace and probably other names too, which logs all communication between a process and the kernel across the system call interface. A couple of years ago I wrote an analogous program called xtruss, which produces similar logging but operates at the interface between an X11 client program and the X server. (Of course, that wasn't a new idea; I just liked my version's design better than prior ones, mostly because it behaves more like strace.) A related piece of software to strace is Subterfugue, which intercepts system calls using the same underlying technology that strace does, but instead of passively monitoring them, is able to modify the results as it sees fit. The result is a user-scriptable system that allows you to subject a process to all sorts of subtle and not-so-subtle illusions or behaviour modifications; it can be quite tricky to do anything that's both useful and robust with it, but it's potentially pretty powerful. (It's also not been maintained for ages, but that's not relevant to my current train of thought.) Today I had the idea: why not fill in the blank in that table, and write the thing that is to xtruss what Subterfugue is to strace? Reuse xtruss's framework for conveniently setting up one-off X11 proxies between a specific application and the X server, and then implement a marshalling and demarshalling layer which translates between wire-encoded X11 messages and an unpacked format that can be accessed by a popular scripting language. Then you could arrange both large and small special effects on X programs, and in particular you could cause them to happen on a per-client basis rather than uniformly across the whole server. But that wasn't the idea I started off with. I was actually wondering about a much more specific problem: remapping – and occasional complete destruction – of X keystroke events on a per-application basis, for applications with inadequate built-in keymap configurability. (For instance, I keep accidentally hitting a key combination in my work email client which causes half-composed messages to be sent without confirmation, but I'm unwilling to just define that key combination to be a window-manager hot key for ‘do nothing’ in case I turn out to need it in some totally different application.) And since I already have the X proxy framework from xtruss, the thought occurred that I could enhance it just a little to let it rewrite or squash X events, and then I'd have a proxy that would do the thing I wanted; and although this would certainly be a disproportionate effort for the result if I were writing that X proxy from scratch, doing it by slightly modifying code I've already got seemed almost practical by comparison. But of course once I'd thought of doing this job by proxying an X connection and rewriting pieces of it, I realised that that certainly wouldn't be the only use for such technology, which led immediately to the idea of a Subterfugue-like general framework. And on the one hand that does sound like quite a fun piece of software … and yet, we're now back to it being a huge amount of work to go to for the sake of the one specific application I actually wanted it for, and I'm pretty sure I can't be bothered. But on the other hand, now I've imagined the generic version, I also wouldn't feel right about writing just the one-off utility that only does key mapping (or, worse still, only the specific key mapping I wanted). Bah. (There seems a good chance that at least one reader will point out some totally different way in which I could impose keystroke-mangling of my choice on an uncooperative X client. I will be grateful for that, but it won't affect the main point, which is that sometimes having an apparently cool and generalising and elegant idea makes me less happy, and furthermore, bah.) |
| | |
|
|
|
|
Unexpectedly handy Over the last couple of weeks I've been trying to arrange to get a proper lock fitted on my back gate at home: one that you can conveniently open with a key from either side, instead of having to reach through the gate to a fiddly padlock and risk dropping your entire keyring on the wrong side of a gate you can't get through. I found an online recommendation for a handyman, and since he had an email contact address listed, I thought I'd do the initial feasibility discussion by email in the hope that it would be less hassle than faffing about with telephones. This turned out to work very well: he was able to send me a URL showing the precise type of lock he suggested would be best, and in return I sent him a URL to a photo I'd just taken of my gate so he could judge whether it was suitable to take that lock without actually having to come and look at it, and then he sent me an official quote for the job as a PDF. What I wasn't expecting was that an hour ago, when I was in the Tesco near work buying my lunch, a guy I'd never seen before stopped me in an aisle and asked ‘Are you Simon?’ – and when I spotted the logo on his jacket, I realised he was the handyman himself! He'd found my picture on my website somehow (my guess is by trimming the URL of the photo I'd sent and following links back to my home page, though I suppose it's also possible he might just have googled me), and remembered it well enough to recognise me in passing. |
| | |
|
|
|
|
Signs of life After over four years, a PuTTY release sees the light! But good grief, I had forgotten how much hassle the release process was. I remember having a long and clearly worded checklist to help me through it – and yet I could swear the checklist has somehow bit-rotted over time, so that now it seemed opaque and fiddly. (Or perhaps it's just my brain that's rotted.) Suddenly I feel a surge of sympathy for the people at work who have to actually ship software to customers. |
| | |
|
|
|
|
Bah A pleasant evening; a good book, a silly iPad game, a nice bowl of soup almost ready to eat, and then the prospect of the pub. One ill-judged arm movement later: a fiddly and unpleasant job of cleaning up soup from all over what seems like 3/4 of the kitchen, half my clothes thrown in the wash, a sudden need to find emergency backup dinner, and no realistic prospect of getting to the pub at all. Bah. That last point is probably just as well today, I suppose. If I can make this much mess in ten seconds while sober… |
| | |
|
|
|
|
Pub poetry Crashety-bashety Microsoft Windows is badly in need of a UI that's nice. Some feature filed under ‘Accessibility’ makes it superb – but you can't find it twice.
(Brought to you by several pints of Kopparberg and fanf praising the ‘mouse trails’ feature in Windows.) |
| | |
|
|
|
|
You couldn't make it up Oh, good grief. My missing prescription from Monday turned up in the post yesterday, after the surgery got their printers working again. I took it to a pharmacy just now – who refused to fill it, because the doctor had (presumably due to the unusual circumstances) forgotten to sign it. |
| | |
|
|
|
|
Medical farce Two weeks ago I tried to make an appointment with my GP. Since it was tedious administrative routine (renewing my prescription for gluten-free pasta, which I still can't bring myself to believe is worth wasting a medical professional's time for in the first place), I didn't think it was worth booking an urgent same-day appointment, and instead tried to book in advance. It turned out they didn't have any advance appointments earlier than a week later – you can have today, or next week, and nothing in between. When I arrived for my appointment they said I didn't have one. I was not best pleased, but the receptionist was utterly unwilling to do anything to compensate, so the best I could do was to walk away with an appointment card promising me an appointment in another week's time. This morning I turned up for that one, and this time I got to see a doctor. However, I still didn't walk away with a prescription in my hand – because all their printers, or at least all the ones they tried, were broken! |
| | |
|
|
|
|
Murphy strikes again When wielding a Stanley knife, I concentrate extremely hard on not cutting myself with the Stanley knife. So hard, in fact, that I manage to completely overlook the possibility of cutting a finger on the thumbnail of my other hand. Sigh. |
| | |
|
|
|
|
Machine translation gets it spectacularly right In a debate at work about development workflow, I somewhat whimsically responded to a suggestion by writing ‘Jira issues non sunt multiplicanda praeter necessitatem’. (For those lucky enough not to have encountered it, ‘Jira’ is the name of a bug tracker.) I wondered briefly whether that would be too incomprehensible to post (but decided not, and posted it anyway). Chris had the obvious idea that if someone didn't understand it, they might try pasting it into Google Translate, and tried it. Google Translate renders the sentence into English as ‘Jira issues must not be multiplied beyond necessity’. Very good; I'd have preferred should, but must is acceptable. But what's impressive is that if you switch the target language to something else, it turns out that it's not (as I initially assumed) identifying the language as Latin, applying a Latin-to-English translation step, and giving up on the English fragment and passing it through unchanged. No: it actually managed to translate the English part from English, and the Latin part from Latin, both into the specified target language, and as far as I could tell it even got the two fragments in their correct grammatical relationship. I may be out of date with the state of the art, but I was impressed by that! |
| | |
|
|
|
|
Exploding toothpaste Warrgh, that was unexpected. I picked up my toothpaste tube, squeezed it gently until toothpaste began to emerge from the nozzle … and there was a sudden pop, a fingertip-sized blob of toothpaste flew out of the tube and landed in the basin, and I was hit in the eye by a sharp puff of minty air. There must have been a big bubble of air in the tube due to a manufacturing defect of some sort, and the instant there was no longer enough toothpaste blocking the nozzle to impede its bid for freedom, off it went. But for all that the cause is comprehensible after the fact … I've never had a tube of toothpaste explode in my face before! |
| | |
|
|
|
|
Gadgets I would like to exist I've occasionally thought it would be nice to have a coffee mug with a built-in heater, so it keeps the coffee from getting completely cold. But this is an obviously impractical idea: heating costs serious energy, so you'd have to have a stand to supply the power, which is inconvenient; also there are probably some exciting failure modes. This morning it occurs to me that there's a much smaller, simpler and more realistic coffee-related gadget that would deliver a similar benefit: a thermometer you could attach to the outside of the mug which would go beep when the temperature dropped to a predefined threshold, signalling ‘last chance to drink up your coffee before it gets unpleasantly cold’. That could much more easily be a standalone device running off a battery. I suppose you'd also want it to notice if you'd already finished the coffee, and not go beep just because an empty mug had cooled past the threshold. Hmm. Must be something clever you can do about that… |
| | |
|
|
|
|
Errata Ahem. In yesterday's post about iterating over a circularly linked list, I made a mistake. The construction I exhibited, because it completely skips any test at the start of the loop, will crash if the list is empty and hence its head pointer is NULL. Fortunately, this is fixable by putting an additional test in the switch statement: switch ((elephant = head) == NULL) while (elephant = elephant->next, elephant != head) case 0:
Then if the head pointer is NULL, the switch's input value will be 1, so it won't execute anything in its body at all. However, I now also realise that there's a better answer in the first place. One commenter yesterday observed (and I had also thought myself) that the problem would be easy if only you could declare an extra flag variable and use it to suppress the first loop test. You can't, under the constraints of C90 syntax, because there's nowhere to put the declaration that doesn't cause further syntactic problems. But actually, I just realised, you don't need an extra variable at all – all you need is an extra value for the loop variable you've already got, and we already have a good special value for pointer variables in the form of NULL. So you can just do this: for (elephant = NULL; elephant ? elephant != head : (elephant = head) != NULL; elephant = elephant->next)
So if elephant is NULL on entry to the loop test clause, that's the signal that it's the very first iteration, and we reassign elephant to the loop head pointer (and terminate if even that is NULL). Otherwise, it's a non-initial test, and we do the obvious thing of checking whether we've arrived back at head. This is a cleaner solution than the switch-based one, because it doesn't interfere with case statements inside the user-provided loop body. It's far less exciting, but there we go. |
| | |
|
|
|
|
C abuse of the week A while back I wanted to write some C code that looped over every element in a collection. But I wanted the code to be parametrisable in the face of different implementations of that collection, because it might have to link against several other pieces of code which might all store the things in question in a different format. ( iteration over a collection of elephants by C switch abuse ) eta: there's a bug in the switch-based solution above. See my follow-up post for details. |
| | |
| |