grinder's Journal grinder's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-01-25T02:08:25+00:00 pudge Technology hourly 1 1970-01-01T00:00+00:00 grinder's Journal print scalar gmtime 1234567890 <p>It seems like only yesterday we passed epoch 1000000000 when in fact it was nearly eight and a half years ago. On the other hand I remember epoch 1111111111 quite clearly since it was just before my birthday.</p><p>And now we come to another momentous epoch, that of 1234567890. I just happened to notice this as I was watching a Cyrus imapd logfile.</p><p>2009-02-13 23:31:30 UTC, by my reckoning. A good excuse for a pint, if you ask me.</p> grinder 2009-02-12T21:15:54+00:00 journal Please test File::Path 2.06_06 <p>A couple of usability bugs turned up when File::Path was dragged kicking and screaming into the third millennium, with its new options hash interface.</p><p>Refactoring the code introduced a nasty symlink chmod 777 error, and the heuristics for detecting the new way of calling <tt>rmtree</tt> and <tt>mkpath</tt> made the wrong call in some circumstances.</p><p>All should be fixed, and the code as it stands should be ready to be bundled with perl 5.8.9. To help this happen, could people <a href="">give this a spin</a>?</p><p>Notably, users of minicpan should see errors about uninitialized variables go away, and people who see spurious all-digits directories created in $HOME should also see them go away.</p><p>Also, is the documentation clear? Please lodge RT reports for any problems you encounter.</p> grinder 2008-10-28T10:31:43+00:00 journal Another fun (?) SQL puzzle <p>So, I have a database with a particularly nasty design decision. We have people who belong to cost centres, usually only one, but sometimes with a prorata on two cost centres. The programmer responsable for creating the table denormalised things, so rather than having</p><blockquote><div><p> <tt>&nbsp; &nbsp; EMP1&nbsp; UNIT1 50%<br>&nbsp; &nbsp; EMP1&nbsp; UNIT2 50%<br>&nbsp; &nbsp; EMP2&nbsp; UNIT3 100%<br>&nbsp; &nbsp; EMP3&nbsp; UNIT1 100%</tt></p></div> </blockquote><p>we have something that looks like</p><blockquote><div><p> <tt>&nbsp; &nbsp; EMP1&nbsp; &nbsp;UNIT1&nbsp; &nbsp;UNIT2&nbsp; &nbsp; 50&nbsp; &nbsp;50<br>&nbsp; &nbsp; EMP2&nbsp; &nbsp;UNIT3&nbsp; &nbsp;null&nbsp; &nbsp; 100&nbsp; &nbsp; 0<br>&nbsp; &nbsp; EMP3&nbsp; &nbsp;UNIT1&nbsp; &nbsp;null&nbsp; &nbsp; 100&nbsp; &nbsp; 0</tt></p></div> </blockquote><p>That is, both cost centre ids in the same table, the second one usually null. It is a given that there will never be more than two. This table is of course an utter bitch to work with. Turns out we can cheat a bit, by only keeping track of the rate of the first centre, the second is just 100-first (which also helps cut down round-offs). Let us create a table to play with:</p><blockquote><div><p> <tt>create table t1 (<br>&nbsp; &nbsp;id_person varchar(10),<br>&nbsp; &nbsp;rate&nbsp; &nbsp; &nbsp; number(5,2),<br>&nbsp; &nbsp;unit1&nbsp; &nbsp; &nbsp;varchar(3),<br>&nbsp; &nbsp;unit2&nbsp; &nbsp; &nbsp;varchar(3),<br>&nbsp; &nbsp;val1&nbsp; &nbsp; &nbsp; number(10),<br>&nbsp; &nbsp;val2&nbsp; &nbsp; &nbsp; number(10)<br>);<br>insert into t1 values ('alice',&nbsp; &nbsp;1, 'U1', null,&nbsp; &nbsp;10,&nbsp; &nbsp;20);<br>insert into t1 values ('bob',&nbsp; &nbsp; &nbsp;1, 'U2', null,&nbsp; &nbsp; 4,&nbsp; &nbsp; 8);<br>insert into t1 values ('carol', 0.5, 'U1', 'U2',&nbsp; 300,&nbsp; 600);<br>insert into t1 values ('david', 0.2, 'U1', 'U3', 6000, 8000);</tt></p></div> </blockquote><p>Now I want the sum the values val1 and val2 by unit, keeping in mind that for 'david', VAL1 6000 * 0.2 = 1200 is summed to U1, and the difference, 4800, to U3. Similarly, for VAL2, 1600 to U1 and 6400 to U3. In other words, I want the following result set:</p><blockquote><div><p> <tt>&nbsp; &nbsp; U1 1360 1920<br>&nbsp; &nbsp; U2&nbsp; 154&nbsp; 308<br>&nbsp; &nbsp; U3 4800 6400</tt></p></div> </blockquote><p>Now the only way that I can see is to:</p><ol> <li>Sum the value proratas for all people on their first cost centre. If they have one centre, they get the full hit, otherwise it's prorata'ed between it and the second.</li><li>Union the above with the people having two centres, by subtracting the prorata of the first centre from the total value to arrive at the second prorata (to minimise roundoff errors, otherwise the sum of both centres will lose a cent compared with the initial sum from time to time).</li><li><p>Treat all that as a derived table, and sum the results.</p></li> </ol><p>This gives the following:</p><blockquote><div><p> <tt>select<br>&nbsp; &nbsp; &nbsp;S.UNIT&nbsp; UNIT<br>&nbsp; &nbsp;<nobr> <wbr></nobr>,sum(V1) V1_TOT<br>&nbsp; &nbsp;<nobr> <wbr></nobr>,sum(V2) V2_TOT<br>from (<br>&nbsp; &nbsp; select<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unit1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UNIT<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>,sum(val1 * rate) V1<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>,sum(val2 * rate) V2<br>&nbsp; &nbsp; from<br>&nbsp; &nbsp; &nbsp; &nbsp; t1<br>&nbsp; &nbsp; group by<br>&nbsp; &nbsp; &nbsp; &nbsp; unit1<br>&nbsp; &nbsp; union select<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unit2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;UNIT<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>,sum(val1 - val1 * rate) V1<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>,sum(val2 - val2 * rate) V2<br>&nbsp; &nbsp; from<br>&nbsp; &nbsp; &nbsp; &nbsp; t1<br>&nbsp; &nbsp; where<br>&nbsp; &nbsp; &nbsp; &nbsp; unit2 is not null<br>&nbsp; &nbsp; group by<br>&nbsp; &nbsp; &nbsp; &nbsp; unit2<br>) S<br>group by S.UNIT<br>order by S.UNIT</tt></p></div> </blockquote><p>That's pretty ugly. Is there a better way?</p> grinder 2007-10-19T11:20:42+00:00 journal Bitten by glob crypto context <p><nobr> <wbr></nobr><tt>/me is annoyed</tt> </p><p>I just spent a while chasing a stupid bug. I have an big log directory that I have to clean up. The number of files caused the shell's wildcard expansion to fail. So I wrote some perl to move things around.</p><p>And it didn't do anything. To cut a long story short, I needed the total number of files in the directory. So I had something along the lines of:</p><blockquote><div><p> <tt>perl -le 'print scalar(glob("*"))'</tt></p></div> </blockquote><p>That does not return the number of files. It returns the name of the first file. Or the last. I don't care.</p><p>You have to force array context and throw it away:</p><blockquote><div><p> <tt>perl -le 'print scalar(()=glob("*"))'</tt></p></div> </blockquote><p>This prints 31192. I wish Perl didn't do this. Nice interview question though, I guess.</p> grinder 2007-09-27T11:05:09+00:00 journal How to recover from an out-of-sync Win32 screen resolution <p>Just a note to myself, in case I ever need this again, and it may help someone else....</p><p>I have a boring 17" no-name cathode ray monitor at home, coupled to a Wintel box with a reasonably useful graphics chipset on the motherboard.</p><p>The chipset appears to know how to do a virtual screen or 3000 or so pixels square, and window the screen display onto it, not that I find this particularly useful, but anyway...</p><p>One of my children has a computer game that kicks the screen into a certain resolution, and when you quit, it resets the screen resolution back into this mega-enormous resolution, and the screen attempts to try and display it at 70-80 times a second and fails dismally, instead of just setting a viewport into it. I have no idea who's fault this is. The result is what Neal Stephenson might call a snowcrash.</p><p>Actually, it's not. The machine is still completely functional except that it looks like you're looking at encrypted TV without a decoder.</p><p>After a number of reboots, the machine finally gets the message and resets the resolution to something sane. No, Safe Mode doesn't work. When I return to normal mode after a Safe session, the screen remains scrambled.</p><p>So finally after having done this too many times, I realised was that all I needed to do was to note the keyboard shortcut sequence, and then I could land the beast on instruments only.</p><p>And here is the recipe:</p><ol> <li>Right-click # bring up the desktop/display menu</li><li>P # select "Properties" (up arrow probably works too)</li><li><p>Shift-Ctrl-Tab # select previous (i.e. last, right-most) display tab</p></li><li>Alt-R # Resolution widget</li><li>Left arrow 15 times # back to 800x600</li><li>Enter</li></ol><p>At the point the screen realigns itself with reality again, and then I can go and choose some other resolution.</p><p>grmphlkrjmgna</p> grinder 2007-06-11T21:26:25+00:00 journal Call for testers: the new File::Path <p>The latest development version of File::Path (version 1.99_02) is winging its way around the world to a CPAN mirror near you. It needs to be tested on as wide a variety of platforms as possible. This includes Windows, VMS, OS/2, QNX, NFS file systems, AFS and anything else you can lay your hands on.</p><p>If all goes according to plan, it will be bundled with Perl 5.10, and it is also backwards-compatible all the way back to Perl 5.005 (and possibly earlier), which will allow older installations to be upgraded to the new version as well.</p><p>The main improvement is that instead of writing:</p><blockquote><div><p> <tt>&nbsp; &nbsp; rmtree( ['/foo/bar/rat', '/zug/zwang'], 1, 1 );</tt></p></div> </blockquote><p>... (quick, what do those positional parameters do?) one may now write the more self-documenting</p><blockquote><div><p> <tt>&nbsp; &nbsp; rmtree( '/foo/bar/rat', '/zug/zwang',<br>&nbsp; &nbsp; &nbsp; &nbsp; { verbose =&gt; 1, skip_others =&gt; 1 }<br>&nbsp; &nbsp; );</tt></p></div> </blockquote><p>But all this needs to be tested as far as possible, to ensure that nothing has been broken during the renovations. Please report bugs on the File-Path RT queue (<a href=""></a>).</p><p>Thanks.</p> grinder 2007-05-27T14:37:39+00:00 cpan Ever heard of Pex::Text? <p>An item came up on the contact address the other day: someone was asking where to find Pex::Text since they couldn't install it.</p><p>My first stop was to try out a couple of things on, but the results were a little too helpful, i.e., pages and pages of results or nothing at all.</p><p>So I fired up my second tool of choice, based on acme's most excellent Parse::CPAN::Packages and after a couple of regexp searches I was satisfied nothing remotely like it exists.</p><p>I then turned to a reputable search engine and ran a search on "Pex::Text" and the first page was what looked to be like sploit sites, written in various slavic and asian languages I have trouble identifying.</p><p>So I closed the ticket saying that the person was on their own. But for my own edification, I'd like to know if anyone has heard anything about it (what it does, what it's used for/in), just for the record (and the fact that reputable search engines will no doubt pick up on this journal in the future).</p> grinder 2007-05-03T20:25:49+00:00 journal Calculating years (anniversaries) between dates in SQL <p>Dear Lazyweb,</p><p>I've just spent the better part of an hour searching the web and coming up blank, and finally coding up my own SQL statement to solve the following problem: given a two dates, how many years apart are they? I didn't want to use Oracle's date minus date equals number of days, because I wanted to avoid the hassle of dealing with leap years.</p><blockquote><div><p> <tt>select<br>&nbsp; &nbsp; case<br>&nbsp; &nbsp; when (to_char(sysdate, 'MM'&nbsp; ) - to_char(to_date(:dt), 'MM')) &gt; 0<br>&nbsp; &nbsp; &nbsp; &nbsp; then (to_char(sysdate, 'YYYY') - to_char(to_date(:dt), 'YYYY'))<br>&nbsp; &nbsp; when (to_char(sysdate, 'MM'&nbsp; ) - to_char(to_date(:dt), 'MM')) &lt; 0<br>&nbsp; &nbsp; &nbsp; &nbsp; then (to_char(sysdate, 'YYYY') - to_char(to_date(:dt), 'YYYY')) - 1<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; case when (to_char(sysdate, 'DD'&nbsp; ) - to_char(to_date(:dt), 'DD')) &gt;= 0<br>&nbsp; &nbsp; &nbsp; &nbsp; then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (to_char(sysdate, 'YYYY') - to_char(to_date(:dt), 'YYYY'))<br>&nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (to_char(sysdate, 'YYYY') - to_char(to_date(:dt), 'YYYY')) - 1<br>&nbsp; &nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; end as "y"<br>&nbsp; &nbsp; --<nobr> <wbr></nobr>,(to_char(sysdate, 'MM'&nbsp; ) - to_char(to_date(:dt), 'MM'))&nbsp; &nbsp;as "m",<br>&nbsp; &nbsp; --<nobr> <wbr></nobr>,(to_char(sysdate, 'DD'&nbsp; ) - to_char(to_date(:dt), 'DD'))&nbsp; &nbsp;as "d"<br>from dual</tt></p></div> </blockquote><p>I've tested a number of boundary conditions and it seems correct to me.</p><p>Now, after you stop sniggering, you may show me the function I overlooked that would have done this for me, or point out any obvious bugs.</p> grinder 2007-03-30T09:29:42+00:00 journal Crypt::SSLeay is broken and this is the fix (version 0.51) <p>I just a spent considerable amount of time to get Crypt::SSLeay installed. Far too much time. At first I blamed myself, my host, my OpenSSL installation, perl, everything.</p><p>Finally I searched the web and found the following message:</p><p><nobr>2<wbr></nobr> </p><p>Turns out that there's a bug in the code, and a one-liner patch to SSLeay.xs fixes it. There's even an RT ticket on the matter. Grrr!</p><p>So, if you see the following warning in your build:</p><blockquote><div><p> <tt>SSLeay.xs:252: warning: passing arg 2 of `SSL_set_info_callback' from incompatible pointer type</tt></p></div> </blockquote><p>... and the test dumps core, then patch the source as follows:</p><blockquote><div><p> <tt>--- SSLeay.xs.orig&nbsp; &nbsp; &nbsp; 2002-08-01 17:43:22.000000000 -0400<br>+++ SSLeay.xs&nbsp; &nbsp;2003-01-29 21:41:17.000000000 -0500<br>@@ -109,6 +109,7 @@<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SSLeay_add_all_algorithms();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SSL_load_error_strings();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ERR_load_crypto_strings();<br>+&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SSL_library_init();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bNotFirstTime = 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RAND_seed(buf,sizeof buf);</tt></p></div> </blockquote><p>And now it works, yay!</p> grinder 2006-12-14T12:22:03+00:00 journal Complexity <p>This article was posted to computer.risks recently.</p><blockquote><div><p>Date: Tue, 04 Jul 2006 13:17:36 +0200<br> From: Peter B. Ladkin<br> Subject: B747 freighter crash</p><p>The Canadian TSB have issued the report on the 14 October 2004 crash of a Boeing B747 freighter on takeoff at Halifax airport, Nova Scotia.</p><p>According to a Flight International report by David Kaminski-Morrow (4-10 July 2006, p4), the TSB "says that the crew's misunderstanding of a laptop computer tool for calculating take-off performance led to the accidents. It concludes that the crew unwittingly transferred and used weight data from the aircraft's previous flight while calculating performance criteria for the next take-off. The obsolete data misled the crew to derive incorrect thrust settings and critical speeds for take-off."</p><p>The aircraft failed to lift off after rotation and overran the end of the runway by 250 meters, briefly lifting off but then striking an earth berm, severing the tail section and bringing the aircraft to earth again. All seven crew were killed.</p></div> </blockquote><p>I was deeply moved reading this. If it isn't already evident, piloting a 747 is not just a question of jockeying the thing down to the end of the runway and hitting the juice. So you put your faith in the numbers cranked out by a computer program since there are too many parameters for a person to take into account and deal with, and no-one has the numeracy skills any more to realise that things might be a little out of whack.</p><p>I wonder if the crew had a gut feeling of the unfolding events, based only on the note of the jet engines and feeling of acceleration. No doubt they knew something was amiss when the damned machine refused to haul itself into the sky at the expected time.</p><p>My heart goes out to the families left behind.</p> grinder 2006-07-25T16:14:03+00:00 journal Brute force compilation <p>I ran the following program:</p><blockquote><div><p> <tt>%<nobr> <wbr></nobr>/usr/bin/perl<nobr> <wbr></nobr>/usr/share/dict/words<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 56367.<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 58414.<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 72599.<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 104537.<br>Bareword found where operator expected at<nobr> <wbr></nobr>/usr/share/dict/words line 109459, near "Maarten"<br>&nbsp; (Might be a runaway multi-line MM string starting on line 109455)<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 124219.<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 136839.<br>Bareword found where operator expected at<nobr> <wbr></nobr>/usr/share/dict/words line 161158, near "qere"<br>&nbsp; (Might be a runaway multi-line qq string starting on line 161157)<br>Semicolon seems to be missing at<nobr> <wbr></nobr>/usr/share/dict/words line 167505.<br>Bareword found where operator expected at<nobr> <wbr></nobr>/usr/share/dict/words line 171985, near "sab"<br>&nbsp; (Might be a runaway multi-line ss string starting on line 171980)<br>syntax error at<nobr> <wbr></nobr>/usr/share/dict/words line 4650, near "Alaric<br>alarm<br>"<br>No such class Mya at<nobr> <wbr></nobr>/usr/share/dict/words line 121337, near "muzzy<br>Mwa<br>my<br>Mya"<br>"no" not allowed in expression at<nobr> <wbr></nobr>/usr/share/dict/words line 124778, at end of line<br>No such class Ouranos at<nobr> <wbr></nobr>/usr/share/dict/words line 133287, near "ouphe<br>ouphish<br>our<br>Ouranos"<br>Illegal declaration of subroutine main::subabbot at<nobr> <wbr></nobr>/usr/share/dict/words line 191503.</tt></p></div> </blockquote><p>.. and wondered why I was getting such perplexing errors. Then I realised that I had omitted the name of the script, and was thus executing the word list file.</p><p>This reminds me of the time at school when I tried to compile a COBOL program with a Pascal compiler. I got a thick stack of fan-fold back from the computer room. Page after page of errors. It did nearly manage to parse one line correctly, when it got to</p><blockquote><div><p> <tt>PROCEDURE DIVISION</tt></p></div> </blockquote><p>... but apart from that it recorded several thousand syntax errors. I like it when programs march on stubbornly in the face of impossible odds. It makes me feel smarter than them.</p> grinder 2006-02-15T18:20:02+00:00 journal I suspect that this entry contains worms <p>Clearing out my inbox from the Christmas break, I ran across some virus backscatter with a most entertaining subject:</p><blockquote><div><p> <tt>MailMarshal suspects that this message contains worms</tt></p></div> </blockquote><p>I'm wondering if I should crush a couple of worm tablets and sprinkle the powder onto my keyboard. You just never know.</p> grinder 2006-01-03T10:29:35+00:00 journal Xah Lee on Python <p>It's time for my biannual journal entry!</p><p>Well heh, this makes me laugh. Seems like Xah Lee is now <a href="">trolling the Pythoneers</a>. I don't know if XL still trolls in Perl newsgroups...</p><p>I suppose this is a sign of a language's maturity. Godzilla come back! All is forgiven!</p> grinder 2005-09-01T16:43:12+00:00 journal Cool T-Shirt Idea <p>We were clowning around of the French Perl Mongers mailing list the other day. Someone moaned about the latest Python snipe (actually I think I saw this some time ago, but anyway): <a href=""> Perl Coder</a>.</p><p>So in the spirit of that and a tweak from rafael I came up with:</p><blockquote><div><p> <tt>perl -i -e 's/^\s+//' *.py</tt></p></div> </blockquote><p>Compact and devastating. Well, <i>I</i> thought it was funny<nobr> <wbr></nobr>:)</p> grinder 2004-07-01T17:22:30+00:00 journal Stalling the pipeline in the checkout queue I was in the supermarket the other day after work. I had a number of essentials in my basket and I was itching to get home.<p>Big problem: which queue to choose? Having learnt about Queuing Theory at school, and knowing that single queue-multiple consumer is as efficient as it gets, it's always an agonizing decision. You have to balance a number of factors: how many people in the queue, how many items do people want to buy, do they look impatient or vagued out. It's better to be behind a person buying 10 of one thing, than one item of ten different things. And, although it pains me to admit it, old people are Bad News. Statistically, you'll waste 30 seconds to five minutes with them in front of you.</p><p>So I was pondering this the other day, and reflecting on my worldview, how I tend to algorithmatise things (figuring out the shortest path between the four shops I need to go to, establishing contigency plans in case a shop doesn't have a product I need, that sort of stuff. When house-cleaning I try to keep my hands full. I hate going into room A to fetch something for room B, and realising there was something in room B which should be tidied away in room A). Geeking out, basically.</p><p>And as I stood there ruminating on this, I was idly watching the woman at the front of the line, and became more and more alarmed. She was just stacking up the products that the cashier swiped...<i>but not putting them into bags.</i> I couldn't figure out what she was doing, but figured it was bad news for me. And on and on it went, until the cashier had checked out every last item. Then she handed over her credit card, had it swiped, punched in her pin, and only once she had received her docket did she begin to bag up the stuff she'd bought. And I thought "You f5cking moron: can't you deal with asynchronous events?" Because the cashier couldn't start checking out the items of the next person until she'd cleared the decks. Which took a non-trivial amount of time, during which no other work could be done.</p><p>Meantime I note that the people who were at the ends of the other queues are now close to being served, and I've still got two people in front of me. But I'm in too deep at this point to bear the cost of cutting my losses and requeuing on another line.</p><p>The next person went through without a hitch: a few items, had cash ready, out straight away.</p><p>Then the person in front of me went through. Seemed to be okay: started bagging up the goods as soon as they came through, but she had a fair number of things to buy. Then it turns out that she has a Method. All the fruit goes together, the stuff that requires Refrigeration goes together, tins kept apart from packets and so on. And the cashier is done quickly and announces the price. But does she do anything? Noooooooooo! She just keeps putting stuff in bags. And the cashier, who is polite (the Customer is always Right and all that) says nothing.</p><p>At this point I just take a deep breath and resign myself. The people who were at the ends of the other queues are all long since gone. At times like this I can't help thinking that a lot of what we learn in Computer Science is applicable to the Real World. And one of the cardinal sins is stalling the pipeline. When you have people queued up to do something, you want to get in and get out as fast as possible, just like an instruction on a CPU. Because wait states are just time lost. Gone, never to come back.</p><p>I really, <i>really</i> hate when that happens.</p> grinder 2002-08-25T22:07:37+00:00 journal Do's and Don'ts <p>Here is a list of Do's and Don'ts for enlightened program development.</p><ul> <li>First off, when the usual person in charge of backups takes Friday off, <b>do not</b> forget to insert a tape into the DLT tape drive so that Friday's files get backed up.</li><li> <b>Do not</b> work on a new version of an production script by running <tt>cp `which important-script` . </tt> rather, rename it to something else.</li><li> <b>Do not</b> use <tt>cp</tt> in a different session window to copy output datafiles from said script from one directory to another, simply because the second directory happens to be accessible from a Samba share so that you can import the data into Excel.</li><li> <b>Do not</b> get confused about which window you are in and re-run the <tt>cp</tt> command using <tt>!cp</tt>, thereby reinitialising the contents of your updated script back to how it was before you started hacking on it two days ago.</li><li> <b>Do</b> alias <tt>cp</tt> to <tt>cp -i</tt>. It's not just for <tt>root</tt>!</li><li> <b>Do</b> print out the script on hard-copy from time to time, even if it was Friday midday, because at least then you don't lose quite as much work.</li><li> <b>Do</b> get a better version of <tt>vi</tt> than Solaris' shi^Wbraindead implementation. At least one that creates ~backup files.</li><li> <b>Do</b> know how to touch-type, so that at least rekeying 12 pages of Perl code doesn't take so long, even if that is a meagre consolation.</li></ul><p>Man I hate when that happens.</p> grinder 2002-02-11T17:46:11+00:00 journal Hello, world If everybody else is doing it, why shouldn't I?<p>For Christmas, I got a kidney stone. Eeeeeeew, it really hurt, like, the pain was so bad that I was vomiting spontaneously. Not fun.</p><p>But then I got better and back to work, with an inbox a mile look. Various things at work were broken and I had to get them up to speed. In the past 10 days I have</p><ul> <li>Upgraded Apache from 1.3.9 to 1.3.22.</li> <li>Upgraded from 2.56 to 2.79.</li> <li>Wrote a script that extracts information from our tracking database to the accounting system.</li> <li>Updated various documents in our bofh tech library.</li> <li>Wrote a web script to allow people to cook^Wmodify financial details in the billings database.</li> <li>Set up a couple of printers on the network.</li> <li>Figured out why the primary DNS server was refusing ssh connections.</li> <li>Got the Frankfurt office up and running (they had run out of disk space).</li> <li>Posted a snippet to Perl Monks, only to have Merlyn point out that I had successfully reinvented CGI-&gt;Dump. Man I hate when that happens.</li> </ul> grinder 2002-01-24T14:53:13+00:00 journal